804 lines
28 KiB
JavaScript
804 lines
28 KiB
JavaScript
|
/*
|
||
|
* @project: TERA
|
||
|
* @version: Development (beta)
|
||
|
* @license: MIT (not for evil)
|
||
|
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
|
||
|
* Web: https://terafoundation.org
|
||
|
* Twitter: https://twitter.com/terafoundation
|
||
|
* Telegram: https://t.me/terafoundation
|
||
|
*/
|
||
|
|
||
|
(function ()
|
||
|
{
|
||
|
'use strict';
|
||
|
var root = typeof window === 'object' ? window : {};
|
||
|
var NODE_JS = !root.JS_SHA3_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
|
||
|
if(NODE_JS && !root.RUN_NW_CLIENT)
|
||
|
{
|
||
|
root = global;
|
||
|
}
|
||
|
if(root.RUN_CLIENT)
|
||
|
{
|
||
|
root = window;
|
||
|
}
|
||
|
var COMMON_JS = !root.JS_SHA3_NO_COMMON_JS && typeof module === 'object' && module.exports;
|
||
|
var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
|
||
|
var HEX_CHARS = '0123456789abcdef'.split('');
|
||
|
var SHAKE_PADDING = [31, 7936, 2031616, 520093696];
|
||
|
var CSHAKE_PADDING = [4, 1024, 262144, 67108864];
|
||
|
var KECCAK_PADDING = [1, 256, 65536, 16777216];
|
||
|
var PADDING = [6, 1536, 393216, 100663296];
|
||
|
var SHIFT = [0, 8, 16, 24];
|
||
|
var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649, 0, 2147516545, 2147483648, 32777,
|
||
|
2147483648, 138, 0, 136, 0, 2147516425, 0, 2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771, 2147483648,
|
||
|
32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648, 2147516545, 2147483648, 32896, 2147483648, 2147483649,
|
||
|
0, 2147516424, 2147483648];
|
||
|
var BITS = [224, 256, 384, 512];
|
||
|
var SHAKE_BITS = [128, 256];
|
||
|
var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array'];
|
||
|
var CSHAKE_BYTEPAD = {'128':168, '256':136};
|
||
|
if(root.JS_SHA3_NO_NODE_JS || !Array.isArray)
|
||
|
{
|
||
|
Array.isArray = function (obj)
|
||
|
{
|
||
|
return Object.prototype.toString.call(obj) === '[object Array]';
|
||
|
};
|
||
|
}
|
||
|
var createOutputMethod = function (bits,padding,outputType)
|
||
|
{
|
||
|
return function (message)
|
||
|
{
|
||
|
return new Keccak(bits, padding, bits).update(message)[outputType]();
|
||
|
};
|
||
|
};
|
||
|
var createShakeOutputMethod = function (bits,padding,outputType)
|
||
|
{
|
||
|
return function (message,outputBits)
|
||
|
{
|
||
|
return new Keccak(bits, padding, outputBits).update(message)[outputType]();
|
||
|
};
|
||
|
};
|
||
|
var createCshakeOutputMethod = function (bits,padding,outputType)
|
||
|
{
|
||
|
return function (message,outputBits,n,s)
|
||
|
{
|
||
|
return methods['cshake' + bits].update(message, outputBits, n, s)[outputType]();
|
||
|
};
|
||
|
};
|
||
|
var createKmacOutputMethod = function (bits,padding,outputType)
|
||
|
{
|
||
|
return function (key,message,outputBits,s)
|
||
|
{
|
||
|
return methods['kmac' + bits].update(key, message, outputBits, s)[outputType]();
|
||
|
};
|
||
|
};
|
||
|
var createOutputMethods = function (method,createMethod,bits,padding)
|
||
|
{
|
||
|
for(var i = 0; i < OUTPUT_TYPES.length; ++i)
|
||
|
{
|
||
|
var type = OUTPUT_TYPES[i];
|
||
|
method[type] = createMethod(bits, padding, type);
|
||
|
}
|
||
|
return method;
|
||
|
};
|
||
|
var createMethod = function (bits,padding,outputs)
|
||
|
{
|
||
|
var method = createOutputMethod(bits, padding, outputs);
|
||
|
method.create = function ()
|
||
|
{
|
||
|
return new Keccak(bits, padding, bits);
|
||
|
};
|
||
|
method.update = function (message)
|
||
|
{
|
||
|
return method.create().update(message);
|
||
|
};
|
||
|
return createOutputMethods(method, createOutputMethod, bits, padding);
|
||
|
};
|
||
|
var createMethodArray = function (bits,padding)
|
||
|
{
|
||
|
var method = createOutputMethod(bits, padding, 'array');
|
||
|
method.create = function ()
|
||
|
{
|
||
|
return new Keccak(bits, padding, bits);
|
||
|
};
|
||
|
method.update = function (message)
|
||
|
{
|
||
|
return method.create().update(message);
|
||
|
};
|
||
|
return createOutputMethods(method, createOutputMethod, bits, padding);
|
||
|
};
|
||
|
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);
|
||
|
};
|
||
|
return createOutputMethods(method, createShakeOutputMethod, bits, padding);
|
||
|
};
|
||
|
var createCshakeMethod = function (bits,padding)
|
||
|
{
|
||
|
var w = CSHAKE_BYTEPAD[bits];
|
||
|
var method = createCshakeOutputMethod(bits, padding, 'hex');
|
||
|
method.create = function (outputBits,n,s)
|
||
|
{
|
||
|
if(!n && !s)
|
||
|
{
|
||
|
return methods['shake' + bits].create(outputBits);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return new Keccak(bits, padding, outputBits).bytepad([n, s], w);
|
||
|
}
|
||
|
};
|
||
|
method.update = function (message,outputBits,n,s)
|
||
|
{
|
||
|
return method.create(outputBits, n, s).update(message);
|
||
|
};
|
||
|
return createOutputMethods(method, createCshakeOutputMethod, bits, padding);
|
||
|
};
|
||
|
var createKmacMethod = function (bits,padding)
|
||
|
{
|
||
|
var w = CSHAKE_BYTEPAD[bits];
|
||
|
var method = createKmacOutputMethod(bits, padding, 'hex');
|
||
|
method.create = function (key,outputBits,s)
|
||
|
{
|
||
|
return new Kmac(bits, padding, outputBits).bytepad(['KMAC', s], w).bytepad([key], w);
|
||
|
};
|
||
|
method.update = function (key,message,outputBits,s)
|
||
|
{
|
||
|
return method.create(key, outputBits, s).update(message);
|
||
|
};
|
||
|
return createOutputMethods(method, createKmacOutputMethod, bits, padding);
|
||
|
};
|
||
|
var algorithms = [{name:'keccak', padding:KECCAK_PADDING, bits:BITS, createMethod:createMethod}, {name:'sha3', padding:PADDING,
|
||
|
bits:BITS, createMethod:createMethod, outputs:'hex'}, {name:'sha3_array', padding:PADDING, bits:BITS, createMethod:createMethod,
|
||
|
outputs:'array'}, {name:'sha3_buf', padding:PADDING, bits:BITS, createMethod:createMethod, outputs:'buffer'}, {name:'shake',
|
||
|
padding:SHAKE_PADDING, bits:SHAKE_BITS, createMethod:createShakeMethod}, {name:'cshake', padding:CSHAKE_PADDING, bits:SHAKE_BITS,
|
||
|
createMethod:createCshakeMethod}, {name:'kmac', padding:CSHAKE_PADDING, bits:SHAKE_BITS, createMethod:createKmacMethod}];
|
||
|
var methods = {}, methodNames = [];
|
||
|
for(var i = 0; i < algorithms.length; ++i)
|
||
|
{
|
||
|
var algorithm = algorithms[i];
|
||
|
var bits = algorithm.bits;
|
||
|
for(var j = 0; j < bits.length; ++j)
|
||
|
{
|
||
|
var methodName = algorithm.name + '_' + bits[j];
|
||
|
methodNames.push(methodName);
|
||
|
methods[methodName] = algorithm.createMethod(bits[j], algorithm.padding, algorithm.outputs);
|
||
|
if(algorithm.name !== 'sha3')
|
||
|
{
|
||
|
var newMethodName = algorithm.name + bits[j];
|
||
|
methodNames.push(newMethodName);
|
||
|
methods[newMethodName] = methods[methodName];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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';
|
||
|
if(notString && message.constructor === root.ArrayBuffer)
|
||
|
{
|
||
|
TO_ERROR_LOG("SHA3", 10, 'ERROR: Error type ArrayBuffer, use Uint8Array instead!');
|
||
|
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||
|
}
|
||
|
var length = message.length;
|
||
|
if(notString)
|
||
|
{
|
||
|
if(typeof length !== 'number' || !Array.isArray(message) && !(ARRAY_BUFFER && ArrayBuffer.isView(message)))
|
||
|
{
|
||
|
TO_ERROR_LOG("SHA3", 20, 'ERROR: Input is invalid type, message=' + JSON.stringify(message));
|
||
|
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||
|
}
|
||
|
}
|
||
|
var 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 = this.start; index < length && i < byteCount; ++index)
|
||
|
{
|
||
|
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(i = this.start; index < length && i < byteCount; ++index)
|
||
|
{
|
||
|
code = message.charCodeAt(index);
|
||
|
if(code < 0x80)
|
||
|
{
|
||
|
blocks[i >> 2] |= code << SHIFT[i++ & 3];
|
||
|
}
|
||
|
else
|
||
|
if(code < 0x800)
|
||
|
{
|
||
|
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
|
||
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||
|
}
|
||
|
else
|
||
|
if(code < 0xd800 || code >= 0xe000)
|
||
|
{
|
||
|
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
|
||
|
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
|
||
|
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
|
||
|
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
|
||
|
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
return this;
|
||
|
};
|
||
|
Keccak.prototype.encode = function (x,right)
|
||
|
{
|
||
|
var o = x & 255, n = 1;
|
||
|
var bytes = [o];
|
||
|
x = x >> 8;
|
||
|
o = x & 255;
|
||
|
while(o > 0)
|
||
|
{
|
||
|
bytes.unshift(o);
|
||
|
x = x >> 8;
|
||
|
o = x & 255;
|
||
|
++n;
|
||
|
}
|
||
|
if(right)
|
||
|
{
|
||
|
bytes.push(n);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bytes.unshift(n);
|
||
|
}
|
||
|
this.update(bytes);
|
||
|
return bytes.length;
|
||
|
};
|
||
|
Keccak.prototype.encodeString = function (str)
|
||
|
{
|
||
|
str = str || '';
|
||
|
var notString = typeof str !== 'string';
|
||
|
if(notString && str.constructor === root.ArrayBuffer)
|
||
|
{
|
||
|
str = new Uint8Array(str);
|
||
|
}
|
||
|
var length = str.length;
|
||
|
if(notString)
|
||
|
{
|
||
|
if(typeof length !== 'number' || !Array.isArray(str) && !(ARRAY_BUFFER && ArrayBuffer.isView(str)))
|
||
|
{
|
||
|
TO_ERROR_LOG("SHA3", 30, 'ERROR: Input is invalid type, str=' + JSON.stringify(str));
|
||
|
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||
|
}
|
||
|
}
|
||
|
var bytes = 0;
|
||
|
if(notString)
|
||
|
{
|
||
|
bytes = length;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(var i = 0; i < str.length; ++i)
|
||
|
{
|
||
|
var code = str.charCodeAt(i);
|
||
|
if(code < 0x80)
|
||
|
{
|
||
|
bytes += 1;
|
||
|
}
|
||
|
else
|
||
|
if(code < 0x800)
|
||
|
{
|
||
|
bytes += 2;
|
||
|
}
|
||
|
else
|
||
|
if(code < 0xd800 || code >= 0xe000)
|
||
|
{
|
||
|
bytes += 3;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));
|
||
|
bytes += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
bytes += this.encode(bytes * 8);
|
||
|
this.update(str);
|
||
|
return bytes;
|
||
|
};
|
||
|
Keccak.prototype.bytepad = function (strs,w)
|
||
|
{
|
||
|
var bytes = this.encode(w);
|
||
|
for(var i = 0; i < strs.length; ++i)
|
||
|
{
|
||
|
bytes += this.encodeString(strs[i]);
|
||
|
}
|
||
|
var paddingBytes = w - bytes % w;
|
||
|
var zeros = [];
|
||
|
zeros.length = paddingBytes;
|
||
|
this.update(zeros);
|
||
|
return this;
|
||
|
};
|
||
|
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);
|
||
|
i = 0;
|
||
|
}
|
||
|
}
|
||
|
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.arrayBuffer = 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.buffer = Keccak.prototype.arrayBuffer;
|
||
|
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;
|
||
|
};
|
||
|
|
||
|
function Kmac(bits,padding,outputBits)
|
||
|
{
|
||
|
Keccak.call(this, bits, padding, outputBits);
|
||
|
};
|
||
|
Kmac.prototype = new Keccak();
|
||
|
Kmac.prototype.finalize = function ()
|
||
|
{
|
||
|
this.encode(this.outputBits, true);
|
||
|
return Keccak.prototype.finalize.call(this);
|
||
|
};
|
||
|
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, b34, b35, b36, b37, b38, b39, b40,
|
||
|
b41, b42, b43, b44, b45, b46, b47, b48, b49;
|
||
|
for(n = 0; n < 48; n += 2)
|
||
|
{
|
||
|
c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
|
||
|
c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
|
||
|
c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42];
|
||
|
c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43];
|
||
|
c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44];
|
||
|
c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45];
|
||
|
c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46];
|
||
|
c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47];
|
||
|
c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48];
|
||
|
c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49];
|
||
|
h = c8 ^ ((c2 << 1) | (c3 >>> 31));
|
||
|
l = c9 ^ ((c3 << 1) | (c2 >>> 31));
|
||
|
s[0] ^= h;
|
||
|
s[1] ^= l;
|
||
|
s[10] ^= h;
|
||
|
s[11] ^= l;
|
||
|
s[20] ^= h;
|
||
|
s[21] ^= l;
|
||
|
s[30] ^= h;
|
||
|
s[31] ^= l;
|
||
|
s[40] ^= h;
|
||
|
s[41] ^= l;
|
||
|
h = c0 ^ ((c4 << 1) | (c5 >>> 31));
|
||
|
l = c1 ^ ((c5 << 1) | (c4 >>> 31));
|
||
|
s[2] ^= h;
|
||
|
s[3] ^= l;
|
||
|
s[12] ^= h;
|
||
|
s[13] ^= l;
|
||
|
s[22] ^= h;
|
||
|
s[23] ^= l;
|
||
|
s[32] ^= h;
|
||
|
s[33] ^= l;
|
||
|
s[42] ^= h;
|
||
|
s[43] ^= l;
|
||
|
h = c2 ^ ((c6 << 1) | (c7 >>> 31));
|
||
|
l = c3 ^ ((c7 << 1) | (c6 >>> 31));
|
||
|
s[4] ^= h;
|
||
|
s[5] ^= l;
|
||
|
s[14] ^= h;
|
||
|
s[15] ^= l;
|
||
|
s[24] ^= h;
|
||
|
s[25] ^= l;
|
||
|
s[34] ^= h;
|
||
|
s[35] ^= l;
|
||
|
s[44] ^= h;
|
||
|
s[45] ^= l;
|
||
|
h = c4 ^ ((c8 << 1) | (c9 >>> 31));
|
||
|
l = c5 ^ ((c9 << 1) | (c8 >>> 31));
|
||
|
s[6] ^= h;
|
||
|
s[7] ^= l;
|
||
|
s[16] ^= h;
|
||
|
s[17] ^= l;
|
||
|
s[26] ^= h;
|
||
|
s[27] ^= l;
|
||
|
s[36] ^= h;
|
||
|
s[37] ^= l;
|
||
|
s[46] ^= h;
|
||
|
s[47] ^= l;
|
||
|
h = c6 ^ ((c0 << 1) | (c1 >>> 31));
|
||
|
l = c7 ^ ((c1 << 1) | (c0 >>> 31));
|
||
|
s[8] ^= h;
|
||
|
s[9] ^= l;
|
||
|
s[18] ^= h;
|
||
|
s[19] ^= l;
|
||
|
s[28] ^= h;
|
||
|
s[29] ^= l;
|
||
|
s[38] ^= h;
|
||
|
s[39] ^= l;
|
||
|
s[48] ^= h;
|
||
|
s[49] ^= l;
|
||
|
b0 = s[0];
|
||
|
b1 = s[1];
|
||
|
b32 = (s[11] << 4) | (s[10] >>> 28);
|
||
|
b33 = (s[10] << 4) | (s[11] >>> 28);
|
||
|
b14 = (s[20] << 3) | (s[21] >>> 29);
|
||
|
b15 = (s[21] << 3) | (s[20] >>> 29);
|
||
|
b46 = (s[31] << 9) | (s[30] >>> 23);
|
||
|
b47 = (s[30] << 9) | (s[31] >>> 23);
|
||
|
b28 = (s[40] << 18) | (s[41] >>> 14);
|
||
|
b29 = (s[41] << 18) | (s[40] >>> 14);
|
||
|
b20 = (s[2] << 1) | (s[3] >>> 31);
|
||
|
b21 = (s[3] << 1) | (s[2] >>> 31);
|
||
|
b2 = (s[13] << 12) | (s[12] >>> 20);
|
||
|
b3 = (s[12] << 12) | (s[13] >>> 20);
|
||
|
b34 = (s[22] << 10) | (s[23] >>> 22);
|
||
|
b35 = (s[23] << 10) | (s[22] >>> 22);
|
||
|
b16 = (s[33] << 13) | (s[32] >>> 19);
|
||
|
b17 = (s[32] << 13) | (s[33] >>> 19);
|
||
|
b48 = (s[42] << 2) | (s[43] >>> 30);
|
||
|
b49 = (s[43] << 2) | (s[42] >>> 30);
|
||
|
b40 = (s[5] << 30) | (s[4] >>> 2);
|
||
|
b41 = (s[4] << 30) | (s[5] >>> 2);
|
||
|
b22 = (s[14] << 6) | (s[15] >>> 26);
|
||
|
b23 = (s[15] << 6) | (s[14] >>> 26);
|
||
|
b4 = (s[25] << 11) | (s[24] >>> 21);
|
||
|
b5 = (s[24] << 11) | (s[25] >>> 21);
|
||
|
b36 = (s[34] << 15) | (s[35] >>> 17);
|
||
|
b37 = (s[35] << 15) | (s[34] >>> 17);
|
||
|
b18 = (s[45] << 29) | (s[44] >>> 3);
|
||
|
b19 = (s[44] << 29) | (s[45] >>> 3);
|
||
|
b10 = (s[6] << 28) | (s[7] >>> 4);
|
||
|
b11 = (s[7] << 28) | (s[6] >>> 4);
|
||
|
b42 = (s[17] << 23) | (s[16] >>> 9);
|
||
|
b43 = (s[16] << 23) | (s[17] >>> 9);
|
||
|
b24 = (s[26] << 25) | (s[27] >>> 7);
|
||
|
b25 = (s[27] << 25) | (s[26] >>> 7);
|
||
|
b6 = (s[36] << 21) | (s[37] >>> 11);
|
||
|
b7 = (s[37] << 21) | (s[36] >>> 11);
|
||
|
b38 = (s[47] << 24) | (s[46] >>> 8);
|
||
|
b39 = (s[46] << 24) | (s[47] >>> 8);
|
||
|
b30 = (s[8] << 27) | (s[9] >>> 5);
|
||
|
b31 = (s[9] << 27) | (s[8] >>> 5);
|
||
|
b12 = (s[18] << 20) | (s[19] >>> 12);
|
||
|
b13 = (s[19] << 20) | (s[18] >>> 12);
|
||
|
b44 = (s[29] << 7) | (s[28] >>> 25);
|
||
|
b45 = (s[28] << 7) | (s[29] >>> 25);
|
||
|
b26 = (s[38] << 8) | (s[39] >>> 24);
|
||
|
b27 = (s[39] << 8) | (s[38] >>> 24);
|
||
|
b8 = (s[48] << 14) | (s[49] >>> 18);
|
||
|
b9 = (s[49] << 14) | (s[48] >>> 18);
|
||
|
s[0] = b0 ^ (~b2 & b4);
|
||
|
s[1] = b1 ^ (~b3 & b5);
|
||
|
s[10] = b10 ^ (~b12 & b14);
|
||
|
s[11] = b11 ^ (~b13 & b15);
|
||
|
s[20] = b20 ^ (~b22 & b24);
|
||
|
s[21] = b21 ^ (~b23 & b25);
|
||
|
s[30] = b30 ^ (~b32 & b34);
|
||
|
s[31] = b31 ^ (~b33 & b35);
|
||
|
s[40] = b40 ^ (~b42 & b44);
|
||
|
s[41] = b41 ^ (~b43 & b45);
|
||
|
s[2] = b2 ^ (~b4 & b6);
|
||
|
s[3] = b3 ^ (~b5 & b7);
|
||
|
s[12] = b12 ^ (~b14 & b16);
|
||
|
s[13] = b13 ^ (~b15 & b17);
|
||
|
s[22] = b22 ^ (~b24 & b26);
|
||
|
s[23] = b23 ^ (~b25 & b27);
|
||
|
s[32] = b32 ^ (~b34 & b36);
|
||
|
s[33] = b33 ^ (~b35 & b37);
|
||
|
s[42] = b42 ^ (~b44 & b46);
|
||
|
s[43] = b43 ^ (~b45 & b47);
|
||
|
s[4] = b4 ^ (~b6 & b8);
|
||
|
s[5] = b5 ^ (~b7 & b9);
|
||
|
s[14] = b14 ^ (~b16 & b18);
|
||
|
s[15] = b15 ^ (~b17 & b19);
|
||
|
s[24] = b24 ^ (~b26 & b28);
|
||
|
s[25] = b25 ^ (~b27 & b29);
|
||
|
s[34] = b34 ^ (~b36 & b38);
|
||
|
s[35] = b35 ^ (~b37 & b39);
|
||
|
s[44] = b44 ^ (~b46 & b48);
|
||
|
s[45] = b45 ^ (~b47 & b49);
|
||
|
s[6] = b6 ^ (~b8 & b0);
|
||
|
s[7] = b7 ^ (~b9 & b1);
|
||
|
s[16] = b16 ^ (~b18 & b10);
|
||
|
s[17] = b17 ^ (~b19 & b11);
|
||
|
s[26] = b26 ^ (~b28 & b20);
|
||
|
s[27] = b27 ^ (~b29 & b21);
|
||
|
s[36] = b36 ^ (~b38 & b30);
|
||
|
s[37] = b37 ^ (~b39 & b31);
|
||
|
s[46] = b46 ^ (~b48 & b40);
|
||
|
s[47] = b47 ^ (~b49 & b41);
|
||
|
s[8] = b8 ^ (~b0 & b2);
|
||
|
s[9] = b9 ^ (~b1 & b3);
|
||
|
s[18] = b18 ^ (~b10 & b12);
|
||
|
s[19] = b19 ^ (~b11 & b13);
|
||
|
s[28] = b28 ^ (~b20 & b22);
|
||
|
s[29] = b29 ^ (~b21 & b23);
|
||
|
s[38] = b38 ^ (~b30 & b32);
|
||
|
s[39] = b39 ^ (~b31 & b33);
|
||
|
s[48] = b48 ^ (~b40 & b42);
|
||
|
s[49] = b49 ^ (~b41 & b43);
|
||
|
s[0] ^= RC[n];
|
||
|
s[1] ^= RC[n + 1];
|
||
|
}
|
||
|
};
|
||
|
root.sha3_str = methods.sha3_256;
|
||
|
root.sha3_array_256 = methods.sha3_array_256;
|
||
|
root.sha3 = methods.sha3_array_256;
|
||
|
root.sha = function (data)
|
||
|
{
|
||
|
return meshhash(methods.sha3_256(data));
|
||
|
};
|
||
|
root.shaarr = function (data)
|
||
|
{
|
||
|
return meshhash(methods.sha3_array_256(data));
|
||
|
};
|
||
|
root.shabuf = function (data)
|
||
|
{
|
||
|
return Buffer.from(shaarr(data));
|
||
|
};
|
||
|
root.shabuf = function (data)
|
||
|
{
|
||
|
return Buffer.from(shaarr(data));
|
||
|
};
|
||
|
root.SHA3BUF = function (data,num)
|
||
|
{
|
||
|
return Buffer.from(SHA3ARR(data, num));
|
||
|
};
|
||
|
root.SHA3ARR = function (data,num)
|
||
|
{
|
||
|
if(!NEW_SIGN_TIME || !num || num >= NEW_SIGN_TIME)
|
||
|
return sha3(data);
|
||
|
else
|
||
|
return meshhash(methods.sha3_array_256(data));
|
||
|
};
|
||
|
root.shaarrblock = function (data,num)
|
||
|
{
|
||
|
return meshhash(methods.sha3_array_256(data), num);
|
||
|
};
|
||
|
})();
|
||
|
|
||
|
function meshhash(hash,num)
|
||
|
{
|
||
|
var regs = [hash[3], hash[2], hash[1], hash[0]];
|
||
|
var mem = [];
|
||
|
for(var i = 0; i < 16; i++)
|
||
|
{
|
||
|
mem[i] = hash[i * 2] + (hash[i * 2 + 1] << 8);
|
||
|
}
|
||
|
var WasGoto = 0;
|
||
|
var L = 0;
|
||
|
for(var i = 0; i < 64; i++)
|
||
|
{
|
||
|
var c = hash[L & 31];
|
||
|
L++;
|
||
|
var a = (c >> 4) & 0xF;
|
||
|
var b = c & 0xF;
|
||
|
var r = c & 0x3;
|
||
|
switch(a)
|
||
|
{
|
||
|
case 0:
|
||
|
regs[0] = regs[0] + regs[r];
|
||
|
break;
|
||
|
case 1:
|
||
|
regs[0] = regs[0] * regs[r];
|
||
|
break;
|
||
|
case 2:
|
||
|
regs[0] = regs[0] | regs[r];
|
||
|
break;
|
||
|
case 3:
|
||
|
regs[0] = regs[0] & regs[r];
|
||
|
break;
|
||
|
case 4:
|
||
|
case 5:
|
||
|
case 6:
|
||
|
case 7:
|
||
|
regs[0] = regs[0] + regs[1] + regs[2] + regs[3];
|
||
|
break;
|
||
|
case 8:
|
||
|
if((regs[0] & 0xFFFF) < 32768 && !WasGoto)
|
||
|
{
|
||
|
L = 32 + L - b;
|
||
|
WasGoto = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 9:
|
||
|
if((regs[0] & 0xFFFF) > 32768 && !WasGoto)
|
||
|
{
|
||
|
L += b;
|
||
|
WasGoto = 1;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
regs[a % 4] = mem[b];
|
||
|
}
|
||
|
var index1 = regs[0] & 0xF;
|
||
|
var index2 = (regs[0] >> 8) & 0xF;
|
||
|
if(index1 !== index2)
|
||
|
{
|
||
|
var temp = mem[index1];
|
||
|
mem[index1] = mem[index2];
|
||
|
mem[index2] = temp;
|
||
|
}
|
||
|
}
|
||
|
var ret = [];
|
||
|
for(var i = 0; i < 16; i++)
|
||
|
{
|
||
|
ret[i * 2] = mem[i] & 0xFF;
|
||
|
ret[i * 2 + 1] = mem[i] >> 8;
|
||
|
}
|
||
|
return sha3_array_256(ret);
|
||
|
};
|