mirror of
https://github.com/emn178/js-sha3.git
synced 2026-08-12 19:41:36 +08:00
Support update interface.
This commit is contained in:
+193
-131
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* js-sha3 v0.4.1
|
||||
* js-sha3 v0.5.0
|
||||
* https://github.com/emn178/js-sha3
|
||||
*
|
||||
* Copyright 2015, emn178@gmail.com
|
||||
@@ -31,69 +31,106 @@
|
||||
var SHAKE_BITS = [128, 256];
|
||||
var OUTPUT_TYPES = ['hex', 'buffer', 'array'];
|
||||
|
||||
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 = [
|
||||
{name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod},
|
||||
{name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod},
|
||||
{name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod}
|
||||
];
|
||||
|
||||
var blocks = [], s = [], methods = {};
|
||||
var methods = {};
|
||||
|
||||
for(var i = 0;i < algorithms.length;++i) {
|
||||
var algorithm = algorithms[i];
|
||||
var bits = algorithm.bits;
|
||||
var createMethod = algorithm.createMethod;
|
||||
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(i = 0;i < 50;++i) {
|
||||
this.s[i] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
Keccak.prototype.update = function(message) {
|
||||
var notString = typeof(message) != 'string';
|
||||
if(notString && message.constructor == root.ArrayBuffer) {
|
||||
message = new Uint8Array(message);
|
||||
}
|
||||
|
||||
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);
|
||||
if (code < 0x80) {
|
||||
blocks[i >> 2] |= code << SHIFT[i++ & 3];
|
||||
@@ -113,109 +150,135 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
start = i - byteCount;
|
||||
if(index == length) {
|
||||
blocks[i >> 2] |= padding[i & 3];
|
||||
++index;
|
||||
}
|
||||
block = blocks[blockCount];
|
||||
if(index > length && i < byteCount) {
|
||||
blocks[blockCount - 1] |= 0x80000000;
|
||||
end = true;
|
||||
}
|
||||
|
||||
for(i = 0;i < blockCount;++i) {
|
||||
s[i] ^= blocks[i];
|
||||
}
|
||||
|
||||
f();
|
||||
} while(!end);
|
||||
|
||||
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);
|
||||
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 {
|
||||
buffer = new ArrayBuffer(bytes);
|
||||
this.start = i;
|
||||
}
|
||||
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(extraBytes) {
|
||||
array[i] = s[i];
|
||||
buffer = buffer.slice(0, bytes);
|
||||
}
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
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];
|
||||
}
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
var f = function() {
|
||||
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);
|
||||
};
|
||||
|
||||
Keccak.prototype.toString = Keccak.prototype.hex = function() {
|
||||
this.finalize();
|
||||
|
||||
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];
|
||||
}
|
||||
if(j % blockCount == 0) {
|
||||
f(s);
|
||||
}
|
||||
}
|
||||
if(extraBytes) {
|
||||
block = s[i];
|
||||
if(extraBytes > 0) {
|
||||
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F];
|
||||
}
|
||||
if(extraBytes > 1) {
|
||||
hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F];
|
||||
}
|
||||
if(extraBytes > 2) {
|
||||
hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F];
|
||||
}
|
||||
}
|
||||
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 {
|
||||
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(j % blockCount == 0) {
|
||||
f(s);
|
||||
}
|
||||
}
|
||||
if(extraBytes) {
|
||||
array[i] = s[i];
|
||||
buffer = buffer.slice(0, bytes);
|
||||
}
|
||||
return buffer;
|
||||
};
|
||||
|
||||
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,
|
||||
b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17,
|
||||
b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33,
|
||||
@@ -400,7 +463,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!root.JS_SHA3_TEST && NODE_JS) {
|
||||
module.exports = methods;
|
||||
} else if(root) {
|
||||
|
||||
Reference in New Issue
Block a user