Compare commits

..
5 Commits
Author SHA1 Message Date
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c3fc9645d4 Bump picomatch from 4.0.2 to 4.0.5 (#46)
Bumps [picomatch](https://github.com/micromatch/picomatch) from 4.0.2 to 4.0.5.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.2...4.0.5)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 4.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 08:35:23 +08:00
Yi-Cyuan Chen 59d5441220 ### Added
- GitHub Actions CI across Node.js 18, 20, 22, and 24 against the packed npm artifact
- GitHub Actions publish workflow on release with npm trusted publishing
- `prepack` script to build distributions before `npm pack` / `npm publish`

### Changed
- Replace Travis CI with GitHub Actions
- Update README badges to GitHub Actions, npm, and jsDelivr
- Upgrade mocha and pin vulnerable transitive dependencies via npm overrides
2026-08-07 08:31:31 +08:00
Yi-Cyuan Chen a67f74cf2c ### Added
- ParallelHash128, ParallelHash256, ParallelHashXOF128, and ParallelHashXOF256 (NIST SP 800-185)
2026-08-07 08:18:38 +08:00
Yi-Cyuan Chen d506b22f67 update RERADME 2026-08-06 11:38:20 +08:00
Yi-Cyuan Chen 5f95ceb733 ### Added
- KMACXOF128 and KMACXOF256 (NIST SP 800-185)
2026-07-18 10:14:36 +08:00
20 changed files with 1949 additions and 1316 deletions
+77
View File
@@ -0,0 +1,77 @@
name: CI
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node 24
uses: actions/setup-node@v4
with:
node-version: 24.x
- name: Install dependencies
run: npm ci
- name: Pack npm package
run: |
mkdir -p package-artifact
npm pack --pack-destination package-artifact
- name: Upload package artifact
uses: actions/upload-artifact@v4
with:
name: package-node-24
path: package-artifact/*.tgz
if-no-files-found: error
runtime-test:
needs: build
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x, 22.x, 24.x]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: Download package artifact
uses: actions/download-artifact@v4
with:
name: package-node-24
path: package-artifact
- name: Extract package artifact
run: tar -xzf package-artifact/*.tgz --strip-components=1 -C .
- name: Run runtime tests
if: matrix.node-version != '24.x'
run: npm run test:runtime
- name: Run runtime tests with coverage
if: matrix.node-version == '24.x'
run: npm run test:coverage
- name: Upload to coveralls
if: matrix.node-version == '24.x'
uses: coverallsapp/github-action@v2
with:
file: ./coverage/lcov.info
+32
View File
@@ -0,0 +1,32 @@
name: Publish
on:
release:
types: [published]
permissions:
contents: read
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24.x
registry-url: https://registry.npmjs.org
package-manager-cache: false
- run: npm ci
- name: Verify release version
run: |
PACKAGE_VERSION=$(node -p "require('./package.json').version")
test "$GITHUB_REF_NAME" = "v$PACKAGE_VERSION"
- run: npm run build
- run: npm test
- run: npm publish
-1
View File
@@ -2,6 +2,5 @@
/coverage/ /coverage/
/.nyc_output/ /.nyc_output/
/tests/ /tests/
.travis.yml
.npmignore .npmignore
bower.json bower.json
-10
View File
@@ -1,10 +0,0 @@
language: node_js
node_js:
- "6.11.4"
- "8.6.0"
before_install:
- npm install coveralls
after_success: npm run coveralls
branches:
only:
- master
+16
View File
@@ -1,5 +1,21 @@
# Change Log # Change Log
## v0.13.0 / 2026-08-07
### Added
- ParallelHash128, ParallelHash256, ParallelHashXOF128, and ParallelHashXOF256 (NIST SP 800-185)
- GitHub Actions CI across Node.js 18, 20, 22, and 24 against the packed npm artifact
- GitHub Actions publish workflow on release with npm trusted publishing
- `prepack` script to build distributions before `npm pack` / `npm publish`
### Changed
- Replace Travis CI with GitHub Actions
- Update README badges to GitHub Actions, npm, and jsDelivr
- Upgrade mocha and pin vulnerable transitive dependencies via npm overrides
## v0.12.0 / 2026-07-18
### Added
- KMACXOF128 and KMACXOF256 (NIST SP 800-185)
## v0.11.0 / 2026-07-18 ## v0.11.0 / 2026-07-18
### Added ### Added
- TupleHash128, TupleHash256, TupleHashXOF128, and TupleHashXOF256 (NIST SP 800-185) - TupleHash128, TupleHash256, TupleHashXOF128, and TupleHashXOF256 (NIST SP 800-185)
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright 2015-2023 Chen, Yi-Cyuan Copyright 2015-2026 Chen, Yi-Cyuan
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
+47 -8
View File
@@ -1,10 +1,10 @@
# js-sha3 # js-sha3
[![CI](https://github.com/emn178/js-sha3/actions/workflows/ci.yml/badge.svg)](https://github.com/emn178/js-sha3/actions/workflows/ci.yml)
[![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)
[![NPM](https://nodei.co/npm/js-sha3.png?stars&downloads)](https://nodei.co/npm/js-sha3/) [![NPM](https://img.shields.io/npm/v/js-sha3)](https://www.npmjs.com/package/js-sha3)
[![CDNJS](https://img.shields.io/jsdelivr/npm/hm/js-sha3)](https://www.jsdelivr.com/package/npm/js-sha3)
A simple SHA-3 / Keccak / SHAKE / cSHAKE / KMAC / TupleHash hash function for JavaScript supports UTF-8 encoding. A simple SHA-3 / Keccak / SHAKE / cSHAKE / KMAC / TupleHash / ParallelHash hash function for JavaScript supports UTF-8 encoding.
## Notice ## Notice
* v0.8.0+ will throw an error if try to update hash after finalize. * v0.8.0+ will throw an error if try to update hash after finalize.
@@ -20,8 +20,22 @@ A simple SHA-3 / Keccak / SHAKE / cSHAKE / KMAC / TupleHash hash function for Ja
[Keccak-384 Online](http://emn178.github.io/online-tools/keccak_384.html) [Keccak-384 Online](http://emn178.github.io/online-tools/keccak_384.html)
[Keccak-256 Online](http://emn178.github.io/online-tools/keccak_256.html) [Keccak-256 Online](http://emn178.github.io/online-tools/keccak_256.html)
[Keccak-224 Online](http://emn178.github.io/online-tools/keccak_224.html) [Keccak-224 Online](http://emn178.github.io/online-tools/keccak_224.html)
[Shake128 Online](http://emn178.github.io/online-tools/shake_128.html) [Shake128 Online](http://emn178.github.io/online-tools/shake128/)
[Shake256 Online](http://emn178.github.io/online-tools/shake_256.html) [Shake256 Online](http://emn178.github.io/online-tools/shake256/)
[cShake128 Online](http://emn178.github.io/online-tools/cshake128/)
[cShake256 Online](http://emn178.github.io/online-tools/cshake256/)
[KMAC128 Online](http://emn178.github.io/online-tools/kmac128/)
[KMAC256 Online](http://emn178.github.io/online-tools/kmac256/)
[KMACXOF128 Online](http://emn178.github.io/online-tools/kmacxof128/)
[KMACXOF256 Online](http://emn178.github.io/online-tools/kmacxof256/)
[TupleHash128 Online](http://emn178.github.io/online-tools/tuplehash128/)
[TupleHash256 Online](http://emn178.github.io/online-tools/tuplehash256/)
[TupleHashXOF128 Online](http://emn178.github.io/online-tools/tuplehashxof128/)
[TupleHashXOF256 Online](http://emn178.github.io/online-tools/tuplehashxof256/)
[ParallelHash128 Online](http://emn178.github.io/online-tools/parallelhash128/)
[ParallelHash256 Online](http://emn178.github.io/online-tools/parallelhash256/)
[ParallelHashXOF128 Online](http://emn178.github.io/online-tools/parallelhashxof128/)
[ParallelHashXOF256 Online](http://emn178.github.io/online-tools/parallelhashxof256/)
## Download ## Download
[Compress](https://raw.github.com/emn178/js-sha3/master/build/sha3.min.js) [Compress](https://raw.github.com/emn178/js-sha3/master/build/sha3.min.js)
@@ -53,10 +67,16 @@ cshake128('Message to hash', 256, 'function name', 'customization');
cshake256('Message to hash', 512, 'function name', 'customization'); cshake256('Message to hash', 512, 'function name', 'customization');
kmac128('key', 'Message to hash', 256, 'customization'); kmac128('key', 'Message to hash', 256, 'customization');
kmac256('key', 'Message to hash', 512, 'customization'); kmac256('key', 'Message to hash', 512, 'customization');
kmacxof128('key', 'Message to hash', 256, 'customization');
kmacxof256('key', 'Message to hash', 512, 'customization');
tuplehash128(['abc', 'd'], 256, 'customization'); tuplehash128(['abc', 'd'], 256, 'customization');
tuplehash256(['abc', 'd'], 512, 'customization'); tuplehash256(['abc', 'd'], 512, 'customization');
tuplehashxof128(['abc', 'd'], 256, 'customization'); tuplehashxof128(['abc', 'd'], 256, 'customization');
tuplehashxof256(['abc', 'd'], 512, 'customization'); tuplehashxof256(['abc', 'd'], 512, 'customization');
parallelhash128('Message to hash', 8, 256, 'customization');
parallelhash256('Message to hash', 8, 512, 'customization');
parallelhashxof128('Message to hash', 8, 256, 'customization');
parallelhashxof256('Message to hash', 8, 512, 'customization');
// Support ArrayBuffer output // Support ArrayBuffer output
var arrayBuffer = keccak224.arrayBuffer('Message to hash'); var arrayBuffer = keccak224.arrayBuffer('Message to hash');
@@ -110,6 +130,13 @@ tupleHash.updateChunk([0x63]);
tupleHash.beginInput(1); tupleHash.beginInput(1);
tupleHash.updateChunk([0x64]); tupleHash.updateChunk([0x64]);
tupleHash.hex(); tupleHash.hex();
// ParallelHash: hash one large input in fixed-size blocks.
parallelhash128('Message to hash', 8, 256, '');
parallelhash128.create(8, 256, '')
.update('Message ')
.update('to hash')
.hex();
``` ```
### Node.js ### Node.js
If you use node.js, you should require the module first: If you use node.js, you should require the module first:
@@ -129,10 +156,16 @@ const {
cshake256, cshake256,
kmac128, kmac128,
kmac256, kmac256,
kmacxof128,
kmacxof256,
tuplehash128, tuplehash128,
tuplehash256, tuplehash256,
tuplehashxof128, tuplehashxof128,
tuplehashxof256 tuplehashxof256,
parallelhash128,
parallelhash256,
parallelhashxof128,
parallelhashxof256
} = require('js-sha3'); } = require('js-sha3');
``` ```
@@ -154,10 +187,16 @@ import {
cshake256, cshake256,
kmac128, kmac128,
kmac256, kmac256,
kmacxof128,
kmacxof256,
tuplehash128, tuplehash128,
tuplehash256, tuplehash256,
tuplehashxof128, tuplehashxof128,
tuplehashxof256 tuplehashxof256,
parallelhash128,
parallelhash256,
parallelhashxof128,
parallelhashxof256
} from 'js-sha3'; } from 'js-sha3';
``` ```
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "js-sha3", "name": "js-sha3",
"version": "0.9.3", "version": "0.13.0",
"main": ["src/sha3.js"], "main": ["src/sha3.js"],
"ignore": [ "ignore": [
"samples", "samples",
+3 -3
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+177 -54
View File
@@ -9,9 +9,9 @@ var sha3$1 = {exports: {}};
/** /**
* [js-sha3]{@link https://github.com/emn178/js-sha3} * [js-sha3]{@link https://github.com/emn178/js-sha3}
* *
* @version 0.11.0 * @version 0.13.0
* @author Chen, Yi-Cyuan [emn178@gmail.com] * @author Chen, Yi-Cyuan [emn178@gmail.com]
* @copyright Chen, Yi-Cyuan 2015-2023 * @copyright Chen, Yi-Cyuan 2015-2026
* @license MIT * @license MIT
*/ */
@@ -25,6 +25,7 @@ var sha3$1 = {exports: {}};
var TUPLE_INCOMPLETE_ERROR = 'tuple input is incomplete'; var TUPLE_INCOMPLETE_ERROR = 'tuple input is incomplete';
var TUPLE_LENGTH_ERROR = 'tuple input exceeds declared length'; var TUPLE_LENGTH_ERROR = 'tuple input exceeds declared length';
var TUPLE_BYTE_LENGTH_ERROR = 'tuple input byte length is invalid'; var TUPLE_BYTE_LENGTH_ERROR = 'tuple input byte length is invalid';
var BLOCK_SIZE_ERROR = 'block size is invalid';
var WINDOW = typeof window === 'object'; var WINDOW = typeof window === 'object';
var root = WINDOW ? window : {}; var root = WINDOW ? window : {};
if (root.JS_SHA3_NO_WINDOW) { if (root.JS_SHA3_NO_WINDOW) {
@@ -119,9 +120,21 @@ var sha3$1 = {exports: {}};
}; };
}; };
var createKmacOutputMethod = function (bits, padding, outputType) { var createKmacOutputMethod = function (bits, padding, xof, outputType) {
return function (key, message, outputBits, s) { return function (key, message, outputBits, s) {
return methods['kmac' + bits].update(key, message, outputBits, s)[outputType](); return methods[(xof ? 'kmacxof' : 'kmac') + bits].update(key, message, outputBits, s)[outputType]();
};
};
var createTupleHashOutputMethod = function (bits, padding, xof, outputType) {
return function (inputs, outputBits, s) {
return methods[(xof ? 'tuplehashxof' : 'tuplehash') + bits].update(inputs, outputBits, s)[outputType]();
};
};
var createParallelHashOutputMethod = function (bits, padding, xof, outputType) {
return function (message, blockSize, outputBits, s) {
return methods[(xof ? 'parallelhashxof' : 'parallelhash') + bits].update(message, blockSize, outputBits, s)[outputType]();
}; };
}; };
@@ -171,22 +184,18 @@ var sha3$1 = {exports: {}};
return createOutputMethods(method, createCshakeOutputMethod, bits, padding); return createOutputMethods(method, createCshakeOutputMethod, bits, padding);
}; };
var createKmacMethod = function (bits, padding) { var createKmacMethod = function (bits, padding, xof) {
var w = CSHAKE_BYTEPAD[bits]; var w = CSHAKE_BYTEPAD[bits];
var method = createKmacOutputMethod(bits, padding, 'hex'); var method = createKmacOutputMethod(bits, padding, xof, 'hex');
method.create = function (key, outputBits, s) { method.create = function (key, outputBits, s) {
return new Kmac(bits, padding, outputBits).bytepad(['KMAC', s], w).bytepad([key], w); return new Kmac(bits, padding, outputBits, xof).bytepad(['KMAC', s], w).bytepad([key], w);
}; };
method.update = function (key, message, outputBits, s) { method.update = function (key, message, outputBits, s) {
return method.create(key, outputBits, s).update(message); return method.create(key, outputBits, s).update(message);
}; };
return createOutputMethods(method, createKmacOutputMethod, bits, padding); return createOutputMethods(method, function (b, p, outputType) {
}; return createKmacOutputMethod(b, p, xof, outputType);
}, bits, padding);
var createTupleHashOutputMethod = function (bits, padding, xof, outputType) {
return function (inputs, outputBits, s) {
return methods[(xof ? 'tuplehashxof' : 'tuplehash') + bits].update(inputs, outputBits, s)[outputType]();
};
}; };
var createTupleHashMethod = function (bits, padding, xof) { var createTupleHashMethod = function (bits, padding, xof) {
@@ -210,17 +219,48 @@ var sha3$1 = {exports: {}};
}, bits, padding); }, bits, padding);
}; };
var createParallelHashMethod = function (bits, padding, xof) {
var w = CSHAKE_BYTEPAD[bits];
var method = createParallelHashOutputMethod(bits, padding, xof, 'hex');
method.create = function (blockSize, outputBits, s) {
if (typeof blockSize !== 'number' || !isFinite(blockSize) || blockSize < 1 ||
Math.floor(blockSize) !== blockSize || blockSize > 0x0fffffff) {
throw new Error(BLOCK_SIZE_ERROR);
}
var hash = new ParallelHash(bits, padding, outputBits, xof, blockSize).bytepad(['ParallelHash', s], w);
hash.encode(blockSize, false);
return hash;
};
method.update = function (message, blockSize, outputBits, s) {
return method.create(blockSize, outputBits, s).update(message);
};
return createOutputMethods(method, function (b, p, outputType) {
return createParallelHashOutputMethod(b, p, xof, outputType);
}, bits, padding);
};
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: function (bits, padding) {
return createKmacMethod(bits, padding, false);
}},
{ name: 'kmacxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createKmacMethod(bits, padding, true);
}},
{ name: 'tuplehash', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) { { name: 'tuplehash', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createTupleHashMethod(bits, padding, false); return createTupleHashMethod(bits, padding, false);
}}, }},
{ name: 'tuplehashxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) { { name: 'tuplehashxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createTupleHashMethod(bits, padding, true); return createTupleHashMethod(bits, padding, true);
}},
{ name: 'parallelhash', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createParallelHashMethod(bits, padding, false);
}},
{ name: 'parallelhashxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createParallelHashMethod(bits, padding, true);
}} }}
]; ];
@@ -496,27 +536,27 @@ var sha3$1 = {exports: {}};
return array; return array;
}; };
function Kmac(bits, padding, outputBits) { function Kmac(bits, padding, outputBits, xof) {
Keccak.call(this, bits, padding, outputBits); Keccak.call(this, bits, padding, outputBits);
this.xof = xof;
} }
Kmac.prototype = new Keccak(); Kmac.prototype = new Keccak();
Kmac.prototype.finalize = function () { Kmac.prototype.finalize = function () {
if (!this.finalized) { if (!this.finalized) {
this.encode(this.outputBits, true); this.encode(this.xof ? 0 : this.outputBits, true);
} }
return Keccak.prototype.finalize.call(this); return Keccak.prototype.finalize.call(this);
}; };
function TupleHash(bits, padding, outputBits, xof) { function TupleHash(bits, padding, outputBits, xof) {
Keccak.call(this, bits, padding, outputBits); Kmac.call(this, bits, padding, outputBits, xof);
this.xof = !!xof;
this.inputActive = false; this.inputActive = false;
this.inputBytesRemaining = 0; this.inputBytesRemaining = 0;
} }
TupleHash.prototype = new Keccak(); TupleHash.prototype = new Kmac();
TupleHash.prototype.getMessageByteLength = function (message) { TupleHash.prototype.getMessageByteLength = function (message) {
var result = formatMessage(message); var result = formatMessage(message);
@@ -542,9 +582,6 @@ var sha3$1 = {exports: {}};
}; };
TupleHash.prototype.beginInput = function (byteLength) { TupleHash.prototype.beginInput = function (byteLength) {
if (this.finalized) {
throw new Error(FINALIZE_ERROR);
}
if (this.inputActive) { if (this.inputActive) {
throw new Error(TUPLE_INCOMPLETE_ERROR); throw new Error(TUPLE_INCOMPLETE_ERROR);
} }
@@ -553,28 +590,15 @@ var sha3$1 = {exports: {}};
throw new Error(TUPLE_BYTE_LENGTH_ERROR); throw new Error(TUPLE_BYTE_LENGTH_ERROR);
} }
this.encode(byteLength * 8, false); this.encode(byteLength * 8, false);
if (byteLength === 0) { if (byteLength !== 0) {
this.inputActive = false;
this.inputBytesRemaining = 0;
} else {
this.inputActive = true; this.inputActive = true;
this.inputBytesRemaining = byteLength; this.inputBytesRemaining = byteLength;
} }
return this; return this;
}; };
TupleHash.prototype.updateChunk = function (message) { TupleHash.prototype._updateChunk = function (message, byteLength) {
if (this.finalized) { Kmac.prototype.update.call(this, message);
throw new Error(FINALIZE_ERROR);
}
if (!this.inputActive) {
throw new Error(TUPLE_ACTIVE_ERROR);
}
var byteLength = this.getMessageByteLength(message);
if (byteLength > this.inputBytesRemaining) {
throw new Error(TUPLE_LENGTH_ERROR);
}
Keccak.prototype.update.call(this, message);
this.inputBytesRemaining -= byteLength; this.inputBytesRemaining -= byteLength;
if (this.inputBytesRemaining === 0) { if (this.inputBytesRemaining === 0) {
this.inputActive = false; this.inputActive = false;
@@ -582,29 +606,115 @@ var sha3$1 = {exports: {}};
return this; return this;
}; };
TupleHash.prototype.update = function (message) { TupleHash.prototype.updateChunk = function (message) {
if (this.finalized) { if (!this.inputActive) {
throw new Error(FINALIZE_ERROR); throw new Error(TUPLE_ACTIVE_ERROR);
}
if (this.inputActive) {
throw new Error(TUPLE_INCOMPLETE_ERROR);
} }
var byteLength = this.getMessageByteLength(message); var byteLength = this.getMessageByteLength(message);
this.beginInput(byteLength); if (byteLength > this.inputBytesRemaining) {
if (byteLength === 0) { throw new Error(TUPLE_LENGTH_ERROR);
return this;
} }
return this.updateChunk(message); return this._updateChunk(message, byteLength);
};
TupleHash.prototype.update = function (message) {
var byteLength = this.getMessageByteLength(message);
this.beginInput(byteLength);
return this._updateChunk(message, byteLength);
}; };
TupleHash.prototype.finalize = function () { TupleHash.prototype.finalize = function () {
if (this.inputActive) { if (this.inputActive) {
throw new Error(TUPLE_INCOMPLETE_ERROR); throw new Error(TUPLE_INCOMPLETE_ERROR);
} }
if (!this.finalized) { return Kmac.prototype.finalize.call(this);
this.encode(this.xof ? 0 : this.outputBits, true); };
function ParallelHash(bits, padding, outputBits, xof, blockSize) {
Kmac.call(this, bits, padding, outputBits, xof);
this.bits = bits;
this.blockSize = blockSize;
this.inner = null;
this.innerBytes = 0;
this.blockNumber = 0;
} }
return Keccak.prototype.finalize.call(this);
ParallelHash.prototype = new Kmac();
ParallelHash.prototype._finishInner = function () {
Kmac.prototype.update.call(this, this.inner.array());
this.inner = null;
this.innerBytes = 0;
++this.blockNumber;
};
ParallelHash.prototype._updateBytes = function (message) {
var length = message.length;
if (!length) {
return;
}
var slice = message.subarray || message.slice;
var blockSize = this.blockSize;
var index = 0;
while (index < length) {
if (!this.inner) {
this.inner = new Keccak(this.bits, SHAKE_PADDING, this.bits << 1);
}
var take = blockSize - this.innerBytes;
if (length - index < take) {
take = length - index;
}
this.inner.update(slice.call(message, index, index + take));
this.innerBytes += take;
index += take;
if (this.innerBytes === blockSize) {
this._finishInner();
}
}
};
ParallelHash.prototype.update = function (message) {
if (this.finalized) {
throw new Error(FINALIZE_ERROR);
}
var result = formatMessage(message);
message = result[0];
if (result[1]) {
var bytes = [], length = message.length, index = 0, code, i;
for (i = 0; i < length; ++i) {
code = message.charCodeAt(i);
if (code < 0x80) {
bytes[index++] = code;
} else if (code < 0x800) {
bytes[index++] = (0xc0 | (code >>> 6));
bytes[index++] = (0x80 | (code & 0x3f));
} else if (code < 0xd800 || code >= 0xe000) {
bytes[index++] = (0xe0 | (code >>> 12));
bytes[index++] = (0x80 | ((code >>> 6) & 0x3f));
bytes[index++] = (0x80 | (code & 0x3f));
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++i) & 0x3ff));
bytes[index++] = (0xf0 | (code >>> 18));
bytes[index++] = (0x80 | ((code >>> 12) & 0x3f));
bytes[index++] = (0x80 | ((code >>> 6) & 0x3f));
bytes[index++] = (0x80 | (code & 0x3f));
}
}
message = bytes;
}
this._updateBytes(message);
return this;
};
ParallelHash.prototype.finalize = function () {
if (!this.finalized) {
if (this.inner) {
this._finishInner();
}
this.encode(this.blockNumber, true);
}
return Kmac.prototype.finalize.call(this);
}; };
var f = function (s) { var f = function (s) {
@@ -834,6 +944,10 @@ const {
kmac_256, kmac_256,
kmac128, kmac128,
kmac256, kmac256,
kmacxof_128,
kmacxof_256,
kmacxof128,
kmacxof256,
tuplehash_128, tuplehash_128,
tuplehash_256, tuplehash_256,
@@ -842,7 +956,16 @@ const {
tuplehashxof_128, tuplehashxof_128,
tuplehashxof_256, tuplehashxof_256,
tuplehashxof128, tuplehashxof128,
tuplehashxof256 tuplehashxof256,
parallelhash_128,
parallelhash_256,
parallelhash128,
parallelhash256,
parallelhashxof_128,
parallelhashxof_256,
parallelhashxof128,
parallelhashxof256
} = sha3; } = sha3;
export { cshake128, cshake256, cshake_128, cshake_256, sha3 as default, keccak224, keccak256, keccak384, keccak512, keccak_224, keccak_256, keccak_384, keccak_512, kmac128, kmac256, kmac_128, kmac_256, sha3_224, sha3_256, sha3_384, sha3_512, shake128, shake256, shake_128, shake_256, tuplehash128, tuplehash256, tuplehash_128, tuplehash_256, tuplehashxof128, tuplehashxof256, tuplehashxof_128, tuplehashxof_256 }; export { cshake128, cshake256, cshake_128, cshake_256, sha3 as default, keccak224, keccak256, keccak384, keccak512, keccak_224, keccak_256, keccak_384, keccak_512, kmac128, kmac256, kmac_128, kmac_256, kmacxof128, kmacxof256, kmacxof_128, kmacxof_256, parallelhash128, parallelhash256, parallelhash_128, parallelhash_256, parallelhashxof128, parallelhashxof256, parallelhashxof_128, parallelhashxof_256, sha3_224, sha3_256, sha3_384, sha3_512, shake128, shake256, shake_128, shake_256, tuplehash128, tuplehash256, tuplehash_128, tuplehash_256, tuplehashxof128, tuplehashxof256, tuplehashxof_128, tuplehashxof_256 };
Vendored
+93
View File
@@ -405,6 +405,10 @@ export var kmac_128: KmacHash;
export var kmac_256: KmacHash; export var kmac_256: KmacHash;
export var kmac128: KmacHash; export var kmac128: KmacHash;
export var kmac256: KmacHash; export var kmac256: KmacHash;
export var kmacxof_128: KmacHash;
export var kmacxof_256: KmacHash;
export var kmacxof128: KmacHash;
export var kmacxof256: KmacHash;
export var tuplehash_128: TupleHashMethod; export var tuplehash_128: TupleHashMethod;
export var tuplehash_256: TupleHashMethod; export var tuplehash_256: TupleHashMethod;
export var tuplehash128: TupleHashMethod; export var tuplehash128: TupleHashMethod;
@@ -413,3 +417,92 @@ export var tuplehashxof_128: TupleHashMethod;
export var tuplehashxof_256: TupleHashMethod; export var tuplehashxof_256: TupleHashMethod;
export var tuplehashxof128: TupleHashMethod; export var tuplehashxof128: TupleHashMethod;
export var tuplehashxof256: TupleHashMethod; export var tuplehashxof256: TupleHashMethod;
interface ParallelHash extends Hasher {
/**
* Absorb message bytes into ParallelHash blocks.
*
* @param message The next message chunk.
*/
update(message: Message): ParallelHash;
}
interface ParallelHashMethod {
/**
* Hash and return hex string.
*
* @param message The message you want to hash.
* @param blockSize The ParallelHash block size in bytes.
* @param outputBits The length of output.
* @param customization The customization string.
*/
(message: Message, blockSize: number, outputBits: number, customization: Message): string;
/**
* Hash and return hex string.
*
* @param message The message you want to hash.
* @param blockSize The ParallelHash block size in bytes.
* @param outputBits The length of output.
* @param customization The customization string.
*/
hex(message: Message, blockSize: number, outputBits: number, customization: Message): string;
/**
* Hash and return ArrayBuffer.
*
* @param message The message you want to hash.
* @param blockSize The ParallelHash block size in bytes.
* @param outputBits The length of output.
* @param customization The customization string.
*/
arrayBuffer(message: Message, blockSize: number, outputBits: number, customization: Message): ArrayBuffer;
/**
* Hash and return integer array.
*
* @param message The message you want to hash.
* @param blockSize The ParallelHash block size in bytes.
* @param outputBits The length of output.
* @param customization The customization string.
*/
digest(message: Message, blockSize: number, outputBits: number, customization: Message): number[];
/**
* Hash and return integer array.
*
* @param message The message you want to hash.
* @param blockSize The ParallelHash block size in bytes.
* @param outputBits The length of output.
* @param customization The customization string.
*/
array(message: Message, blockSize: number, outputBits: number, customization: Message): number[];
/**
* Create a ParallelHash object.
*
* @param blockSize The ParallelHash block size in bytes.
* @param outputBits The length of output.
* @param customization The customization string.
*/
create(blockSize: number, outputBits: number, customization: Message): ParallelHash;
/**
* Create a ParallelHash object and hash message.
*
* @param message The message you want to hash.
* @param blockSize The ParallelHash block size in bytes.
* @param outputBits The length of output.
* @param customization The customization string.
*/
update(message: Message, blockSize: number, outputBits: number, customization: Message): ParallelHash;
}
export var parallelhash_128: ParallelHashMethod;
export var parallelhash_256: ParallelHashMethod;
export var parallelhash128: ParallelHashMethod;
export var parallelhash256: ParallelHashMethod;
export var parallelhashxof_128: ParallelHashMethod;
export var parallelhashxof_256: ParallelHashMethod;
export var parallelhashxof128: ParallelHashMethod;
export var parallelhashxof256: ParallelHashMethod;
+940 -1116
View File
File diff suppressed because it is too large Load Diff
+14 -6
View File
@@ -1,7 +1,7 @@
{ {
"name": "js-sha3", "name": "js-sha3",
"version": "0.11.0", "version": "0.13.0",
"description": "A simple SHA-3 / Keccak / SHAKE / cSHAKE / KMAC / TupleHash hash function for JavaScript supports UTF-8 encoding.", "description": "A simple SHA-3 / Keccak / SHAKE / cSHAKE / KMAC / TupleHash / ParallelHash hash function for JavaScript supports UTF-8 encoding.",
"main": "src/sha3.js", "main": "src/sha3.js",
"module": "build/sha3.mjs", "module": "build/sha3.mjs",
"exports": { "exports": {
@@ -22,17 +22,20 @@
"@rollup/plugin-commonjs": "^28.0.5", "@rollup/plugin-commonjs": "^28.0.5",
"@rollup/plugin-terser": "^1.0.0", "@rollup/plugin-terser": "^1.0.0",
"expect.js": "~0.3.1", "expect.js": "~0.3.1",
"mocha": "^11.7.6", "mocha": "^11.8.0",
"nyc": "^15.1.0", "nyc": "^18.0.0",
"rollup": "^4.43.0", "rollup": "^4.43.0",
"tiny-worker": "^2.3.0", "tiny-worker": "^2.3.0",
"uglify-js": "^3.1.9" "uglify-js": "^3.1.9"
}, },
"scripts": { "scripts": {
"test": "nyc mocha tests/node-test.js", "test": "npm run build && npm run test:coverage",
"test:runtime": "mocha tests/node-test.js",
"test:coverage": "nyc --reporter=text --reporter=html --reporter=lcov mocha tests/node-test.js",
"report": "nyc --reporter=html --reporter=text mocha tests/node-test.js", "report": "nyc --reporter=html --reporter=text mocha tests/node-test.js",
"coveralls": "nyc report --reporter=text-lcov | coveralls", "coveralls": "nyc report --reporter=text-lcov | coveralls",
"build": "rollup -c && uglifyjs src/sha3.js -c -m --comments --output build/sha3.min.js" "build": "rollup -c && uglifyjs src/sha3.js -c -m --comments --output build/sha3.min.js",
"prepack": "npm run build"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -45,6 +48,7 @@
"cshake", "cshake",
"kmac", "kmac",
"tuplehash", "tuplehash",
"parallelhash",
"hash", "hash",
"encryption", "encryption",
"cryptography", "cryptography",
@@ -60,5 +64,9 @@
"exclude": [ "exclude": [
"tests" "tests"
] ]
},
"overrides": {
"diff": "^8.0.3",
"serialize-javascript": "^7.0.7"
} }
} }
+162 -52
View File
@@ -1,9 +1,9 @@
/** /**
* [js-sha3]{@link https://github.com/emn178/js-sha3} * [js-sha3]{@link https://github.com/emn178/js-sha3}
* *
* @version 0.11.0 * @version 0.13.0
* @author Chen, Yi-Cyuan [emn178@gmail.com] * @author Chen, Yi-Cyuan [emn178@gmail.com]
* @copyright Chen, Yi-Cyuan 2015-2023 * @copyright Chen, Yi-Cyuan 2015-2026
* @license MIT * @license MIT
*/ */
/*jslint bitwise: true */ /*jslint bitwise: true */
@@ -16,6 +16,7 @@
var TUPLE_INCOMPLETE_ERROR = 'tuple input is incomplete'; var TUPLE_INCOMPLETE_ERROR = 'tuple input is incomplete';
var TUPLE_LENGTH_ERROR = 'tuple input exceeds declared length'; var TUPLE_LENGTH_ERROR = 'tuple input exceeds declared length';
var TUPLE_BYTE_LENGTH_ERROR = 'tuple input byte length is invalid'; var TUPLE_BYTE_LENGTH_ERROR = 'tuple input byte length is invalid';
var BLOCK_SIZE_ERROR = 'block size is invalid';
var WINDOW = typeof window === 'object'; var WINDOW = typeof window === 'object';
var root = WINDOW ? window : {}; var root = WINDOW ? window : {};
if (root.JS_SHA3_NO_WINDOW) { if (root.JS_SHA3_NO_WINDOW) {
@@ -111,9 +112,21 @@
}; };
}; };
var createKmacOutputMethod = function (bits, padding, outputType) { var createKmacOutputMethod = function (bits, padding, xof, outputType) {
return function (key, message, outputBits, s) { return function (key, message, outputBits, s) {
return methods['kmac' + bits].update(key, message, outputBits, s)[outputType](); return methods[(xof ? 'kmacxof' : 'kmac') + bits].update(key, message, outputBits, s)[outputType]();
};
};
var createTupleHashOutputMethod = function (bits, padding, xof, outputType) {
return function (inputs, outputBits, s) {
return methods[(xof ? 'tuplehashxof' : 'tuplehash') + bits].update(inputs, outputBits, s)[outputType]();
};
};
var createParallelHashOutputMethod = function (bits, padding, xof, outputType) {
return function (message, blockSize, outputBits, s) {
return methods[(xof ? 'parallelhashxof' : 'parallelhash') + bits].update(message, blockSize, outputBits, s)[outputType]();
}; };
}; };
@@ -163,22 +176,18 @@
return createOutputMethods(method, createCshakeOutputMethod, bits, padding); return createOutputMethods(method, createCshakeOutputMethod, bits, padding);
}; };
var createKmacMethod = function (bits, padding) { var createKmacMethod = function (bits, padding, xof) {
var w = CSHAKE_BYTEPAD[bits]; var w = CSHAKE_BYTEPAD[bits];
var method = createKmacOutputMethod(bits, padding, 'hex'); var method = createKmacOutputMethod(bits, padding, xof, 'hex');
method.create = function (key, outputBits, s) { method.create = function (key, outputBits, s) {
return new Kmac(bits, padding, outputBits).bytepad(['KMAC', s], w).bytepad([key], w); return new Kmac(bits, padding, outputBits, xof).bytepad(['KMAC', s], w).bytepad([key], w);
}; };
method.update = function (key, message, outputBits, s) { method.update = function (key, message, outputBits, s) {
return method.create(key, outputBits, s).update(message); return method.create(key, outputBits, s).update(message);
}; };
return createOutputMethods(method, createKmacOutputMethod, bits, padding); return createOutputMethods(method, function (b, p, outputType) {
}; return createKmacOutputMethod(b, p, xof, outputType);
}, bits, padding);
var createTupleHashOutputMethod = function (bits, padding, xof, outputType) {
return function (inputs, outputBits, s) {
return methods[(xof ? 'tuplehashxof' : 'tuplehash') + bits].update(inputs, outputBits, s)[outputType]();
};
}; };
var createTupleHashMethod = function (bits, padding, xof) { var createTupleHashMethod = function (bits, padding, xof) {
@@ -202,17 +211,48 @@
}, bits, padding); }, bits, padding);
}; };
var createParallelHashMethod = function (bits, padding, xof) {
var w = CSHAKE_BYTEPAD[bits];
var method = createParallelHashOutputMethod(bits, padding, xof, 'hex');
method.create = function (blockSize, outputBits, s) {
if (typeof blockSize !== 'number' || !isFinite(blockSize) || blockSize < 1 ||
Math.floor(blockSize) !== blockSize || blockSize > 0x0fffffff) {
throw new Error(BLOCK_SIZE_ERROR);
}
var hash = new ParallelHash(bits, padding, outputBits, xof, blockSize).bytepad(['ParallelHash', s], w);
hash.encode(blockSize, false);
return hash;
};
method.update = function (message, blockSize, outputBits, s) {
return method.create(blockSize, outputBits, s).update(message);
};
return createOutputMethods(method, function (b, p, outputType) {
return createParallelHashOutputMethod(b, p, xof, outputType);
}, bits, padding);
};
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: function (bits, padding) {
return createKmacMethod(bits, padding, false);
}},
{ name: 'kmacxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createKmacMethod(bits, padding, true);
}},
{ name: 'tuplehash', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) { { name: 'tuplehash', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createTupleHashMethod(bits, padding, false); return createTupleHashMethod(bits, padding, false);
}}, }},
{ name: 'tuplehashxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) { { name: 'tuplehashxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createTupleHashMethod(bits, padding, true); return createTupleHashMethod(bits, padding, true);
}},
{ name: 'parallelhash', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createParallelHashMethod(bits, padding, false);
}},
{ name: 'parallelhashxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
return createParallelHashMethod(bits, padding, true);
}} }}
]; ];
@@ -488,27 +528,27 @@
return array; return array;
}; };
function Kmac(bits, padding, outputBits) { function Kmac(bits, padding, outputBits, xof) {
Keccak.call(this, bits, padding, outputBits); Keccak.call(this, bits, padding, outputBits);
this.xof = xof;
} }
Kmac.prototype = new Keccak(); Kmac.prototype = new Keccak();
Kmac.prototype.finalize = function () { Kmac.prototype.finalize = function () {
if (!this.finalized) { if (!this.finalized) {
this.encode(this.outputBits, true); this.encode(this.xof ? 0 : this.outputBits, true);
} }
return Keccak.prototype.finalize.call(this); return Keccak.prototype.finalize.call(this);
}; };
function TupleHash(bits, padding, outputBits, xof) { function TupleHash(bits, padding, outputBits, xof) {
Keccak.call(this, bits, padding, outputBits); Kmac.call(this, bits, padding, outputBits, xof);
this.xof = !!xof;
this.inputActive = false; this.inputActive = false;
this.inputBytesRemaining = 0; this.inputBytesRemaining = 0;
} }
TupleHash.prototype = new Keccak(); TupleHash.prototype = new Kmac();
TupleHash.prototype.getMessageByteLength = function (message) { TupleHash.prototype.getMessageByteLength = function (message) {
var result = formatMessage(message); var result = formatMessage(message);
@@ -534,9 +574,6 @@
}; };
TupleHash.prototype.beginInput = function (byteLength) { TupleHash.prototype.beginInput = function (byteLength) {
if (this.finalized) {
throw new Error(FINALIZE_ERROR);
}
if (this.inputActive) { if (this.inputActive) {
throw new Error(TUPLE_INCOMPLETE_ERROR); throw new Error(TUPLE_INCOMPLETE_ERROR);
} }
@@ -545,28 +582,15 @@
throw new Error(TUPLE_BYTE_LENGTH_ERROR); throw new Error(TUPLE_BYTE_LENGTH_ERROR);
} }
this.encode(byteLength * 8, false); this.encode(byteLength * 8, false);
if (byteLength === 0) { if (byteLength !== 0) {
this.inputActive = false;
this.inputBytesRemaining = 0;
} else {
this.inputActive = true; this.inputActive = true;
this.inputBytesRemaining = byteLength; this.inputBytesRemaining = byteLength;
} }
return this; return this;
}; };
TupleHash.prototype.updateChunk = function (message) { TupleHash.prototype._updateChunk = function (message, byteLength) {
if (this.finalized) { Kmac.prototype.update.call(this, message);
throw new Error(FINALIZE_ERROR);
}
if (!this.inputActive) {
throw new Error(TUPLE_ACTIVE_ERROR);
}
var byteLength = this.getMessageByteLength(message);
if (byteLength > this.inputBytesRemaining) {
throw new Error(TUPLE_LENGTH_ERROR);
}
Keccak.prototype.update.call(this, message);
this.inputBytesRemaining -= byteLength; this.inputBytesRemaining -= byteLength;
if (this.inputBytesRemaining === 0) { if (this.inputBytesRemaining === 0) {
this.inputActive = false; this.inputActive = false;
@@ -574,29 +598,115 @@
return this; return this;
}; };
TupleHash.prototype.update = function (message) { TupleHash.prototype.updateChunk = function (message) {
if (this.finalized) { if (!this.inputActive) {
throw new Error(FINALIZE_ERROR); throw new Error(TUPLE_ACTIVE_ERROR);
}
if (this.inputActive) {
throw new Error(TUPLE_INCOMPLETE_ERROR);
} }
var byteLength = this.getMessageByteLength(message); var byteLength = this.getMessageByteLength(message);
this.beginInput(byteLength); if (byteLength > this.inputBytesRemaining) {
if (byteLength === 0) { throw new Error(TUPLE_LENGTH_ERROR);
return this;
} }
return this.updateChunk(message); return this._updateChunk(message, byteLength);
};
TupleHash.prototype.update = function (message) {
var byteLength = this.getMessageByteLength(message);
this.beginInput(byteLength);
return this._updateChunk(message, byteLength);
}; };
TupleHash.prototype.finalize = function () { TupleHash.prototype.finalize = function () {
if (this.inputActive) { if (this.inputActive) {
throw new Error(TUPLE_INCOMPLETE_ERROR); throw new Error(TUPLE_INCOMPLETE_ERROR);
} }
if (!this.finalized) { return Kmac.prototype.finalize.call(this);
this.encode(this.xof ? 0 : this.outputBits, true); };
function ParallelHash(bits, padding, outputBits, xof, blockSize) {
Kmac.call(this, bits, padding, outputBits, xof);
this.bits = bits;
this.blockSize = blockSize;
this.inner = null;
this.innerBytes = 0;
this.blockNumber = 0;
} }
return Keccak.prototype.finalize.call(this);
ParallelHash.prototype = new Kmac();
ParallelHash.prototype._finishInner = function () {
Kmac.prototype.update.call(this, this.inner.array());
this.inner = null;
this.innerBytes = 0;
++this.blockNumber;
};
ParallelHash.prototype._updateBytes = function (message) {
var length = message.length;
if (!length) {
return;
}
var slice = message.subarray || message.slice;
var blockSize = this.blockSize;
var index = 0;
while (index < length) {
if (!this.inner) {
this.inner = new Keccak(this.bits, SHAKE_PADDING, this.bits << 1);
}
var take = blockSize - this.innerBytes;
if (length - index < take) {
take = length - index;
}
this.inner.update(slice.call(message, index, index + take));
this.innerBytes += take;
index += take;
if (this.innerBytes === blockSize) {
this._finishInner();
}
}
};
ParallelHash.prototype.update = function (message) {
if (this.finalized) {
throw new Error(FINALIZE_ERROR);
}
var result = formatMessage(message);
message = result[0];
if (result[1]) {
var bytes = [], length = message.length, index = 0, code, i;
for (i = 0; i < length; ++i) {
code = message.charCodeAt(i);
if (code < 0x80) {
bytes[index++] = code;
} else if (code < 0x800) {
bytes[index++] = (0xc0 | (code >>> 6));
bytes[index++] = (0x80 | (code & 0x3f));
} else if (code < 0xd800 || code >= 0xe000) {
bytes[index++] = (0xe0 | (code >>> 12));
bytes[index++] = (0x80 | ((code >>> 6) & 0x3f));
bytes[index++] = (0x80 | (code & 0x3f));
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++i) & 0x3ff));
bytes[index++] = (0xf0 | (code >>> 18));
bytes[index++] = (0x80 | ((code >>> 12) & 0x3f));
bytes[index++] = (0x80 | ((code >>> 6) & 0x3f));
bytes[index++] = (0x80 | (code & 0x3f));
}
}
message = bytes;
}
this._updateBytes(message);
return this;
};
ParallelHash.prototype.finalize = function () {
if (!this.finalized) {
if (this.inner) {
this._finishInner();
}
this.encode(this.blockNumber, true);
}
return Kmac.prototype.finalize.call(this);
}; };
var f = function (s) { var f = function (s) {
+14 -1
View File
@@ -29,6 +29,10 @@ export const {
kmac_256, kmac_256,
kmac128, kmac128,
kmac256, kmac256,
kmacxof_128,
kmacxof_256,
kmacxof128,
kmacxof256,
tuplehash_128, tuplehash_128,
tuplehash_256, tuplehash_256,
@@ -37,7 +41,16 @@ export const {
tuplehashxof_128, tuplehashxof_128,
tuplehashxof_256, tuplehashxof_256,
tuplehashxof128, tuplehashxof128,
tuplehashxof256 tuplehashxof256,
parallelhash_128,
parallelhash_256,
parallelhash128,
parallelhash256,
parallelhashxof_128,
parallelhashxof_256,
parallelhashxof128,
parallelhashxof256
} = sha3; } = sha3;
export default sha3; export default sha3;
+19
View File
@@ -16,10 +16,16 @@ function unset() {
shake256 = null; shake256 = null;
kmac128 = null; kmac128 = null;
kmac256 = null; kmac256 = null;
kmacxof128 = null;
kmacxof256 = null;
tuplehash128 = null; tuplehash128 = null;
tuplehash256 = null; tuplehash256 = null;
tuplehashxof128 = null; tuplehashxof128 = null;
tuplehashxof256 = null; tuplehashxof256 = null;
parallelhash128 = null;
parallelhash256 = null;
parallelhashxof128 = null;
parallelhashxof256 = null;
BUFFER = undefined; BUFFER = undefined;
JS_SHA3_NO_WINDOW = undefined; JS_SHA3_NO_WINDOW = undefined;
JS_SHA3_NO_NODE_JS = undefined; JS_SHA3_NO_NODE_JS = undefined;
@@ -45,10 +51,16 @@ function requireToGlobal() {
cshake256 = sha3.cshake256; cshake256 = sha3.cshake256;
kmac128 = sha3.kmac128; kmac128 = sha3.kmac128;
kmac256 = sha3.kmac256; kmac256 = sha3.kmac256;
kmacxof128 = sha3.kmacxof128;
kmacxof256 = sha3.kmacxof256;
tuplehash128 = sha3.tuplehash128; tuplehash128 = sha3.tuplehash128;
tuplehash256 = sha3.tuplehash256; tuplehash256 = sha3.tuplehash256;
tuplehashxof128 = sha3.tuplehashxof128; tuplehashxof128 = sha3.tuplehashxof128;
tuplehashxof256 = sha3.tuplehashxof256; tuplehashxof256 = sha3.tuplehashxof256;
parallelhash128 = sha3.parallelhash128;
parallelhash256 = sha3.parallelhash256;
parallelhashxof128 = sha3.parallelhashxof128;
parallelhashxof256 = sha3.parallelhashxof256;
} }
function runCommonJsTest() { function runCommonJsTest() {
@@ -66,6 +78,7 @@ function runWindowTest(extra) {
require('./test-cshake.js'); require('./test-cshake.js');
require('./test-kmac.js'); require('./test-kmac.js');
require('./test-tuplehash.js'); require('./test-tuplehash.js');
require('./test-parallelhash.js');
} }
unset(); unset();
} }
@@ -117,10 +130,16 @@ define = function (func) {
cshake256 = sha3.cshake256; cshake256 = sha3.cshake256;
kmac128 = sha3.kmac128; kmac128 = sha3.kmac128;
kmac256 = sha3.kmac256; kmac256 = sha3.kmac256;
kmacxof128 = sha3.kmacxof128;
kmacxof256 = sha3.kmacxof256;
tuplehash128 = sha3.tuplehash128; tuplehash128 = sha3.tuplehash128;
tuplehash256 = sha3.tuplehash256; tuplehash256 = sha3.tuplehash256;
tuplehashxof128 = sha3.tuplehashxof128; tuplehashxof128 = sha3.tuplehashxof128;
tuplehashxof256 = sha3.tuplehashxof256; tuplehashxof256 = sha3.tuplehashxof256;
parallelhash128 = sha3.parallelhash128;
parallelhash256 = sha3.parallelhash256;
parallelhashxof128 = sha3.parallelhashxof128;
parallelhashxof256 = sha3.parallelhashxof256;
require('./test.js'); require('./test.js');
}; };
define.amd = true; define.amd = true;
+98 -59
View File
@@ -1,26 +1,9 @@
(function (kmac256, kmac128) { (function (kmac256, kmac128, kmacxof256, kmacxof128) {
// http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/KMAC_samples.pdf // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/KMAC_samples.pdf
var testCases = [ // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMACXOF_samples.pdf
{ var key = [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F];
name: 'kmac128', var shortInput = [0x00, 0x01, 0x02, 0x03];
method: kmac128, var longInput = [
cases: [
{
input: [0x00, 0x01, 0x02, 0x03],
bits: 256,
key: [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F],
s: '',
output: 'e5780b0d3ea6f7d3a429c5706aa43a00fadbd7d49628839e3187243f456ee14e'
},
{
input: [0x00, 0x01, 0x02, 0x03],
bits: 256,
key: [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F],
s: 'My Tagged Application',
output: '3b1fba963cd8b0b59e8c1a6d71888b7143651af8ba0a7070c0979e2811324aa5'
},
{
input: [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
@@ -34,9 +17,31 @@
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7
], ];
var testCases = [
{
name: 'kmac128',
method: kmac128,
cases: [
{
input: shortInput,
bits: 256, bits: 256,
key: [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F], key: key,
s: '',
output: 'e5780b0d3ea6f7d3a429c5706aa43a00fadbd7d49628839e3187243f456ee14e'
},
{
input: shortInput,
bits: 256,
key: key,
s: 'My Tagged Application',
output: '3b1fba963cd8b0b59e8c1a6d71888b7143651af8ba0a7070c0979e2811324aa5'
},
{
input: longInput,
bits: 256,
key: key,
s: 'My Tagged Application', s: 'My Tagged Application',
output: '1f5b4e6cca02209e0dcb5ca635b89a15e271ecc760071dfd805faa38f9729230' output: '1f5b4e6cca02209e0dcb5ca635b89a15e271ecc760071dfd805faa38f9729230'
} }
@@ -47,51 +52,23 @@
method: kmac256, method: kmac256,
cases: [ cases: [
{ {
input: [0x00, 0x01, 0x02, 0x03], input: shortInput,
bits: 512, bits: 512,
key: [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F], key: key,
s: 'My Tagged Application', s: 'My Tagged Application',
output: '20c570c31346f703c9ac36c61c03cb64c3970d0cfc787e9b79599d273a68d2f7f69d4cc3de9d104a351689f27cf6f5951f0103f33f4f24871024d9c27773a8dd' output: '20c570c31346f703c9ac36c61c03cb64c3970d0cfc787e9b79599d273a68d2f7f69d4cc3de9d104a351689f27cf6f5951f0103f33f4f24871024d9c27773a8dd'
}, },
{ {
input: [ input: longInput,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7
],
bits: 512, bits: 512,
key: [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F], key: key,
s: '', s: '',
output: '75358cf39e41494e949707927cee0af20a3ff553904c86b08f21cc414bcfd691589d27cf5e15369cbbff8b9a4c2eb17800855d0235ff635da82533ec6b759b69' output: '75358cf39e41494e949707927cee0af20a3ff553904c86b08f21cc414bcfd691589d27cf5e15369cbbff8b9a4c2eb17800855d0235ff635da82533ec6b759b69'
}, },
{ {
input: [ input: longInput,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7
],
bits: 512, bits: 512,
key: [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F], key: key,
s: 'My Tagged Application', s: 'My Tagged Application',
output: 'b58618f71f92e1d56c1b8c55ddd7cd188b97b4ca4d99831eb2699a837da2e4d970fbacfde50033aea585f1a2708510c32d07880801bd182898fe476876fc8965' output: 'b58618f71f92e1d56c1b8c55ddd7cd188b97b4ca4d99831eb2699a837da2e4d970fbacfde50033aea585f1a2708510c32d07880801bd182898fe476876fc8965'
}, },
@@ -103,6 +80,60 @@
output: '031801b0b50ebeef772fbe7a279bc144' output: '031801b0b50ebeef772fbe7a279bc144'
} }
] ]
},
{
name: 'kmacxof128',
method: kmacxof128,
cases: [
{
input: shortInput,
bits: 256,
key: key,
s: '',
output: 'cd83740bbd92ccc8cf032b1481a0f4460e7ca9dd12b08a0c4031178bacd6ec35'
},
{
input: shortInput,
bits: 256,
key: key,
s: 'My Tagged Application',
output: '31a44527b4ed9f5c6101d11de6d26f0620aa5c341def41299657fe9df1a3b16c'
},
{
input: longInput,
bits: 256,
key: key,
s: 'My Tagged Application',
output: '47026c7cd793084aa0283c253ef658490c0db61438b8326fe9bddf281b83ae0f'
}
]
},
{
name: 'kmacxof256',
method: kmacxof256,
cases: [
{
input: shortInput,
bits: 512,
key: key,
s: 'My Tagged Application',
output: '1755133f1534752aad0748f2c706fb5c784512cab835cd15676b16c0c6647fa96faa7af634a0bf8ff6df39374fa00fad9a39e322a7c92065a64eb1fb0801eb2b'
},
{
input: longInput,
bits: 512,
key: key,
s: '',
output: 'ff7b171f1e8a2b24683eed37830ee797538ba8dc563f6da1e667391a75edc02ca633079f81ce12a25f45615ec89972031d18337331d24ceb8f8ca8e6a19fd98b'
},
{
input: longInput,
bits: 512,
key: key,
s: 'My Tagged Application',
output: 'd5be731c954ed7732846bb59dbe3a8e30f83e77a4bff4459f2f1c2b4ecebb8ce67ba01c62e8ab8578d2d499bd1bb276768781190020a306a97de281dcc30305d'
}
]
} }
]; ];
@@ -115,4 +146,12 @@
}); });
}); });
}); });
})(kmac256, kmac128);
describe('#kmacxof aliases', function () {
it('should export identical aliases', function () {
var sha3 = require('../src/sha3.js');
expect(sha3.kmacxof128).to.be(sha3.kmacxof_128);
expect(sha3.kmacxof256).to.be(sha3.kmacxof_256);
});
});
})(kmac256, kmac128, kmacxof256, kmacxof128);
+251
View File
@@ -0,0 +1,251 @@
(function (parallelhash256, parallelhash128, parallelhashxof256, parallelhashxof128) {
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/ParallelHash_samples.pdf
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/ParallelHashXOF_samples.pdf
var d1 = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
];
var d2 = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b
];
var testCases = [
{
name: 'parallelhash128',
method: parallelhash128,
cases: [
{
message: d1,
blockSize: 8,
bits: 256,
s: '',
output: 'ba8dc1d1d979331d3f813603c67f72609ab5e44b94a0b8f9af46514454a2b4f5'
},
{
message: d1,
blockSize: 8,
bits: 256,
s: 'Parallel Data',
output: 'fc484dcb3f84dceedc353438151bee58157d6efed0445a81f165e495795b7206'
},
{
message: d2,
blockSize: 12,
bits: 256,
s: 'Parallel Data',
output: 'f7fd5312896c6685c828af7e2adb97e393e7f8d54e3c2ea4b95e5aca3796e8fc'
}
]
},
{
name: 'parallelhash256',
method: parallelhash256,
cases: [
{
message: d1,
blockSize: 8,
bits: 512,
s: '',
output: 'bc1ef124da34495e948ead207dd9842235da432d2bbc54b4c110e64c451105531b7f2a3e0ce055c02805e7c2de1fb746af97a1dd01f43b824e31b87612410429'
},
{
message: d1,
blockSize: 8,
bits: 512,
s: 'Parallel Data',
output: 'cdf15289b54f6212b4bc270528b49526006dd9b54e2b6add1ef6900dda3963bb33a72491f236969ca8afaea29c682d47a393c065b38e29fae651a2091c833110'
},
{
message: d2,
blockSize: 12,
bits: 512,
s: 'Parallel Data',
output: '69d0fcb764ea055dd09334bc6021cb7e4b61348dff375da262671cdec3effa8d1b4568a6cce16b1cad946ddde27f6ce2b8dee4cd1b24851ebf00eb90d43813e9'
}
]
},
{
name: 'parallelhashxof128',
method: parallelhashxof128,
cases: [
{
message: d1,
blockSize: 8,
bits: 256,
s: '',
output: 'fe47d661e49ffe5b7d999922c062356750caf552985b8e8ce6667f2727c3c8d3'
},
{
message: d1,
blockSize: 8,
bits: 256,
s: 'Parallel Data',
output: 'ea2a793140820f7a128b8eb70a9439f93257c6e6e79b4a540d291d6dae7098d7'
},
{
message: d2,
blockSize: 12,
bits: 256,
s: 'Parallel Data',
output: '0127ad9772ab904691987fcc4a24888f341fa0db2145e872d4efd255376602f0'
}
]
},
{
name: 'parallelhashxof256',
method: parallelhashxof256,
cases: [
{
message: d1,
blockSize: 8,
bits: 512,
s: '',
output: 'c10a052722614684144d28474850b410757e3cba87651ba167a5cbddff7f466675fbf84bcae7378ac444be681d729499afca667fb879348bfdda427863c82f1c'
},
{
message: d1,
blockSize: 8,
bits: 512,
s: 'Parallel Data',
output: '538e105f1a22f44ed2f5cc1674fbd40be803d9c99bf5f8d90a2c8193f3fe6ea768e5c1a20987e2c9c65febed03887a51d35624ed12377594b5585541dc377efc'
},
{
message: d2,
blockSize: 12,
bits: 512,
s: 'Parallel Data',
output: '6b3e790b330c889a204c2fbc728d809f19367328d852f4002dc829f73afd6bcefb7fe5b607b13a801c0be5c1170bdb794e339458fdb0e62a6af3d42558970249'
}
]
}
];
testCases.forEach(function (testCase) {
describe('#' + testCase.name, function () {
testCase.cases.forEach(function (c) {
it('should match NIST sample vector', function () {
expect(testCase.method(c.message, c.blockSize, c.bits, c.s)).to.be(c.output);
});
});
});
});
describe('#parallelhash API', function () {
it('should match instance update and method update with one-shot', function () {
var expected = parallelhash128(d1, 8, 256, 'cache');
var incremental = parallelhash128.create(8, 256, 'cache').update(d1.slice(0, 10)).update(d1.slice(10)).hex();
var methodUpdate = parallelhash128.update(d1.slice(0, 5), 8, 256, 'cache').update(d1.slice(5)).hex();
expect(incremental).to.be(expected);
expect(methodUpdate).to.be(expected);
expect(parallelhash128.update(d1, 8, 256, 'cache').hex()).to.be(expected);
});
it('should stream binary messages in irregular chunks', function () {
var expected = parallelhash128(d2, 12, 256, '');
var hash = parallelhash128.create(12, 256, '');
hash.update(d2.slice(0, 1));
hash.update(d2.slice(1, 17));
hash.update(d2.slice(17, 50));
hash.update(d2.slice(50));
expect(hash.hex()).to.be(expected);
});
it('should stream ArrayBuffer and Uint8Array views', function () {
var expected = parallelhash128(d1, 8, 256, '');
var buffer = new Uint8Array(d1).buffer;
var view = new Uint8Array(new Uint8Array(d1).buffer, 0, d1.length);
expect(parallelhash128.create(8, 256, '').update(buffer).hex()).to.be(expected);
expect(parallelhash128.create(8, 256, '').update(view).hex()).to.be(expected);
});
it('should hash empty message with n = 0', function () {
var empty = parallelhash128([], 8, 256, '');
var emptyString = parallelhash128('', 8, 256, '');
expect(empty).to.be(emptyString);
expect(empty).to.not.be(parallelhash128([0x00], 8, 256, ''));
});
it('should handle UTF-8 strings across block boundaries', function () {
var message = 'åbc'; // 2 + 1 + 1 = 4 UTF-8 bytes
var expected = parallelhash128(message, 3, 256, '');
var hash = parallelhash128.create(3, 256, '');
hash.update('å').update('bc');
expect(hash.hex()).to.be(expected);
});
it('should encode 3-byte and 4-byte UTF-8 characters', function () {
var message = '中\uE000\uD83D\uDE00'; // 3 + 3 + 4 = 10 UTF-8 bytes
var expected = parallelhash128(message, 4, 256, '');
var hash = parallelhash128.create(4, 256, '');
hash.update('中').update('\uE000').update('\uD83D\uDE00');
expect(hash.hex()).to.be(expected);
expect(hash.array().length).to.be(32);
});
it('should keep absorbing when update is shorter than remaining block space', function () {
var expected = parallelhash128(d1, 8, 256, '');
var hash = parallelhash128.create(8, 256, '');
hash.update(d1.slice(0, 3)); // partial inner block, need 5 more
hash.update(d1.slice(3, 5)); // still short, continue same inner SHAKE
hash.update(d1.slice(5)); // finish remaining blocks
expect(hash.hex()).to.be(expected);
});
it('should not be affected by mutating input after update', function () {
var expected = parallelhash128(d1, 8, 256, '');
var chunk = new Uint8Array(d1.slice(0, 3));
var rest = new Uint8Array(d1.slice(3));
var hash = parallelhash128.create(8, 256, '');
hash.update(chunk);
chunk[0] = 0xff;
chunk[1] = 0xff;
chunk[2] = 0xff;
hash.update(rest);
expect(hash.hex()).to.be(expected);
});
it('should allow repeated output representations', function () {
var hash = parallelhash128.create(8, 256, '').update(d1);
var hex = hash.hex();
var array = hash.array();
var digest = hash.digest();
var buffer = hash.arrayBuffer();
expect(hash.hex()).to.be(hex);
expect(array).to.eql(digest);
expect(Array.prototype.slice.call(new Uint8Array(buffer))).to.eql(array);
expect(function () { hash.update(d1); }).to.throwError(/finalize already called/);
});
it('should require customization like KMAC', function () {
expect(function () { parallelhash128(d1, 8, 256); }).to.throwError(/input is invalid type/);
});
it('should reject invalid block sizes', function () {
expect(function () { parallelhash128.create(0, 256, ''); }).to.throwError(/block size is invalid/);
expect(function () { parallelhash128.create(-1, 256, ''); }).to.throwError(/block size is invalid/);
expect(function () { parallelhash128.create(1.5, 256, ''); }).to.throwError(/block size is invalid/);
expect(function () { parallelhash128.create(NaN, 256, ''); }).to.throwError(/block size is invalid/);
expect(function () { parallelhash128.create(0x20000000, 256, ''); }).to.throwError(/block size is invalid/);
});
it('should export identical aliases', function () {
var sha3 = require('../src/sha3.js');
expect(sha3.parallelhash128).to.be(sha3.parallelhash_128);
expect(sha3.parallelhash256).to.be(sha3.parallelhash_256);
expect(sha3.parallelhashxof128).to.be(sha3.parallelhashxof_128);
expect(sha3.parallelhashxof256).to.be(sha3.parallelhashxof_256);
});
it('should reject update after finalize', function () {
var hash = parallelhash128.create(8, 256, '').update([0x00]);
hash.hex();
expect(function () { hash.update([0x01]); }).to.throwError(/finalize already called/);
});
});
})(parallelhash256, parallelhash128, parallelhashxof256, parallelhashxof128);
+1 -1
View File
@@ -203,7 +203,7 @@
expect(array).to.eql(digest); expect(array).to.eql(digest);
expect(Array.prototype.slice.call(new Uint8Array(buffer))).to.eql(array); expect(Array.prototype.slice.call(new Uint8Array(buffer))).to.eql(array);
expect(function () { hash.update(t1); }).to.throwError(/finalize already called/); expect(function () { hash.update(t1); }).to.throwError(/finalize already called/);
expect(function () { hash.updateChunk(t1); }).to.throwError(/finalize already called/); expect(function () { hash.updateChunk(t1); }).to.throwError(/no active tuple input/);
}); });
it('should require customization like KMAC', function () { it('should require customization like KMAC', function () {