js-sha3
Advanced tools
Comparing version 0.4.1 to 0.5.1
{ | ||
"name": "js-sha3", | ||
"version": "0.4.1", | ||
"version": "0.5.1", | ||
"main": ["src/sha3.js"], | ||
@@ -5,0 +5,0 @@ "ignore": [ |
@@ -0,1 +1,9 @@ | ||
# v0.5.1 / 2015-10-27 | ||
* Update package.json and bower.json. | ||
# v0.5.0 / 2015-09-23 | ||
* Support update interface. | ||
# v0.4.1 / 2015-09-18 | ||
@@ -2,0 +10,0 @@ |
{ | ||
"name": "js-sha3", | ||
"version": "0.4.1", | ||
"version": "0.5.1", | ||
"description": "A simple SHA-3 / Keccak / Shake hash function for JavaScript supports UTF-8 encoding.", | ||
@@ -5,0 +5,0 @@ "main": "src/sha3.js", |
# js-sha3 | ||
[![Build Status](https://travis-ci.org/emn178/js-sha3.svg?branch=master)](https://travis-ci.org/emn178/js-sha3) | ||
[![Coverage Status](https://coveralls.io/repos/emn178/js-sha3/badge.svg?branch=master)](https://coveralls.io/r/emn178/js-sha3?branch=master) | ||
[![Coverage Status](https://coveralls.io/repos/emn178/js-sha3/badge.svg?branch=master)](https://coveralls.io/r/emn178/js-sha3?branch=master) | ||
A simple SHA-3 / Keccak / Shake hash function for JavaScript supports UTF-8 encoding. | ||
@@ -51,2 +53,19 @@ | ||
var buffer = keccak_224.array('Message to hash'); | ||
// update hash | ||
sha3_512.update('Message ').update('to ').update('hash').hex(); | ||
// specify shake output bits at first update | ||
shake_128.update('Message ', 256).update('to ').update('hash').hex(); | ||
// or to use create | ||
var hash = sha3_512.create(); | ||
hash.update('...'); | ||
hash.update('...'); | ||
hash.hex(); | ||
// specify shake output bits when creating | ||
var hash = shake_128.create(256); | ||
hash.update('...'); | ||
hash.update('...'); | ||
hash.hex(); | ||
``` | ||
@@ -53,0 +72,0 @@ If you use node.js, you should require the module first: |
302
src/sha3.js
/* | ||
* js-sha3 v0.4.1 | ||
* js-sha3 v0.5.1 | ||
* https://github.com/emn178/js-sha3 | ||
@@ -34,14 +34,44 @@ * | ||
var createMethod = function(bits, padding, outputType) { | ||
var createOutputMethod = function(bits, padding, outputType) { | ||
return function(message) { | ||
return keccak(message, bits, padding, bits, outputType); | ||
return new Keccak(bits, padding, bits).update(message)[outputType](); | ||
} | ||
}; | ||
var createShakeMethod = function(bits, padding, outputType) { | ||
var createShakeOutputMethod = function(bits, padding, outputType) { | ||
return function(message, outputBits) { | ||
return keccak(message, bits, padding, outputBits, outputType); | ||
return new Keccak(bits, padding, outputBits).update(message)[outputType](); | ||
} | ||
}; | ||
var createMethod = function(bits, padding) { | ||
var method = createOutputMethod(bits, padding, 'hex'); | ||
method.create = function() { | ||
return new Keccak(bits, padding, bits); | ||
}; | ||
method.update = function(message) { | ||
return method.create().update(message); | ||
}; | ||
for(var i = 0;i < OUTPUT_TYPES.length;++i) { | ||
var type = OUTPUT_TYPES[i]; | ||
method[type] = createOutputMethod(bits, padding, type); | ||
} | ||
return method; | ||
}; | ||
var createShakeMethod = function(bits, padding) { | ||
var method = createShakeOutputMethod(bits, padding, 'hex'); | ||
method.create = function(outputBits) { | ||
return new Keccak(bits, padding, outputBits); | ||
}; | ||
method.update = function(message, outputBits) { | ||
return method.create(outputBits).update(message); | ||
}; | ||
for(var i = 0;i < OUTPUT_TYPES.length;++i) { | ||
var type = OUTPUT_TYPES[i]; | ||
method[type] = createShakeOutputMethod(bits, padding, type); | ||
} | ||
return method; | ||
}; | ||
var algorithms = [ | ||
@@ -53,3 +83,3 @@ {name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod}, | ||
var blocks = [], s = [], methods = {}; | ||
var methods = {}; | ||
@@ -61,14 +91,26 @@ for(var i = 0;i < algorithms.length;++i) { | ||
for(var j = 0;j < bits.length;++j) { | ||
(function(algorithm, bits) { | ||
var method = createMethod(bits, algorithm.padding, 'hex'); | ||
methods[algorithm.name +'_' + bits] = method; | ||
for(var k = 0;k < OUTPUT_TYPES.length;++k) { | ||
var type = OUTPUT_TYPES[k]; | ||
method[type] = createMethod(bits, algorithm.padding, type); | ||
} | ||
})(algorithm, bits[j]); | ||
var method = algorithm.createMethod(bits[j], algorithm.padding); | ||
methods[algorithm.name +'_' + bits[j]] = method; | ||
} | ||
} | ||
var keccak = function(message, bits, padding, outputBits, outputType) { | ||
function Keccak(bits, padding, outputBits) { | ||
this.blocks = []; | ||
this.s = []; | ||
this.padding = padding; | ||
this.outputBits = outputBits; | ||
this.reset = true; | ||
this.block = 0; | ||
this.start = 0; | ||
this.blockCount = (1600 - (bits << 1)) >> 5; | ||
this.byteCount = this.blockCount << 2; | ||
this.outputBlocks = outputBits >> 5; | ||
this.extraBytes = (outputBits & 31) >> 3; | ||
for(var i = 0;i < 50;++i) { | ||
this.s[i] = 0; | ||
} | ||
}; | ||
Keccak.prototype.update = function(message) { | ||
var notString = typeof(message) != 'string'; | ||
@@ -78,24 +120,19 @@ if(notString && message.constructor == root.ArrayBuffer) { | ||
} | ||
var block, code, end = false, index = 0, start = 0, length = message.length, | ||
i, j, h; | ||
var blockCount = (1600 - (bits << 1)) >> 5; | ||
var byteCount = blockCount << 2; | ||
for(i = 0;i < 50;++i) { | ||
s[i] = 0; | ||
} | ||
block = 0; | ||
do { | ||
blocks[0] = block; | ||
for(i = 1;i < blockCount + 1;++i) { | ||
blocks[i] = 0; | ||
var length = message.length, blocks = this.blocks, byteCount = this.byteCount, | ||
blockCount = this.blockCount, index = 0, s = this.s, i, code; | ||
while(index < length) { | ||
if(this.reset) { | ||
this.reset = false; | ||
blocks[0] = this.block; | ||
for(i = 1;i < blockCount + 1;++i) { | ||
blocks[i] = 0; | ||
} | ||
} | ||
if(notString) { | ||
for (i = start;index < length && i < byteCount; ++index) { | ||
for (i = this.start;index < length && i < byteCount; ++index) { | ||
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; | ||
} | ||
} else { | ||
for (i = start;index < length && i < byteCount; ++index) { | ||
for (i = this.start;index < length && i < byteCount; ++index) { | ||
code = message.charCodeAt(index); | ||
@@ -120,105 +157,131 @@ if (code < 0x80) { | ||
} | ||
start = i - byteCount; | ||
if(index == length) { | ||
blocks[i >> 2] |= padding[i & 3]; | ||
++index; | ||
this.lastByteIndex = i; | ||
if(i >= byteCount) { | ||
this.start = i - byteCount; | ||
this.block = blocks[blockCount]; | ||
for(i = 0;i < blockCount;++i) { | ||
s[i] ^= blocks[i]; | ||
} | ||
f(s); | ||
this.reset = true; | ||
} else { | ||
this.start = i; | ||
} | ||
block = blocks[blockCount]; | ||
if(index > length && i < byteCount) { | ||
blocks[blockCount - 1] |= 0x80000000; | ||
end = true; | ||
} | ||
} | ||
return this; | ||
}; | ||
for(i = 0;i < blockCount;++i) { | ||
s[i] ^= blocks[i]; | ||
Keccak.prototype.finalize = function() { | ||
var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s; | ||
blocks[i >> 2] |= this.padding[i & 3]; | ||
if(this.lastByteIndex == this.byteCount) { | ||
blocks[0] = blocks[blockCount]; | ||
for(i = 1;i < blockCount + 1;++i) { | ||
blocks[i] = 0; | ||
} | ||
} | ||
blocks[blockCount - 1] |= 0x80000000; | ||
for(i = 0;i < blockCount;++i) { | ||
s[i] ^= blocks[i]; | ||
} | ||
f(s); | ||
}; | ||
f(); | ||
} while(!end); | ||
Keccak.prototype.toString = Keccak.prototype.hex = function() { | ||
this.finalize(); | ||
var outputBlocks = outputBits >> 5; | ||
var extraBytes = (outputBits & 31) >> 3; | ||
j = 0, i = 0; | ||
if(outputType == 'buffer') { | ||
var bytes = outputBits >> 3; | ||
var buffer; | ||
if(extraBytes) { | ||
buffer = new ArrayBuffer((outputBlocks + 1) << 2); | ||
} else { | ||
buffer = new ArrayBuffer(bytes); | ||
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, | ||
extraBytes = this.extraBytes, i = 0, j = 0; | ||
var hex = '', block; | ||
while(j < outputBlocks) { | ||
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { | ||
block = s[i]; | ||
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] + | ||
HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] + | ||
HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] + | ||
HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F]; | ||
} | ||
var array = new Uint32Array(buffer); | ||
while(j < outputBlocks) { | ||
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { | ||
array[j] = s[i]; | ||
} | ||
if(j % blockCount == 0) { | ||
f(); | ||
} | ||
if(j % blockCount == 0) { | ||
f(s); | ||
} | ||
if(extraBytes) { | ||
array[i] = s[i]; | ||
buffer = buffer.slice(0, bytes); | ||
} | ||
if(extraBytes) { | ||
block = s[i]; | ||
if(extraBytes > 0) { | ||
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F]; | ||
} | ||
return buffer; | ||
} else if(outputType == 'array') { | ||
var array = [], offset; | ||
while(j < outputBlocks) { | ||
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { | ||
offset = j << 2; | ||
h = s[i]; | ||
array[offset] = h & 0xFF; | ||
array[offset + 1] = (h >> 8) & 0xFF; | ||
array[offset + 2] = (h >> 16) & 0xFF; | ||
array[offset + 3] = (h >> 24) & 0xFF; | ||
} | ||
if(j % blockCount == 0) { | ||
f(); | ||
} | ||
if(extraBytes > 1) { | ||
hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F]; | ||
} | ||
if(extraBytes) { | ||
offset = j << 2; | ||
h = s[i]; | ||
if(extraBytes > 0) { | ||
array[offset] = h & 0xFF; | ||
} | ||
if(extraBytes > 1) { | ||
array[offset + 1] = (h >> 8) & 0xFF; | ||
} | ||
if(extraBytes > 2) { | ||
array[offset + 2] = (h >> 16) & 0xFF; | ||
} | ||
if(extraBytes > 2) { | ||
hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F]; | ||
} | ||
return array; | ||
} | ||
return hex; | ||
}; | ||
Keccak.prototype.buffer = function() { | ||
this.finalize(); | ||
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, | ||
extraBytes = this.extraBytes, i = 0, j = 0; | ||
var bytes = this.outputBits >> 3; | ||
var buffer; | ||
if(extraBytes) { | ||
buffer = new ArrayBuffer((outputBlocks + 1) << 2); | ||
} else { | ||
var hex = ''; | ||
while(j < outputBlocks) { | ||
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { | ||
h = s[i]; | ||
hex += HEX_CHARS[(h >> 4) & 0x0F] + HEX_CHARS[h & 0x0F] + | ||
HEX_CHARS[(h >> 12) & 0x0F] + HEX_CHARS[(h >> 8) & 0x0F] + | ||
HEX_CHARS[(h >> 20) & 0x0F] + HEX_CHARS[(h >> 16) & 0x0F] + | ||
HEX_CHARS[(h >> 28) & 0x0F] + HEX_CHARS[(h >> 24) & 0x0F]; | ||
} | ||
if(j % blockCount == 0) { | ||
f(); | ||
} | ||
buffer = new ArrayBuffer(bytes); | ||
} | ||
var array = new Uint32Array(buffer); | ||
while(j < outputBlocks) { | ||
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { | ||
array[j] = s[i]; | ||
} | ||
if(extraBytes) { | ||
h = s[i]; | ||
if(extraBytes > 0) { | ||
hex += HEX_CHARS[(h >> 4) & 0x0F] + HEX_CHARS[h & 0x0F]; | ||
} | ||
if(extraBytes > 1) { | ||
hex += HEX_CHARS[(h >> 12) & 0x0F] + HEX_CHARS[(h >> 8) & 0x0F]; | ||
} | ||
if(extraBytes > 2) { | ||
hex += HEX_CHARS[(h >> 20) & 0x0F] + HEX_CHARS[(h >> 16) & 0x0F]; | ||
} | ||
if(j % blockCount == 0) { | ||
f(s); | ||
} | ||
return hex; | ||
} | ||
if(extraBytes) { | ||
array[i] = s[i]; | ||
buffer = buffer.slice(0, bytes); | ||
} | ||
return buffer; | ||
}; | ||
var f = function() { | ||
Keccak.prototype.digest = Keccak.prototype.array = function() { | ||
this.finalize(); | ||
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, | ||
extraBytes = this.extraBytes, i = 0, j = 0; | ||
var array = [], offset, block; | ||
while(j < outputBlocks) { | ||
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { | ||
offset = j << 2; | ||
block = s[i]; | ||
array[offset] = block & 0xFF; | ||
array[offset + 1] = (block >> 8) & 0xFF; | ||
array[offset + 2] = (block >> 16) & 0xFF; | ||
array[offset + 3] = (block >> 24) & 0xFF; | ||
} | ||
if(j % blockCount == 0) { | ||
f(s); | ||
} | ||
} | ||
if(extraBytes) { | ||
offset = j << 2; | ||
block = s[i]; | ||
if(extraBytes > 0) { | ||
array[offset] = block & 0xFF; | ||
} | ||
if(extraBytes > 1) { | ||
array[offset + 1] = (block >> 8) & 0xFF; | ||
} | ||
if(extraBytes > 2) { | ||
array[offset + 2] = (block >> 16) & 0xFF; | ||
} | ||
} | ||
return array; | ||
}; | ||
var f = function(s) { | ||
var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, | ||
@@ -408,3 +471,2 @@ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, | ||
if(!root.JS_SHA3_TEST && NODE_JS) { | ||
@@ -411,0 +473,0 @@ module.exports = methods; |
28766
457
285