- AMD support.
- support for web worker. #13

Changed
- throw error if input type is incorrect when cSHAKE and KMAC.
- freeze hash after finalize.
pull/16/head v0.7.0
Yi-Cyuan Chen 8 years ago
parent c43f9d1d18
commit fb7e6403d9

@ -1,2 +0,0 @@
/node_modules/
/tests/

4
.gitignore vendored

@ -1,3 +1,3 @@
/node_modules/ /node_modules/
/covreporter/ /coverage/
/my_test/ /.nyc_output/

@ -0,0 +1,7 @@
/node_modules/
/coverage/
/.nyc_output/
/tests/
.travis.yml
.npmignore
bower.json

@ -1,12 +1,10 @@
language: node_js language: node_js
node_js: node_js:
- "0.12.15" - "6.11.4"
- "4.5" - "8.6.0"
- "6.5.0"
before_install: before_install:
- npm install coveralls - npm install coveralls
- npm install mocha-lcov-reporter after_success: npm run coveralls
script: npm run-script coveralls
branches: branches:
only: only:
- master - master

@ -1,5 +1,14 @@
# Change Log # Change Log
## v0.7.0 / 2017-12-01
### Added
- AMD support.
- support for web worker. #13
### Changed
- throw error if input type is incorrect when cSHAKE and KMAC.
- freeze hash after finalize.
## v0.6.1 / 2017-07-03 ## v0.6.1 / 2017-07-03
### Fixed ### Fixed
- Typo on variable kmac_256 type definition. #12 - Typo on variable kmac_256 type definition. #12

@ -1,6 +1,6 @@
{ {
"name": "js-sha3", "name": "js-sha3",
"version": "0.6.1", "version": "0.7.0",
"main": ["src/sha3.js"], "main": ["src/sha3.js"],
"ignore": [ "ignore": [
"samples", "samples",

4
build/sha3.min.js vendored

File diff suppressed because one or more lines are too long

1802
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,21 +1,20 @@
{ {
"name": "js-sha3", "name": "js-sha3",
"version": "0.6.1", "version": "0.7.0",
"description": "A simple SHA-3 / Keccak / Shake hash function for JavaScript supports UTF-8 encoding.", "description": "A simple SHA-3 / Keccak / Shake hash function for JavaScript supports UTF-8 encoding.",
"main": "src/sha3.js", "main": "src/sha3.js",
"typings": "index",
"types": "index.d.ts",
"devDependencies": { "devDependencies": {
"expect.js": "~0.3.1", "expect.js": "~0.3.1",
"jscoverage": "~0.5.9", "mocha": "~2.3.4",
"mocha": "~2.3.2", "nyc": "^11.3.0",
"uglifyjs": "~2.4.10" "uglify-js": "^3.1.9",
"webworker-threads": "^0.7.13"
}, },
"scripts": { "scripts": {
"test": "mocha tests/node-test.js -r jscoverage", "test": "nyc mocha tests/node-test.js",
"report": "mocha tests/node-test.js -r jscoverage --covout=html", "report": "nyc --reporter=html --reporter=text mocha tests/node-test.js",
"coveralls": "mocha tests/node-test.js -R mocha-lcov-reporter -r jscoverage | coveralls", "coveralls": "nyc report --reporter=text-lcov | coveralls",
"build": "uglifyjs src/sha3.js --compress --mangle --comments --output build/sha3.min.js" "build": "uglifyjs src/sha3.js -c -m --comments --output build/sha3.min.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -37,5 +36,10 @@
"homepage": "https://github.com/emn178/js-sha3", "homepage": "https://github.com/emn178/js-sha3",
"bugs": { "bugs": {
"url": "https://github.com/emn178/js-sha3/issues" "url": "https://github.com/emn178/js-sha3/issues"
},
"nyc": {
"exclude": [
"tests"
]
} }
} }

@ -1,7 +1,7 @@
/** /**
* [js-sha3]{@link https://github.com/emn178/js-sha3} * [js-sha3]{@link https://github.com/emn178/js-sha3}
* *
* @version 0.6.1 * @version 0.7.0
* @author Chen, Yi-Cyuan [emn178@gmail.com] * @author Chen, Yi-Cyuan [emn178@gmail.com]
* @copyright Chen, Yi-Cyuan 2015-2017 * @copyright Chen, Yi-Cyuan 2015-2017
* @license MIT * @license MIT
@ -10,12 +10,21 @@
(function () { (function () {
'use strict'; 'use strict';
var root = typeof window === 'object' ? window : {}; var ERROR = 'input is invalid type';
var WINDOW = typeof window === 'object';
var root = WINDOW ? window : {};
if (root.JS_SHA3_NO_WINDOW) {
WINDOW = false;
}
var WEB_WORKER = !WINDOW && typeof self === 'object';
var NODE_JS = !root.JS_SHA3_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node; var NODE_JS = !root.JS_SHA3_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
if (NODE_JS) { if (NODE_JS) {
root = global; root = global;
} else if (WEB_WORKER) {
root = self;
} }
var COMMON_JS = !root.JS_SHA3_NO_COMMON_JS && typeof module === 'object' && module.exports; var COMMON_JS = !root.JS_SHA3_NO_COMMON_JS && typeof module === 'object' && module.exports;
var AMD = typeof define === 'function' && define.amd;
var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined'; var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
var HEX_CHARS = '0123456789abcdef'.split(''); var HEX_CHARS = '0123456789abcdef'.split('');
var SHAKE_PADDING = [31, 7936, 2031616, 520093696]; var SHAKE_PADDING = [31, 7936, 2031616, 520093696];
@ -24,13 +33,13 @@
var PADDING = [6, 1536, 393216, 100663296]; var PADDING = [6, 1536, 393216, 100663296];
var SHIFT = [0, 8, 16, 24]; var SHIFT = [0, 8, 16, 24];
var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649, var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649,
0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0, 0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0,
2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771, 2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771,
2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648, 2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648,
2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648]; 2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648];
var BITS = [224, 256, 384, 512]; var BITS = [224, 256, 384, 512];
var SHAKE_BITS = [128, 256]; var SHAKE_BITS = [128, 256];
var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array']; var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array', 'digest'];
var CSHAKE_BYTEPAD = { var CSHAKE_BYTEPAD = {
'128': 168, '128': 168,
'256': 136 '256': 136
@ -42,6 +51,12 @@
}; };
} }
if (ARRAY_BUFFER && (root.JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
ArrayBuffer.isView = function (obj) {
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
};
}
var createOutputMethod = function (bits, padding, outputType) { var createOutputMethod = function (bits, padding, outputType) {
return function (message) { return function (message) {
return new Keccak(bits, padding, bits).update(message)[outputType](); return new Keccak(bits, padding, bits).update(message)[outputType]();
@ -125,18 +140,18 @@
}; };
var algorithms = [ var algorithms = [
{name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod}, { name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod },
{name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod}, { name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod },
{name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod}, { name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod },
{name: 'cshake', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createCshakeMethod}, { name: 'cshake', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createCshakeMethod },
{name: 'kmac', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createKmacMethod} { name: 'kmac', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createKmacMethod }
]; ];
var methods = {}, methodNames = []; var methods = {}, methodNames = [];
for (var i = 0; i < algorithms.length; ++i) { for (var i = 0; i < algorithms.length; ++i) {
var algorithm = algorithms[i]; var algorithm = algorithms[i];
var bits = algorithm.bits; var bits = algorithm.bits;
for (var j = 0; j < bits.length; ++j) { for (var j = 0; j < bits.length; ++j) {
var methodName = algorithm.name + '_' + bits[j]; var methodName = algorithm.name + '_' + bits[j];
methodNames.push(methodName); methodNames.push(methodName);
@ -155,6 +170,7 @@
this.padding = padding; this.padding = padding;
this.outputBits = outputBits; this.outputBits = outputBits;
this.reset = true; this.reset = true;
this.finalized = false;
this.block = 0; this.block = 0;
this.start = 0; this.start = 0;
this.blockCount = (1600 - (bits << 1)) >> 5; this.blockCount = (1600 - (bits << 1)) >> 5;
@ -168,19 +184,27 @@
} }
Keccak.prototype.update = function (message) { Keccak.prototype.update = function (message) {
var notString = typeof message !== 'string'; if (this.finalized) {
if (notString && message.constructor === root.ArrayBuffer) { return;
message = new Uint8Array(message);
} }
var length = message.length; var notString, type = typeof message;
if (notString) { if (type !== 'string') {
if (typeof length !== 'number' || if (type === 'object') {
!Array.isArray(message) && if (message === null) {
!(ARRAY_BUFFER && ArrayBuffer.isView(message))) { throw ERROR;
throw 'input is invalid type'; } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
message = new Uint8Array(message);
} else if (!Array.isArray(message)) {
if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
throw ERROR;
}
}
} else {
throw ERROR;
} }
notString = true;
} }
var blocks = this.blocks, byteCount = this.byteCount, var blocks = this.blocks, byteCount = this.byteCount, length = message.length,
blockCount = this.blockCount, index = 0, s = this.s, i, code; blockCount = this.blockCount, index = 0, s = this.s, i, code;
while (index < length) { while (index < length) {
@ -253,20 +277,24 @@
}; };
Keccak.prototype.encodeString = function (str) { Keccak.prototype.encodeString = function (str) {
str = str || ''; var notString, type = typeof str;
var notString = typeof str !== 'string'; if (type !== 'string') {
if (notString && str.constructor === root.ArrayBuffer) { if (type === 'object') {
str = new Uint8Array(str); if (str === null) {
} throw ERROR;
var length = str.length; } else if (ARRAY_BUFFER && str.constructor === ArrayBuffer) {
if (notString) { str = new Uint8Array(str);
if (typeof length !== 'number' || } else if (!Array.isArray(str)) {
!Array.isArray(str) && if (!ARRAY_BUFFER || !ArrayBuffer.isView(str)) {
!(ARRAY_BUFFER && ArrayBuffer.isView(str))) { throw ERROR;
throw 'input is invalid type'; }
}
} else {
throw ERROR;
} }
notString = true;
} }
var bytes = 0; var bytes = 0, length = str.length;
if (notString) { if (notString) {
bytes = length; bytes = length;
} else { } else {
@ -291,7 +319,7 @@
Keccak.prototype.bytepad = function (strs, w) { Keccak.prototype.bytepad = function (strs, w) {
var bytes = this.encode(w); var bytes = this.encode(w);
for (var i = 0;i < strs.length;++i) { for (var i = 0; i < strs.length; ++i) {
bytes += this.encodeString(strs[i]); bytes += this.encodeString(strs[i]);
} }
var paddingBytes = w - bytes % w; var paddingBytes = w - bytes % w;
@ -302,6 +330,10 @@
}; };
Keccak.prototype.finalize = function () { Keccak.prototype.finalize = function () {
if (this.finalized) {
return;
}
this.finalized = true;
var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s; var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s;
blocks[i >> 2] |= this.padding[i & 3]; blocks[i >> 2] |= this.padding[i & 3];
if (this.lastByteIndex === this.byteCount) { if (this.lastByteIndex === this.byteCount) {
@ -321,15 +353,15 @@
this.finalize(); this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0; extraBytes = this.extraBytes, i = 0, j = 0;
var hex = '', block; var hex = '', block;
while (j < outputBlocks) { while (j < outputBlocks) {
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
block = s[i]; block = s[i];
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] + hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] +
HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] + HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] +
HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] + HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] +
HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F]; HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F];
} }
if (j % blockCount === 0) { if (j % blockCount === 0) {
f(s); f(s);
@ -338,9 +370,7 @@
} }
if (extraBytes) { if (extraBytes) {
block = s[i]; block = s[i];
if (extraBytes > 0) { hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F];
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F];
}
if (extraBytes > 1) { if (extraBytes > 1) {
hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F]; hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F];
} }
@ -355,7 +385,7 @@
this.finalize(); this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0; extraBytes = this.extraBytes, i = 0, j = 0;
var bytes = this.outputBits >> 3; var bytes = this.outputBits >> 3;
var buffer; var buffer;
if (extraBytes) { if (extraBytes) {
@ -385,7 +415,7 @@
this.finalize(); this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0; extraBytes = this.extraBytes, i = 0, j = 0;
var array = [], offset, block; var array = [], offset, block;
while (j < outputBlocks) { while (j < outputBlocks) {
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
@ -403,9 +433,7 @@
if (extraBytes) { if (extraBytes) {
offset = j << 2; offset = j << 2;
block = s[i]; block = s[i];
if (extraBytes > 0) { array[offset] = block & 0xFF;
array[offset] = block & 0xFF;
}
if (extraBytes > 1) { if (extraBytes > 1) {
array[offset + 1] = (block >> 8) & 0xFF; array[offset + 1] = (block >> 8) & 0xFF;
} }
@ -429,9 +457,9 @@
var f = function (s) { var f = function (s) {
var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, 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, 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, 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; b34, b35, b36, b37, b38, b39, b40, b41, b42, b43, b44, b45, b46, b47, b48, b49;
for (n = 0; n < 48; n += 2) { for (n = 0; n < 48; n += 2) {
c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40]; c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41]; c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
@ -615,8 +643,13 @@
if (COMMON_JS) { if (COMMON_JS) {
module.exports = methods; module.exports = methods;
} else { } else {
for (var i = 0; i < methodNames.length; ++i) { for (i = 0; i < methodNames.length; ++i) {
root[methodNames[i]] = methods[methodNames[i]]; root[methodNames[i]] = methods[methodNames[i]];
} }
if (AMD) {
define(function () {
return methods;
});
}
} }
})(); })();

@ -1,80 +1,150 @@
expect = require('expect.js'); expect = require('expect.js');
Worker = require('webworker-threads').Worker;
function unset() {
delete require.cache[require.resolve('../src/sha3.js')];
delete require.cache[require.resolve('./test.js')];
sha3_512 = null;
sha3_384 = null;
sha3_256 = null;
sha3_224 = null;
keccak512 = null;
keccak384 = null;
keccak256 = null;
keccak224 = null;
shake128 = null;
shake256 = null;
kmac128 = null;
kmac256 = null;
BUFFER = undefined;
JS_SHA3_NO_WINDOW = undefined;
JS_SHA3_NO_NODE_JS = undefined;
JS_SHA3_NO_COMMON_JS = undefined;
JS_SHA3_NO_ARRAY_BUFFER = undefined;
JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW = undefined;
window = undefined;
}
function requireToGlobal() {
var sha3 = require('../src/sha3.js');
keccak512 = sha3.keccak512;
keccak384 = sha3.keccak384;
keccak256 = sha3.keccak256;
keccak224 = sha3.keccak224;
sha3_512 = sha3.sha3_512;
sha3_384 = sha3.sha3_384;
sha3_256 = sha3.sha3_256;
sha3_224 = sha3.sha3_224;
shake128 = sha3.shake128;
shake256 = sha3.shake256;
cshake128 = sha3.cshake128;
cshake256 = sha3.cshake256;
kmac128 = sha3.kmac128;
kmac256 = sha3.kmac256;
}
function runCommonJsTest() {
requireToGlobal();
require('./test.js');
unset();
}
function runWindowTest(extra) {
window = global;
require('../src/sha3.js');
require('./test.js');
if (extra) {
require('./test-shake.js');
require('./test-cshake.js');
require('./test-kmac.js');
}
unset();
}
// Node.js env // Node.js env
var sha3 = require('../src/sha3.js'); BUFFER = true;
keccak512 = sha3.keccak512; runCommonJsTest();
keccak384 = sha3.keccak384;
keccak256 = sha3.keccak256;
keccak224 = sha3.keccak224;
sha3_512 = sha3.sha3_512;
sha3_384 = sha3.sha3_384;
sha3_256 = sha3.sha3_256;
sha3_224 = sha3.sha3_224;
shake128 = sha3.shake128;
shake256 = sha3.shake256;
cshake128 = sha3.cshake128;
cshake256 = sha3.cshake256;
kmac128 = sha3.kmac128;
kmac256 = sha3.kmac256;
require('./test.js');
require('./test-shake.js');
require('./test-cshake.js');
require('./test-kmac.js');
delete require.cache[require.resolve('../src/sha3.js')];
delete require.cache[require.resolve('./test.js')];
delete require.cache[require.resolve('./test-shake.js')];
delete require.cache[require.resolve('./test-cshake.js')];
delete require.cache[require.resolve('./test-kmac.js')];
// Webpack browser env // Webpack browser env
JS_SHA3_NO_NODE_JS = true; JS_SHA3_NO_NODE_JS = true;
window = global; window = global;
expect = require('expect.js'); runCommonJsTest();
var sha3 = require('../src/sha3.js');
keccak512 = sha3.keccak512;
keccak384 = sha3.keccak384;
keccak256 = sha3.keccak256;
keccak224 = sha3.keccak224;
sha3_512 = sha3.sha3_512;
sha3_384 = sha3.sha3_384;
sha3_256 = sha3.sha3_256;
sha3_224 = sha3.sha3_224;
shake128 = sha3.shake128;
shake256 = sha3.shake256;
cshake128 = sha3.cshake128;
cshake256 = sha3.cshake256;
kmac128 = sha3.kmac128;
kmac256 = sha3.kmac256;
require('./test.js');
require('./test-shake.js');
require('./test-cshake.js');
require('./test-kmac.js');
delete require.cache[require.resolve('../src/sha3.js')];
delete require.cache[require.resolve('./test.js')];
delete require.cache[require.resolve('./test-shake.js')];
delete require.cache[require.resolve('./test-cshake.js')];
delete require.cache[require.resolve('./test-kmac.js')];
sha3_512 = null;
sha3_384 = null;
sha3_256 = null;
sha3_224 = null;
keccak512 = null;
keccak384 = null;
keccak256 = null;
keccak224 = null;
shake128 = null;
shake256 = null;
kmac128 = null;
kmac256 = null;
// browser env // browser env
JS_SHA3_NO_NODE_JS = true; JS_SHA3_NO_NODE_JS = true;
JS_SHA3_NO_COMMON_JS = true; JS_SHA3_NO_COMMON_JS = true;
runWindowTest(true);
// browser env and no array buffer
JS_SHA3_NO_NODE_JS = true;
JS_SHA3_NO_COMMON_JS = true;
JS_SHA3_NO_ARRAY_BUFFER = true;
runWindowTest();
// browser env and no isView
JS_SHA3_NO_NODE_JS = true;
JS_SHA3_NO_COMMON_JS = true;
JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW = true;
runWindowTest();
// browser AMD
JS_SHA3_NO_NODE_JS = true;
JS_SHA3_NO_COMMON_JS = true;
JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW = false;
window = global; window = global;
define = function (func) {
sha3 = func();
keccak512 = sha3.keccak512;
keccak384 = sha3.keccak384;
keccak256 = sha3.keccak256;
keccak224 = sha3.keccak224;
sha3_512 = sha3.sha3_512;
sha3_384 = sha3.sha3_384;
sha3_256 = sha3.sha3_256;
sha3_224 = sha3.sha3_224;
shake128 = sha3.shake128;
shake256 = sha3.shake256;
cshake128 = sha3.cshake128;
cshake256 = sha3.cshake256;
kmac128 = sha3.kmac128;
kmac256 = sha3.kmac256;
require('./test.js');
};
define.amd = true;
require('../src/sha3.js'); require('../src/sha3.js');
require('./test.js'); unset();
require('./test-shake.js');
require('./test-cshake.js'); // webworker
require('./test-kmac.js'); WORKER = 'tests/worker.js';
SOURCE = 'src/sha3.js';
require('./worker-test.js');
delete require.cache[require.resolve('./worker-test.js')];
// cover webworker
JS_SHA3_NO_WINDOW = true;
JS_SHA3_NO_NODE_JS = true;
WORKER = './worker.js';
SOURCE = '../src/sha3.js';
window = global;
self = global;
Worker = function (file) {
require(file);
currentWorker = this;
this.postMessage = function (data) {
onmessage({data: data});
};
}
postMessage = function (data) {
currentWorker.onmessage({data: data});
}
importScripts = function () {};
requireToGlobal();
require('./worker-test.js');

@ -27,6 +27,7 @@
it('should be equal', function () { it('should be equal', function () {
expect(shake128('', 16)).to.be('7f9c'); expect(shake128('', 16)).to.be('7f9c');
expect(shake128('', 24)).to.be('7f9c2b'); expect(shake128('', 24)).to.be('7f9c2b');
expect(shake128.array('', 8)).to.eql([0x7f]);
expect(shake128.array('', 16)).to.eql([0x7f, 0x9c]); expect(shake128.array('', 16)).to.eql([0x7f, 0x9c]);
expect(shake128.array('', 24)).to.eql([0x7f, 0x9c, 0x2b]); expect(shake128.array('', 24)).to.eql([0x7f, 0x9c, 0x2b]);
}); });

@ -9,63 +9,6 @@
return hex; return hex;
}; };
function runTestCases(methods, testCases) {
methods.forEach(function (method) {
describe('#' + method.name, function () {
var methodTestCases = testCases[method.name];
for (var testCaseName in methodTestCases) {
(function (testCaseName) {
var testCase = methodTestCases[testCaseName];
context('when ' + testCaseName, function () {
for (var hash in testCase) {
(function (message, hash) {
it('should be equal', function () {
expect(method.call(message)).to.be(hash);
});
})(testCase[hash], hash);
}
});
})(testCaseName);
}
});
});
}
var methods = [
{
name: 'sha3_512',
call: sha3_512
},
{
name: 'sha3_384',
call: sha3_384
},
{
name: 'sha3_256',
call: sha3_256
},
{
name: 'sha3_224',
call: sha3_224
},
{
name: 'keccak512',
call: keccak512
},
{
name: 'keccak384',
call: keccak384
},
{
name: 'keccak256',
call: keccak256
},
{
name: 'keccak224',
call: keccak224
}
];
var testCases = { var testCases = {
sha3_512: { sha3_512: {
'ascii': { 'ascii': {
@ -92,14 +35,6 @@
'Array': { 'Array': {
'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26': [], 'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26': [],
'01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450': [84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103] '01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450': [84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103]
},
'Uint8Array': {
'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26': new Uint8Array([]),
'01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450': new Uint8Array([84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103])
},
'ArrayBuffer': {
'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26': new ArrayBuffer(0),
'01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450': new Uint8Array([84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103]).buffer
} }
}, },
sha3_384: { sha3_384: {
@ -237,104 +172,192 @@
} }
}; };
runTestCases(methods, testCases); if (!(typeof JS_SHA3_NO_ARRAY_BUFFER === 'boolean' && JS_SHA3_NO_ARRAY_BUFFER)) {
testCases.sha3_512.Uint8Array = {
describe('sha3_512', function () { 'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26': new Uint8Array([]),
context('#arrayBuffer', function () { '01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450': new Uint8Array([84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103])
it('should be equal', function () { };
expect(sha3_512.arrayBuffer('').toHexString()).to.be('a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'); testCases.sha3_512.ArrayBuffer = {
expect(sha3_512.buffer('').toHexString()).to.be('a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'); 'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26': new ArrayBuffer(0),
}); '01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450': new Uint8Array([84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103]).buffer
}); };
}
context('#hex', function () { if (typeof BUFFER === 'boolean' && BUFFER) {
it('should be equal', function () { testCases.sha3_512.Buffer = {
expect(sha3_512.hex('')).to.be('a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'); 'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26': new Buffer(0),
}); '01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450': new Buffer(new Uint8Array([84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103]))
}); };
}
context('#update', function () { var errorTestCases = [null, undefined, { length: 0 }, 0, 1, false, true, NaN, Infinity, function () {}];
it('should be equal', function () {
expect(sha3_512.update('').hex()).to.be('a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26');
expect(sha3_512.update('The quick brown fox ').update('jumps over the lazy dog').hex()).to.be('01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450');
});
});
context('#create', function () { function runTestCases(name, algorithm) {
it('should be equal', function () { var methods = [
var bytes = [84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103]; {
var hash = sha3_512.create(); name: name,
for (var i = 0; i < bytes.length; ++i) { call: algorithm,
hash.update([bytes[i]]); },
{
name: name + '.hex',
call: algorithm.hex
},
{
name: name + '.array',
call: function (message) {
return algorithm.array(message).toHexString();
} }
expect(hash.hex()).to.be('01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450'); },
}); {
}); name: name + '.digest',
}); call: function (message) {
return algorithm.digest(message).toHexString();
describe('#keccak512', function () { }
context('when special length', function () { },
it('should be equal', function () { {
expect(keccak512('012345678901234567890123456789012345678901234567890123456789012345678901')).to.be('90b1d032c3bf06dcc78a46fe52054bab1250600224bfc6dfbfb40a7877c55e89bb982799a2edf198568a4166f6736678b45e76b12fac813cfdf0a76714e5eae8'); name: name + '.arrayBuffer',
expect(keccak512('01234567890123456789012345678901234567890123456789012345678901234567890')).to.be('3173e7abc754a0b2909410d78986428a9183e996864af02f421d273d9fa1b4e4a5b14e2998b20767712f53a01ff8f6ae2c3e71e51e2c0f24257b03e6da09eb77'); call: function (message) {
}); return algorithm.arrayBuffer(message).toHexString();
}); }
}
];
context('when Array', function () { var classMethods = [
it('should be equal', function () { {
expect(keccak512([])).to.be('0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e'); name: 'create',
expect(keccak512([84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103])).to.be('d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609'); call: function (message) {
}); return algorithm.create().update(message).toString();
}); }
},
{
name: 'update',
call: function (message) {
return algorithm.update(message).toString();
}
},
{
name: 'hex',
call: function (message) {
return algorithm.update(message).hex();
}
},
{
name: 'array',
call: function (message) {
return algorithm.update(message).array().toHexString();
}
},
{
name: 'digest',
call: function (message) {
return algorithm.update(message).digest().toHexString();
}
},
{
name: 'arrayBuffer',
call: function (message) {
return algorithm.update(message).arrayBuffer().toHexString();
}
},
{
name: 'finalize',
call: function (message) {
var hash = algorithm.update(message);
hash.hex();
hash.update(message);
return hash.hex();
}
}
];
context('when Uint8Array', function () { var subTestCases = testCases[name];
it('should be equal', function () {
expect(keccak512(new Uint8Array([]))).to.be('0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e');
expect(keccak512(new Uint8Array([84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103]))).to.be('d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609');
});
});
context('when ArrayBuffer', function () { describe(name, function () {
it('should be equal', function () { methods.forEach(function (method) {
expect(keccak512(new ArrayBuffer(0))).to.be('0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e'); describe('#' + method.name, function () {
for (var testCaseName in subTestCases) {
(function (testCaseName) {
var testCase = subTestCases[testCaseName];
context('when ' + testCaseName, function () {
for (var hash in testCase) {
(function (message, hash) {
it('should be equal', function () {
expect(method.call(message)).to.be(hash);
});
})(testCase[hash], hash);
}
});
})(testCaseName);
}
});
}); });
});
context('when output ArrayBuffer', function () { classMethods.forEach(function (method) {
it('should be equal', function () { describe('#' + method.name, function () {
expect(keccak512.arrayBuffer('').toHexString()).to.be('0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e'); for (var testCaseName in subTestCases) {
expect(keccak512.buffer('').toHexString()).to.be('0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e'); (function (testCaseName) {
var testCase = subTestCases[testCaseName];
context('when ' + testCaseName, function () {
for (var hash in testCase) {
(function (message, hash) {
it('should be equal', function () {
expect(method.call(message)).to.be(hash);
});
})(testCase[hash], hash);
}
});
})(testCaseName);
}
});
}); });
});
context('when output Array', function () { describe('#' + name, function () {
it('should be equal', function () { errorTestCases.forEach(function (testCase) {
expect(keccak512.array('').toHexString()).to.be('0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e'); context('when ' + testCase, function () {
it('should throw error', function () {
expect(function () {
algorithm(testCase);
}).to.throwError(/input is invalid type/);
});
});
});
}); });
}); });
}
context('when incorrect input', function () { runTestCases('sha3_512', sha3_512);
it('should throw error', function () { runTestCases('sha3_384', sha3_384);
expect(function () { runTestCases('sha3_256', sha3_256);
keccak512(1); runTestCases('sha3_224', sha3_224);
}).to.throwError(); runTestCases('keccak512', keccak512);
}); runTestCases('keccak384', keccak384);
}); runTestCases('keccak256', keccak256);
runTestCases('keccak224', keccak224);
describe('#keccak512', function () {
context('#encodeString', function () { context('#encodeString', function () {
context('when incorrect input', function () { errorTestCases.forEach(function (testCase) {
it('should throw error', function () { context('when ' + testCase, function () {
expect(function () { it('should throw error', function () {
keccak512.create().encodeString(1); expect(function () {
}).to.throwError(); keccak512.create().encodeString(testCase);
}).to.throwError(/input is invalid type/);
});
}); });
}); });
context('when ArrayBuffer', function () { if (!(typeof JS_SHA3_NO_ARRAY_BUFFER === 'boolean' && JS_SHA3_NO_ARRAY_BUFFER)) {
it('should throw error', function () { context('when ArrayBuffer', function () {
expect(keccak512.create().encodeString(new ArrayBuffer(0))).to.be(2); it('should throw error', function () {
expect(keccak512.create().encodeString(new ArrayBuffer(0))).to.be(2);
});
}); });
}); context('when Uint8Array', function () {
it('should throw error', function () {
expect(keccak512.create().encodeString(new Uint8Array(0))).to.be(2);
});
});
}
context('when UTF-8', function () { context('when UTF-8', function () {
it('should throw error', function () { it('should throw error', function () {

@ -0,0 +1,21 @@
(function (Worker, WORKER, SOURCE) {
var cases = {
'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26': '',
'01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450': 'The quick brown fox jumps over the lazy dog',
'18f4f4bd419603f95538837003d9d254c26c23765565162247483f65c50303597bc9ce4d289f21d1c2f1f458828e33dc442100331b35e7eb031b5d38ba6460f8': 'The quick brown fox jumps over the lazy dog.'
};
describe('#sha3_512', function () {
Object.keys(cases).forEach(function (hash) {
it('should be equal', function (done) {
var worker = new Worker(WORKER);
worker.onmessage = function(event) {
expect(event.data).to.be(hash);
done();
};
worker.postMessage(SOURCE);
worker.postMessage(cases[hash]);
});
});
});
})(Worker, WORKER, SOURCE);

@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SHA3</title>
<link rel="stylesheet" href="../node_modules/mocha/mocha.css">
<script src="../node_modules/mocha/mocha.js"></script>
<script src="../node_modules/expect.js/index.js"></script>
<script src="../src/sha3.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>
WORKER = 'worker.js';
SOURCE = '../src/sha3.js';
mocha.setup('bdd');
</script>
<script src="worker-test.js"></script>
<script>
mocha.checkLeaks();
mocha.run();
</script>
<script>
</script>
</body>
</html>

@ -0,0 +1,12 @@
var imported = false;
onmessage = function(e) {
if (imported) {
postMessage(sha3_512(e.data));
if (typeof exports !== 'undefined') {
imported = false;
}
} else {
imported = true;
importScripts(e.data);
}
}
Loading…
Cancel
Save