mirror of
https://github.com/emn178/js-sha3.git
synced 2026-08-12 19:41:36 +08:00
Compare commits
12
Commits
v0.9.3
...
c3fc9645d4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3fc9645d4 | ||
|
|
59d5441220 | ||
|
|
a67f74cf2c | ||
|
|
d506b22f67 | ||
|
|
5f95ceb733 | ||
|
|
01b1baf1e7 | ||
|
|
f0ab0aec2c | ||
|
|
951408a3aa | ||
|
|
00d3aa232f | ||
|
|
83e468af79 | ||
|
|
d1ab318829 | ||
|
|
6efde1cf1b |
@@ -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
|
||||||
@@ -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
|
||||||
@@ -2,6 +2,5 @@
|
|||||||
/coverage/
|
/coverage/
|
||||||
/.nyc_output/
|
/.nyc_output/
|
||||||
/tests/
|
/tests/
|
||||||
.travis.yml
|
|
||||||
.npmignore
|
.npmignore
|
||||||
bower.json
|
bower.json
|
||||||
|
|||||||
-10
@@ -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
|
|
||||||
@@ -1,5 +1,33 @@
|
|||||||
# 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
|
||||||
|
### Added
|
||||||
|
- TupleHash128, TupleHash256, TupleHashXOF128, and TupleHashXOF256 (NIST SP 800-185)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- KMAC repeated output reads after finalize
|
||||||
|
|
||||||
|
## v0.10.0 / 2026-07-17
|
||||||
|
### Added
|
||||||
|
- support ESM #42, #38
|
||||||
|
- types index.d.ts to package.json #32
|
||||||
|
|
||||||
## v0.9.3 / 2023-12-16
|
## v0.9.3 / 2023-12-16
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fix error in arrayBuffer when there are extra bytes #37
|
- Fix error in arrayBuffer when there are extra bytes #37
|
||||||
|
|||||||
+1
-1
@@ -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
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# js-sha3
|
# js-sha3
|
||||||
|
[](https://github.com/emn178/js-sha3/actions/workflows/ci.yml)
|
||||||
[](https://travis-ci.org/emn178/js-sha3)
|
|
||||||
[](https://coveralls.io/r/emn178/js-sha3?branch=master)
|
[](https://coveralls.io/r/emn178/js-sha3?branch=master)
|
||||||
[](https://nodei.co/npm/js-sha3/)
|
[](https://www.npmjs.com/package/js-sha3)
|
||||||
|
[](https://www.jsdelivr.com/package/npm/js-sha3)
|
||||||
|
|
||||||
A simple SHA-3 / Keccak / Shake 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 hash function for JavaScript supports UTF-8 enco
|
|||||||
[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,6 +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');
|
||||||
|
tuplehash256(['abc', 'd'], 512, 'customization');
|
||||||
|
tuplehashxof128(['abc', 'd'], 256, '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');
|
||||||
@@ -83,6 +107,36 @@ var hash = cshake128.create(256, 'function name', 'customization');
|
|||||||
|
|
||||||
// specify kmac key, output bits and customization when creating
|
// specify kmac key, output bits and customization when creating
|
||||||
var hash = kmac128.create('key', 256, 'customization');
|
var hash = kmac128.create('key', 256, 'customization');
|
||||||
|
|
||||||
|
// TupleHash: a tuple contains zero or more input strings.
|
||||||
|
// One-shot and method-level update
|
||||||
|
tuplehash128(['abc', 'd'], 256, '');
|
||||||
|
tuplehash128.update(['abc', 'd'], 256, '').hex();
|
||||||
|
|
||||||
|
// Incremental complete inputs (each update is one tuple input string)
|
||||||
|
tuplehash128.create(256, '')
|
||||||
|
.update('abc')
|
||||||
|
.update('d')
|
||||||
|
.hex();
|
||||||
|
|
||||||
|
// Streaming a large input when its byte length is known in advance.
|
||||||
|
// beginInput + updateChunk; no endInput() is needed.
|
||||||
|
// Inputs are absorbed sequentially. TupleHash does not parallelize tuple inputs;
|
||||||
|
// use ParallelHash for parallel hashing of one large input.
|
||||||
|
var tupleHash = tuplehash128.create(256, '');
|
||||||
|
tupleHash.beginInput(3);
|
||||||
|
tupleHash.updateChunk([0x61, 0x62]);
|
||||||
|
tupleHash.updateChunk([0x63]);
|
||||||
|
tupleHash.beginInput(1);
|
||||||
|
tupleHash.updateChunk([0x64]);
|
||||||
|
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:
|
||||||
@@ -101,7 +155,17 @@ const {
|
|||||||
cshake128,
|
cshake128,
|
||||||
cshake256,
|
cshake256,
|
||||||
kmac128,
|
kmac128,
|
||||||
kmac25
|
kmac256,
|
||||||
|
kmacxof128,
|
||||||
|
kmacxof256,
|
||||||
|
tuplehash128,
|
||||||
|
tuplehash256,
|
||||||
|
tuplehashxof128,
|
||||||
|
tuplehashxof256,
|
||||||
|
parallelhash128,
|
||||||
|
parallelhash256,
|
||||||
|
parallelhashxof128,
|
||||||
|
parallelhashxof256
|
||||||
} = require('js-sha3');
|
} = require('js-sha3');
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -122,7 +186,17 @@ import {
|
|||||||
cshake128,
|
cshake128,
|
||||||
cshake256,
|
cshake256,
|
||||||
kmac128,
|
kmac128,
|
||||||
kmac256
|
kmac256,
|
||||||
|
kmacxof128,
|
||||||
|
kmacxof256,
|
||||||
|
tuplehash128,
|
||||||
|
tuplehash256,
|
||||||
|
tuplehashxof128,
|
||||||
|
tuplehashxof256,
|
||||||
|
parallelhash128,
|
||||||
|
parallelhash256,
|
||||||
|
parallelhashxof128,
|
||||||
|
parallelhashxof256
|
||||||
} from 'js-sha3';
|
} from 'js-sha3';
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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",
|
||||||
|
|||||||
Vendored
+3
-3
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+971
@@ -0,0 +1,971 @@
|
|||||||
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
||||||
|
|
||||||
|
function getDefaultExportFromCjs (x) {
|
||||||
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sha3$1 = {exports: {}};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [js-sha3]{@link https://github.com/emn178/js-sha3}
|
||||||
|
*
|
||||||
|
* @version 0.13.0
|
||||||
|
* @author Chen, Yi-Cyuan [emn178@gmail.com]
|
||||||
|
* @copyright Chen, Yi-Cyuan 2015-2026
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function (module) {
|
||||||
|
/*jslint bitwise: true */
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
var INPUT_ERROR = 'input is invalid type';
|
||||||
|
var FINALIZE_ERROR = 'finalize already called';
|
||||||
|
var TUPLE_ACTIVE_ERROR = 'no active tuple input';
|
||||||
|
var TUPLE_INCOMPLETE_ERROR = 'tuple input is incomplete';
|
||||||
|
var TUPLE_LENGTH_ERROR = 'tuple input exceeds declared length';
|
||||||
|
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 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;
|
||||||
|
if (NODE_JS) {
|
||||||
|
root = commonjsGlobal;
|
||||||
|
} else if (WEB_WORKER) {
|
||||||
|
root = self;
|
||||||
|
}
|
||||||
|
var COMMON_JS = !root.JS_SHA3_NO_COMMON_JS && 'object' === 'object' && module.exports;
|
||||||
|
var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
|
||||||
|
var HEX_CHARS = '0123456789abcdef'.split('');
|
||||||
|
var SHAKE_PADDING = [31, 7936, 2031616, 520093696];
|
||||||
|
var CSHAKE_PADDING = [4, 1024, 262144, 67108864];
|
||||||
|
var KECCAK_PADDING = [1, 256, 65536, 16777216];
|
||||||
|
var PADDING = [6, 1536, 393216, 100663296];
|
||||||
|
var SHIFT = [0, 8, 16, 24];
|
||||||
|
var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649,
|
||||||
|
0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0,
|
||||||
|
2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771,
|
||||||
|
2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648,
|
||||||
|
2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648];
|
||||||
|
var BITS = [224, 256, 384, 512];
|
||||||
|
var SHAKE_BITS = [128, 256];
|
||||||
|
var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array', 'digest'];
|
||||||
|
var CSHAKE_BYTEPAD = {
|
||||||
|
'128': 168,
|
||||||
|
'256': 136
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var isArray = root.JS_SHA3_NO_NODE_JS || !Array.isArray
|
||||||
|
? function (obj) {
|
||||||
|
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||||
|
}
|
||||||
|
: Array.isArray;
|
||||||
|
|
||||||
|
var isView = (ARRAY_BUFFER && (root.JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView))
|
||||||
|
? function (obj) {
|
||||||
|
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
|
||||||
|
}
|
||||||
|
: ArrayBuffer.isView;
|
||||||
|
|
||||||
|
// [message: string, isString: bool]
|
||||||
|
var formatMessage = function (message) {
|
||||||
|
var type = typeof message;
|
||||||
|
if (type === 'string') {
|
||||||
|
return [message, true];
|
||||||
|
}
|
||||||
|
if (type !== 'object' || message === null) {
|
||||||
|
throw new Error(INPUT_ERROR);
|
||||||
|
}
|
||||||
|
if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
|
||||||
|
return [new Uint8Array(message), false];
|
||||||
|
}
|
||||||
|
if (!isArray(message) && !isView(message)) {
|
||||||
|
throw new Error(INPUT_ERROR);
|
||||||
|
}
|
||||||
|
return [message, false];
|
||||||
|
};
|
||||||
|
|
||||||
|
var empty = function (message) {
|
||||||
|
return formatMessage(message)[0].length === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
var cloneArray = function (array) {
|
||||||
|
var newArray = [];
|
||||||
|
for (var i = 0; i < array.length; ++i) {
|
||||||
|
newArray[i] = array[i];
|
||||||
|
}
|
||||||
|
return newArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
var createOutputMethod = function (bits, padding, outputType) {
|
||||||
|
return function (message) {
|
||||||
|
return new Keccak(bits, padding, bits).update(message)[outputType]();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var createShakeOutputMethod = function (bits, padding, outputType) {
|
||||||
|
return function (message, outputBits) {
|
||||||
|
return new Keccak(bits, padding, outputBits).update(message)[outputType]();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var createCshakeOutputMethod = function (bits, padding, outputType) {
|
||||||
|
return function (message, outputBits, n, s) {
|
||||||
|
return methods['cshake' + bits].update(message, outputBits, n, s)[outputType]();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var createKmacOutputMethod = function (bits, padding, xof, outputType) {
|
||||||
|
return function (key, message, outputBits, s) {
|
||||||
|
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]();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var createOutputMethods = function (method, createMethod, bits, padding) {
|
||||||
|
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
|
||||||
|
var type = OUTPUT_TYPES[i];
|
||||||
|
method[type] = createMethod(bits, padding, type);
|
||||||
|
}
|
||||||
|
return method;
|
||||||
|
};
|
||||||
|
|
||||||
|
var createMethod = function (bits, padding) {
|
||||||
|
var method = createOutputMethod(bits, padding, 'hex');
|
||||||
|
method.create = function () {
|
||||||
|
return new Keccak(bits, padding, bits);
|
||||||
|
};
|
||||||
|
method.update = function (message) {
|
||||||
|
return method.create().update(message);
|
||||||
|
};
|
||||||
|
return createOutputMethods(method, createOutputMethod, bits, padding);
|
||||||
|
};
|
||||||
|
|
||||||
|
var createShakeMethod = function (bits, padding) {
|
||||||
|
var method = createShakeOutputMethod(bits, padding, 'hex');
|
||||||
|
method.create = function (outputBits) {
|
||||||
|
return new Keccak(bits, padding, outputBits);
|
||||||
|
};
|
||||||
|
method.update = function (message, outputBits) {
|
||||||
|
return method.create(outputBits).update(message);
|
||||||
|
};
|
||||||
|
return createOutputMethods(method, createShakeOutputMethod, bits, padding);
|
||||||
|
};
|
||||||
|
|
||||||
|
var createCshakeMethod = function (bits, padding) {
|
||||||
|
var w = CSHAKE_BYTEPAD[bits];
|
||||||
|
var method = createCshakeOutputMethod(bits, padding, 'hex');
|
||||||
|
method.create = function (outputBits, n, s) {
|
||||||
|
if (empty(n) && empty(s)) {
|
||||||
|
return methods['shake' + bits].create(outputBits);
|
||||||
|
} else {
|
||||||
|
return new Keccak(bits, padding, outputBits).bytepad([n, s], w);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
method.update = function (message, outputBits, n, s) {
|
||||||
|
return method.create(outputBits, n, s).update(message);
|
||||||
|
};
|
||||||
|
return createOutputMethods(method, createCshakeOutputMethod, bits, padding);
|
||||||
|
};
|
||||||
|
|
||||||
|
var createKmacMethod = function (bits, padding, xof) {
|
||||||
|
var w = CSHAKE_BYTEPAD[bits];
|
||||||
|
var method = createKmacOutputMethod(bits, padding, xof, 'hex');
|
||||||
|
method.create = function (key, outputBits, s) {
|
||||||
|
return new Kmac(bits, padding, outputBits, xof).bytepad(['KMAC', s], w).bytepad([key], w);
|
||||||
|
};
|
||||||
|
method.update = function (key, message, outputBits, s) {
|
||||||
|
return method.create(key, outputBits, s).update(message);
|
||||||
|
};
|
||||||
|
return createOutputMethods(method, function (b, p, outputType) {
|
||||||
|
return createKmacOutputMethod(b, p, xof, outputType);
|
||||||
|
}, bits, padding);
|
||||||
|
};
|
||||||
|
|
||||||
|
var createTupleHashMethod = function (bits, padding, xof) {
|
||||||
|
var w = CSHAKE_BYTEPAD[bits];
|
||||||
|
var method = createTupleHashOutputMethod(bits, padding, xof, 'hex');
|
||||||
|
method.create = function (outputBits, s) {
|
||||||
|
return new TupleHash(bits, padding, outputBits, xof).bytepad(['TupleHash', s], w);
|
||||||
|
};
|
||||||
|
method.update = function (inputs, outputBits, s) {
|
||||||
|
if (!isArray(inputs)) {
|
||||||
|
throw new Error(INPUT_ERROR);
|
||||||
|
}
|
||||||
|
var hash = method.create(outputBits, s);
|
||||||
|
for (var i = 0; i < inputs.length; ++i) {
|
||||||
|
hash.update(inputs[i]);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
return createOutputMethods(method, function (b, p, outputType) {
|
||||||
|
return createTupleHashOutputMethod(b, p, xof, outputType);
|
||||||
|
}, 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 = [
|
||||||
|
{ name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod },
|
||||||
|
{ name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod },
|
||||||
|
{ name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod },
|
||||||
|
{ name: 'cshake', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createCshakeMethod },
|
||||||
|
{ 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) {
|
||||||
|
return createTupleHashMethod(bits, padding, false);
|
||||||
|
}},
|
||||||
|
{ name: 'tuplehashxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
|
||||||
|
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);
|
||||||
|
}}
|
||||||
|
];
|
||||||
|
|
||||||
|
var methods = {}, methodNames = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < algorithms.length; ++i) {
|
||||||
|
var algorithm = algorithms[i];
|
||||||
|
var bits = algorithm.bits;
|
||||||
|
for (var j = 0; j < bits.length; ++j) {
|
||||||
|
var methodName = algorithm.name + '_' + bits[j];
|
||||||
|
methodNames.push(methodName);
|
||||||
|
methods[methodName] = algorithm.createMethod(bits[j], algorithm.padding);
|
||||||
|
if (algorithm.name !== 'sha3') {
|
||||||
|
var newMethodName = algorithm.name + bits[j];
|
||||||
|
methodNames.push(newMethodName);
|
||||||
|
methods[newMethodName] = methods[methodName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Keccak(bits, padding, outputBits) {
|
||||||
|
this.blocks = [];
|
||||||
|
this.s = [];
|
||||||
|
this.padding = padding;
|
||||||
|
this.outputBits = outputBits;
|
||||||
|
this.reset = true;
|
||||||
|
this.finalized = false;
|
||||||
|
this.block = 0;
|
||||||
|
this.start = 0;
|
||||||
|
this.blockCount = (1600 - (bits << 1)) >> 5;
|
||||||
|
this.byteCount = this.blockCount << 2;
|
||||||
|
this.outputBlocks = outputBits >> 5;
|
||||||
|
this.extraBytes = (outputBits & 31) >> 3;
|
||||||
|
|
||||||
|
for (var i = 0; i < 50; ++i) {
|
||||||
|
this.s[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keccak.prototype.update = function (message) {
|
||||||
|
if (this.finalized) {
|
||||||
|
throw new Error(FINALIZE_ERROR);
|
||||||
|
}
|
||||||
|
var result = formatMessage(message);
|
||||||
|
message = result[0];
|
||||||
|
var isString = result[1];
|
||||||
|
var blocks = this.blocks, byteCount = this.byteCount, length = message.length,
|
||||||
|
blockCount = this.blockCount, index = 0, s = this.s, i, code;
|
||||||
|
|
||||||
|
while (index < length) {
|
||||||
|
if (this.reset) {
|
||||||
|
this.reset = false;
|
||||||
|
blocks[0] = this.block;
|
||||||
|
for (i = 1; i < blockCount + 1; ++i) {
|
||||||
|
blocks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isString) {
|
||||||
|
for (i = this.start; index < length && i < byteCount; ++index) {
|
||||||
|
code = message.charCodeAt(index);
|
||||||
|
if (code < 0x80) {
|
||||||
|
blocks[i >> 2] |= code << SHIFT[i++ & 3];
|
||||||
|
} else if (code < 0x800) {
|
||||||
|
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
|
||||||
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||||
|
} else if (code < 0xd800 || code >= 0xe000) {
|
||||||
|
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
|
||||||
|
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||||||
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||||
|
} else {
|
||||||
|
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
|
||||||
|
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
|
||||||
|
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
|
||||||
|
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||||||
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = this.start; index < length && i < byteCount; ++index) {
|
||||||
|
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.lastByteIndex = i;
|
||||||
|
if (i >= byteCount) {
|
||||||
|
this.start = i - byteCount;
|
||||||
|
this.block = blocks[blockCount];
|
||||||
|
for (i = 0; i < blockCount; ++i) {
|
||||||
|
s[i] ^= blocks[i];
|
||||||
|
}
|
||||||
|
f(s);
|
||||||
|
this.reset = true;
|
||||||
|
} else {
|
||||||
|
this.start = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Keccak.prototype.encode = function (x, right) {
|
||||||
|
var o = x & 255, n = 1;
|
||||||
|
var bytes = [o];
|
||||||
|
x = x >> 8;
|
||||||
|
o = x & 255;
|
||||||
|
while (o > 0) {
|
||||||
|
bytes.unshift(o);
|
||||||
|
x = x >> 8;
|
||||||
|
o = x & 255;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
if (right) {
|
||||||
|
bytes.push(n);
|
||||||
|
} else {
|
||||||
|
bytes.unshift(n);
|
||||||
|
}
|
||||||
|
Keccak.prototype.update.call(this, bytes);
|
||||||
|
return bytes.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
Keccak.prototype.encodeString = function (str) {
|
||||||
|
var result = formatMessage(str);
|
||||||
|
str = result[0];
|
||||||
|
var isString = result[1];
|
||||||
|
var bytes = 0, length = str.length;
|
||||||
|
if (isString) {
|
||||||
|
for (var i = 0; i < str.length; ++i) {
|
||||||
|
var code = str.charCodeAt(i);
|
||||||
|
if (code < 0x80) {
|
||||||
|
bytes += 1;
|
||||||
|
} else if (code < 0x800) {
|
||||||
|
bytes += 2;
|
||||||
|
} else if (code < 0xd800 || code >= 0xe000) {
|
||||||
|
bytes += 3;
|
||||||
|
} else {
|
||||||
|
code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));
|
||||||
|
bytes += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bytes = length;
|
||||||
|
}
|
||||||
|
bytes += this.encode(bytes * 8);
|
||||||
|
Keccak.prototype.update.call(this, str);
|
||||||
|
return bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
Keccak.prototype.bytepad = function (strs, w) {
|
||||||
|
var bytes = this.encode(w);
|
||||||
|
for (var i = 0; i < strs.length; ++i) {
|
||||||
|
bytes += this.encodeString(strs[i]);
|
||||||
|
}
|
||||||
|
var paddingBytes = (w - bytes % w) % w;
|
||||||
|
var zeros = [];
|
||||||
|
zeros.length = paddingBytes;
|
||||||
|
Keccak.prototype.update.call(this, zeros);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Keccak.prototype.finalize = function () {
|
||||||
|
if (this.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.finalized = true;
|
||||||
|
var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s;
|
||||||
|
blocks[i >> 2] |= this.padding[i & 3];
|
||||||
|
if (this.lastByteIndex === this.byteCount) {
|
||||||
|
blocks[0] = blocks[blockCount];
|
||||||
|
for (i = 1; i < blockCount + 1; ++i) {
|
||||||
|
blocks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blocks[blockCount - 1] |= 0x80000000;
|
||||||
|
for (i = 0; i < blockCount; ++i) {
|
||||||
|
s[i] ^= blocks[i];
|
||||||
|
}
|
||||||
|
f(s);
|
||||||
|
};
|
||||||
|
|
||||||
|
Keccak.prototype.toString = Keccak.prototype.hex = function () {
|
||||||
|
this.finalize();
|
||||||
|
|
||||||
|
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
|
||||||
|
extraBytes = this.extraBytes, i = 0, j = 0;
|
||||||
|
var hex = '', block;
|
||||||
|
while (j < outputBlocks) {
|
||||||
|
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
|
||||||
|
block = s[i];
|
||||||
|
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] +
|
||||||
|
HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] +
|
||||||
|
HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] +
|
||||||
|
HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F];
|
||||||
|
}
|
||||||
|
if (j % blockCount === 0) {
|
||||||
|
s = cloneArray(s);
|
||||||
|
f(s);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (extraBytes) {
|
||||||
|
block = s[i];
|
||||||
|
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F];
|
||||||
|
if (extraBytes > 1) {
|
||||||
|
hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F];
|
||||||
|
}
|
||||||
|
if (extraBytes > 2) {
|
||||||
|
hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
};
|
||||||
|
|
||||||
|
Keccak.prototype.arrayBuffer = function () {
|
||||||
|
this.finalize();
|
||||||
|
|
||||||
|
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
|
||||||
|
extraBytes = this.extraBytes, i = 0, j = 0;
|
||||||
|
var bytes = this.outputBits >> 3;
|
||||||
|
var buffer;
|
||||||
|
if (extraBytes) {
|
||||||
|
buffer = new ArrayBuffer((outputBlocks + 1) << 2);
|
||||||
|
} else {
|
||||||
|
buffer = new ArrayBuffer(bytes);
|
||||||
|
}
|
||||||
|
var array = new Uint32Array(buffer);
|
||||||
|
while (j < outputBlocks) {
|
||||||
|
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
|
||||||
|
array[j] = s[i];
|
||||||
|
}
|
||||||
|
if (j % blockCount === 0) {
|
||||||
|
s = cloneArray(s);
|
||||||
|
f(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (extraBytes) {
|
||||||
|
array[j] = s[i];
|
||||||
|
buffer = buffer.slice(0, bytes);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
Keccak.prototype.buffer = Keccak.prototype.arrayBuffer;
|
||||||
|
|
||||||
|
Keccak.prototype.digest = Keccak.prototype.array = function () {
|
||||||
|
this.finalize();
|
||||||
|
|
||||||
|
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
|
||||||
|
extraBytes = this.extraBytes, i = 0, j = 0;
|
||||||
|
var array = [], offset, block;
|
||||||
|
while (j < outputBlocks) {
|
||||||
|
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
|
||||||
|
offset = j << 2;
|
||||||
|
block = s[i];
|
||||||
|
array[offset] = block & 0xFF;
|
||||||
|
array[offset + 1] = (block >> 8) & 0xFF;
|
||||||
|
array[offset + 2] = (block >> 16) & 0xFF;
|
||||||
|
array[offset + 3] = (block >> 24) & 0xFF;
|
||||||
|
}
|
||||||
|
if (j % blockCount === 0) {
|
||||||
|
s = cloneArray(s);
|
||||||
|
f(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (extraBytes) {
|
||||||
|
offset = j << 2;
|
||||||
|
block = s[i];
|
||||||
|
array[offset] = block & 0xFF;
|
||||||
|
if (extraBytes > 1) {
|
||||||
|
array[offset + 1] = (block >> 8) & 0xFF;
|
||||||
|
}
|
||||||
|
if (extraBytes > 2) {
|
||||||
|
array[offset + 2] = (block >> 16) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Kmac(bits, padding, outputBits, xof) {
|
||||||
|
Keccak.call(this, bits, padding, outputBits);
|
||||||
|
this.xof = xof;
|
||||||
|
}
|
||||||
|
|
||||||
|
Kmac.prototype = new Keccak();
|
||||||
|
|
||||||
|
Kmac.prototype.finalize = function () {
|
||||||
|
if (!this.finalized) {
|
||||||
|
this.encode(this.xof ? 0 : this.outputBits, true);
|
||||||
|
}
|
||||||
|
return Keccak.prototype.finalize.call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
function TupleHash(bits, padding, outputBits, xof) {
|
||||||
|
Kmac.call(this, bits, padding, outputBits, xof);
|
||||||
|
this.inputActive = false;
|
||||||
|
this.inputBytesRemaining = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TupleHash.prototype = new Kmac();
|
||||||
|
|
||||||
|
TupleHash.prototype.getMessageByteLength = function (message) {
|
||||||
|
var result = formatMessage(message);
|
||||||
|
message = result[0];
|
||||||
|
if (!result[1]) {
|
||||||
|
return message.length;
|
||||||
|
}
|
||||||
|
var bytes = 0;
|
||||||
|
for (var i = 0; i < message.length; ++i) {
|
||||||
|
var code = message.charCodeAt(i);
|
||||||
|
if (code < 0x80) {
|
||||||
|
bytes += 1;
|
||||||
|
} else if (code < 0x800) {
|
||||||
|
bytes += 2;
|
||||||
|
} else if (code < 0xd800 || code >= 0xe000) {
|
||||||
|
bytes += 3;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
bytes += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
TupleHash.prototype.beginInput = function (byteLength) {
|
||||||
|
if (this.inputActive) {
|
||||||
|
throw new Error(TUPLE_INCOMPLETE_ERROR);
|
||||||
|
}
|
||||||
|
if (typeof byteLength !== 'number' || !isFinite(byteLength) || byteLength < 0 ||
|
||||||
|
Math.floor(byteLength) !== byteLength || byteLength > 0x0fffffff) {
|
||||||
|
throw new Error(TUPLE_BYTE_LENGTH_ERROR);
|
||||||
|
}
|
||||||
|
this.encode(byteLength * 8, false);
|
||||||
|
if (byteLength !== 0) {
|
||||||
|
this.inputActive = true;
|
||||||
|
this.inputBytesRemaining = byteLength;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
TupleHash.prototype._updateChunk = function (message, byteLength) {
|
||||||
|
Kmac.prototype.update.call(this, message);
|
||||||
|
this.inputBytesRemaining -= byteLength;
|
||||||
|
if (this.inputBytesRemaining === 0) {
|
||||||
|
this.inputActive = false;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
TupleHash.prototype.updateChunk = function (message) {
|
||||||
|
if (!this.inputActive) {
|
||||||
|
throw new Error(TUPLE_ACTIVE_ERROR);
|
||||||
|
}
|
||||||
|
var byteLength = this.getMessageByteLength(message);
|
||||||
|
if (byteLength > this.inputBytesRemaining) {
|
||||||
|
throw new Error(TUPLE_LENGTH_ERROR);
|
||||||
|
}
|
||||||
|
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 () {
|
||||||
|
if (this.inputActive) {
|
||||||
|
throw new Error(TUPLE_INCOMPLETE_ERROR);
|
||||||
|
}
|
||||||
|
return Kmac.prototype.finalize.call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9,
|
||||||
|
b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17,
|
||||||
|
b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33,
|
||||||
|
b34, b35, b36, b37, b38, b39, b40, b41, b42, b43, b44, b45, b46, b47, b48, b49;
|
||||||
|
for (n = 0; n < 48; n += 2) {
|
||||||
|
c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
|
||||||
|
c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
|
||||||
|
c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42];
|
||||||
|
c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43];
|
||||||
|
c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44];
|
||||||
|
c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45];
|
||||||
|
c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46];
|
||||||
|
c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47];
|
||||||
|
c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48];
|
||||||
|
c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49];
|
||||||
|
|
||||||
|
h = c8 ^ ((c2 << 1) | (c3 >>> 31));
|
||||||
|
l = c9 ^ ((c3 << 1) | (c2 >>> 31));
|
||||||
|
s[0] ^= h;
|
||||||
|
s[1] ^= l;
|
||||||
|
s[10] ^= h;
|
||||||
|
s[11] ^= l;
|
||||||
|
s[20] ^= h;
|
||||||
|
s[21] ^= l;
|
||||||
|
s[30] ^= h;
|
||||||
|
s[31] ^= l;
|
||||||
|
s[40] ^= h;
|
||||||
|
s[41] ^= l;
|
||||||
|
h = c0 ^ ((c4 << 1) | (c5 >>> 31));
|
||||||
|
l = c1 ^ ((c5 << 1) | (c4 >>> 31));
|
||||||
|
s[2] ^= h;
|
||||||
|
s[3] ^= l;
|
||||||
|
s[12] ^= h;
|
||||||
|
s[13] ^= l;
|
||||||
|
s[22] ^= h;
|
||||||
|
s[23] ^= l;
|
||||||
|
s[32] ^= h;
|
||||||
|
s[33] ^= l;
|
||||||
|
s[42] ^= h;
|
||||||
|
s[43] ^= l;
|
||||||
|
h = c2 ^ ((c6 << 1) | (c7 >>> 31));
|
||||||
|
l = c3 ^ ((c7 << 1) | (c6 >>> 31));
|
||||||
|
s[4] ^= h;
|
||||||
|
s[5] ^= l;
|
||||||
|
s[14] ^= h;
|
||||||
|
s[15] ^= l;
|
||||||
|
s[24] ^= h;
|
||||||
|
s[25] ^= l;
|
||||||
|
s[34] ^= h;
|
||||||
|
s[35] ^= l;
|
||||||
|
s[44] ^= h;
|
||||||
|
s[45] ^= l;
|
||||||
|
h = c4 ^ ((c8 << 1) | (c9 >>> 31));
|
||||||
|
l = c5 ^ ((c9 << 1) | (c8 >>> 31));
|
||||||
|
s[6] ^= h;
|
||||||
|
s[7] ^= l;
|
||||||
|
s[16] ^= h;
|
||||||
|
s[17] ^= l;
|
||||||
|
s[26] ^= h;
|
||||||
|
s[27] ^= l;
|
||||||
|
s[36] ^= h;
|
||||||
|
s[37] ^= l;
|
||||||
|
s[46] ^= h;
|
||||||
|
s[47] ^= l;
|
||||||
|
h = c6 ^ ((c0 << 1) | (c1 >>> 31));
|
||||||
|
l = c7 ^ ((c1 << 1) | (c0 >>> 31));
|
||||||
|
s[8] ^= h;
|
||||||
|
s[9] ^= l;
|
||||||
|
s[18] ^= h;
|
||||||
|
s[19] ^= l;
|
||||||
|
s[28] ^= h;
|
||||||
|
s[29] ^= l;
|
||||||
|
s[38] ^= h;
|
||||||
|
s[39] ^= l;
|
||||||
|
s[48] ^= h;
|
||||||
|
s[49] ^= l;
|
||||||
|
|
||||||
|
b0 = s[0];
|
||||||
|
b1 = s[1];
|
||||||
|
b32 = (s[11] << 4) | (s[10] >>> 28);
|
||||||
|
b33 = (s[10] << 4) | (s[11] >>> 28);
|
||||||
|
b14 = (s[20] << 3) | (s[21] >>> 29);
|
||||||
|
b15 = (s[21] << 3) | (s[20] >>> 29);
|
||||||
|
b46 = (s[31] << 9) | (s[30] >>> 23);
|
||||||
|
b47 = (s[30] << 9) | (s[31] >>> 23);
|
||||||
|
b28 = (s[40] << 18) | (s[41] >>> 14);
|
||||||
|
b29 = (s[41] << 18) | (s[40] >>> 14);
|
||||||
|
b20 = (s[2] << 1) | (s[3] >>> 31);
|
||||||
|
b21 = (s[3] << 1) | (s[2] >>> 31);
|
||||||
|
b2 = (s[13] << 12) | (s[12] >>> 20);
|
||||||
|
b3 = (s[12] << 12) | (s[13] >>> 20);
|
||||||
|
b34 = (s[22] << 10) | (s[23] >>> 22);
|
||||||
|
b35 = (s[23] << 10) | (s[22] >>> 22);
|
||||||
|
b16 = (s[33] << 13) | (s[32] >>> 19);
|
||||||
|
b17 = (s[32] << 13) | (s[33] >>> 19);
|
||||||
|
b48 = (s[42] << 2) | (s[43] >>> 30);
|
||||||
|
b49 = (s[43] << 2) | (s[42] >>> 30);
|
||||||
|
b40 = (s[5] << 30) | (s[4] >>> 2);
|
||||||
|
b41 = (s[4] << 30) | (s[5] >>> 2);
|
||||||
|
b22 = (s[14] << 6) | (s[15] >>> 26);
|
||||||
|
b23 = (s[15] << 6) | (s[14] >>> 26);
|
||||||
|
b4 = (s[25] << 11) | (s[24] >>> 21);
|
||||||
|
b5 = (s[24] << 11) | (s[25] >>> 21);
|
||||||
|
b36 = (s[34] << 15) | (s[35] >>> 17);
|
||||||
|
b37 = (s[35] << 15) | (s[34] >>> 17);
|
||||||
|
b18 = (s[45] << 29) | (s[44] >>> 3);
|
||||||
|
b19 = (s[44] << 29) | (s[45] >>> 3);
|
||||||
|
b10 = (s[6] << 28) | (s[7] >>> 4);
|
||||||
|
b11 = (s[7] << 28) | (s[6] >>> 4);
|
||||||
|
b42 = (s[17] << 23) | (s[16] >>> 9);
|
||||||
|
b43 = (s[16] << 23) | (s[17] >>> 9);
|
||||||
|
b24 = (s[26] << 25) | (s[27] >>> 7);
|
||||||
|
b25 = (s[27] << 25) | (s[26] >>> 7);
|
||||||
|
b6 = (s[36] << 21) | (s[37] >>> 11);
|
||||||
|
b7 = (s[37] << 21) | (s[36] >>> 11);
|
||||||
|
b38 = (s[47] << 24) | (s[46] >>> 8);
|
||||||
|
b39 = (s[46] << 24) | (s[47] >>> 8);
|
||||||
|
b30 = (s[8] << 27) | (s[9] >>> 5);
|
||||||
|
b31 = (s[9] << 27) | (s[8] >>> 5);
|
||||||
|
b12 = (s[18] << 20) | (s[19] >>> 12);
|
||||||
|
b13 = (s[19] << 20) | (s[18] >>> 12);
|
||||||
|
b44 = (s[29] << 7) | (s[28] >>> 25);
|
||||||
|
b45 = (s[28] << 7) | (s[29] >>> 25);
|
||||||
|
b26 = (s[38] << 8) | (s[39] >>> 24);
|
||||||
|
b27 = (s[39] << 8) | (s[38] >>> 24);
|
||||||
|
b8 = (s[48] << 14) | (s[49] >>> 18);
|
||||||
|
b9 = (s[49] << 14) | (s[48] >>> 18);
|
||||||
|
|
||||||
|
s[0] = b0 ^ (~b2 & b4);
|
||||||
|
s[1] = b1 ^ (~b3 & b5);
|
||||||
|
s[10] = b10 ^ (~b12 & b14);
|
||||||
|
s[11] = b11 ^ (~b13 & b15);
|
||||||
|
s[20] = b20 ^ (~b22 & b24);
|
||||||
|
s[21] = b21 ^ (~b23 & b25);
|
||||||
|
s[30] = b30 ^ (~b32 & b34);
|
||||||
|
s[31] = b31 ^ (~b33 & b35);
|
||||||
|
s[40] = b40 ^ (~b42 & b44);
|
||||||
|
s[41] = b41 ^ (~b43 & b45);
|
||||||
|
s[2] = b2 ^ (~b4 & b6);
|
||||||
|
s[3] = b3 ^ (~b5 & b7);
|
||||||
|
s[12] = b12 ^ (~b14 & b16);
|
||||||
|
s[13] = b13 ^ (~b15 & b17);
|
||||||
|
s[22] = b22 ^ (~b24 & b26);
|
||||||
|
s[23] = b23 ^ (~b25 & b27);
|
||||||
|
s[32] = b32 ^ (~b34 & b36);
|
||||||
|
s[33] = b33 ^ (~b35 & b37);
|
||||||
|
s[42] = b42 ^ (~b44 & b46);
|
||||||
|
s[43] = b43 ^ (~b45 & b47);
|
||||||
|
s[4] = b4 ^ (~b6 & b8);
|
||||||
|
s[5] = b5 ^ (~b7 & b9);
|
||||||
|
s[14] = b14 ^ (~b16 & b18);
|
||||||
|
s[15] = b15 ^ (~b17 & b19);
|
||||||
|
s[24] = b24 ^ (~b26 & b28);
|
||||||
|
s[25] = b25 ^ (~b27 & b29);
|
||||||
|
s[34] = b34 ^ (~b36 & b38);
|
||||||
|
s[35] = b35 ^ (~b37 & b39);
|
||||||
|
s[44] = b44 ^ (~b46 & b48);
|
||||||
|
s[45] = b45 ^ (~b47 & b49);
|
||||||
|
s[6] = b6 ^ (~b8 & b0);
|
||||||
|
s[7] = b7 ^ (~b9 & b1);
|
||||||
|
s[16] = b16 ^ (~b18 & b10);
|
||||||
|
s[17] = b17 ^ (~b19 & b11);
|
||||||
|
s[26] = b26 ^ (~b28 & b20);
|
||||||
|
s[27] = b27 ^ (~b29 & b21);
|
||||||
|
s[36] = b36 ^ (~b38 & b30);
|
||||||
|
s[37] = b37 ^ (~b39 & b31);
|
||||||
|
s[46] = b46 ^ (~b48 & b40);
|
||||||
|
s[47] = b47 ^ (~b49 & b41);
|
||||||
|
s[8] = b8 ^ (~b0 & b2);
|
||||||
|
s[9] = b9 ^ (~b1 & b3);
|
||||||
|
s[18] = b18 ^ (~b10 & b12);
|
||||||
|
s[19] = b19 ^ (~b11 & b13);
|
||||||
|
s[28] = b28 ^ (~b20 & b22);
|
||||||
|
s[29] = b29 ^ (~b21 & b23);
|
||||||
|
s[38] = b38 ^ (~b30 & b32);
|
||||||
|
s[39] = b39 ^ (~b31 & b33);
|
||||||
|
s[48] = b48 ^ (~b40 & b42);
|
||||||
|
s[49] = b49 ^ (~b41 & b43);
|
||||||
|
|
||||||
|
s[0] ^= RC[n];
|
||||||
|
s[1] ^= RC[n + 1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (COMMON_JS) {
|
||||||
|
module.exports = methods;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < methodNames.length; ++i) {
|
||||||
|
root[methodNames[i]] = methods[methodNames[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
} (sha3$1));
|
||||||
|
|
||||||
|
var sha3Exports = sha3$1.exports;
|
||||||
|
var sha3 = /*@__PURE__*/getDefaultExportFromCjs(sha3Exports);
|
||||||
|
|
||||||
|
const {
|
||||||
|
sha3_224,
|
||||||
|
sha3_256,
|
||||||
|
sha3_384,
|
||||||
|
sha3_512,
|
||||||
|
|
||||||
|
keccak_224,
|
||||||
|
keccak_256,
|
||||||
|
keccak_384,
|
||||||
|
keccak_512,
|
||||||
|
keccak224,
|
||||||
|
keccak256,
|
||||||
|
keccak384,
|
||||||
|
keccak512,
|
||||||
|
|
||||||
|
shake_128,
|
||||||
|
shake_256,
|
||||||
|
shake128,
|
||||||
|
shake256,
|
||||||
|
|
||||||
|
cshake_128,
|
||||||
|
cshake_256,
|
||||||
|
cshake128,
|
||||||
|
cshake256,
|
||||||
|
|
||||||
|
kmac_128,
|
||||||
|
kmac_256,
|
||||||
|
kmac128,
|
||||||
|
kmac256,
|
||||||
|
kmacxof_128,
|
||||||
|
kmacxof_256,
|
||||||
|
kmacxof128,
|
||||||
|
kmacxof256,
|
||||||
|
|
||||||
|
tuplehash_128,
|
||||||
|
tuplehash_256,
|
||||||
|
tuplehash128,
|
||||||
|
tuplehash256,
|
||||||
|
tuplehashxof_128,
|
||||||
|
tuplehashxof_256,
|
||||||
|
tuplehashxof128,
|
||||||
|
tuplehashxof256,
|
||||||
|
|
||||||
|
parallelhash_128,
|
||||||
|
parallelhash_256,
|
||||||
|
parallelhash128,
|
||||||
|
parallelhash256,
|
||||||
|
parallelhashxof_128,
|
||||||
|
parallelhashxof_256,
|
||||||
|
parallelhashxof128,
|
||||||
|
parallelhashxof256
|
||||||
|
} = 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, 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
+191
@@ -291,6 +291,96 @@ interface KmacHash {
|
|||||||
update(key: Message, message: Message, outputBits: number, customization: Message): Hasher;
|
update(key: Message, message: Message, outputBits: number, customization: Message): Hasher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TupleInput = Message[];
|
||||||
|
|
||||||
|
interface TupleHash extends Hasher {
|
||||||
|
/**
|
||||||
|
* Start a streaming tuple input with a known UTF-8/binary byte length.
|
||||||
|
*
|
||||||
|
* @param byteLength The byte length of the input that will follow through updateChunk().
|
||||||
|
*/
|
||||||
|
beginInput(byteLength: number): TupleHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absorb part of the active streaming tuple input.
|
||||||
|
*
|
||||||
|
* @param message The next message chunk.
|
||||||
|
*/
|
||||||
|
updateChunk(message: Message): TupleHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append one complete tuple input string.
|
||||||
|
* Equivalent to beginInput(byteLength) followed by updateChunk(message).
|
||||||
|
*
|
||||||
|
* @param message The input string to encode and absorb.
|
||||||
|
*/
|
||||||
|
update(message: Message): TupleHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TupleHashMethod {
|
||||||
|
/**
|
||||||
|
* Hash a tuple and return hex string.
|
||||||
|
*
|
||||||
|
* @param inputs The tuple of input strings.
|
||||||
|
* @param outputBits The length of output.
|
||||||
|
* @param customization The customization string.
|
||||||
|
*/
|
||||||
|
(inputs: TupleInput, outputBits: number, customization: Message): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash a tuple and return hex string.
|
||||||
|
*
|
||||||
|
* @param inputs The tuple of input strings.
|
||||||
|
* @param outputBits The length of output.
|
||||||
|
* @param customization The customization string.
|
||||||
|
*/
|
||||||
|
hex(inputs: TupleInput, outputBits: number, customization: Message): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash a tuple and return ArrayBuffer.
|
||||||
|
*
|
||||||
|
* @param inputs The tuple of input strings.
|
||||||
|
* @param outputBits The length of output.
|
||||||
|
* @param customization The customization string.
|
||||||
|
*/
|
||||||
|
arrayBuffer(inputs: TupleInput, outputBits: number, customization: Message): ArrayBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash a tuple and return integer array.
|
||||||
|
*
|
||||||
|
* @param inputs The tuple of input strings.
|
||||||
|
* @param outputBits The length of output.
|
||||||
|
* @param customization The customization string.
|
||||||
|
*/
|
||||||
|
digest(inputs: TupleInput, outputBits: number, customization: Message): number[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash a tuple and return integer array.
|
||||||
|
*
|
||||||
|
* @param inputs The tuple of input strings.
|
||||||
|
* @param outputBits The length of output.
|
||||||
|
* @param customization The customization string.
|
||||||
|
*/
|
||||||
|
array(inputs: TupleInput, outputBits: number, customization: Message): number[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TupleHash object.
|
||||||
|
*
|
||||||
|
* @param outputBits The length of output.
|
||||||
|
* @param customization The customization string.
|
||||||
|
*/
|
||||||
|
create(outputBits: number, customization: Message): TupleHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TupleHash object and absorb the given tuple inputs.
|
||||||
|
*
|
||||||
|
* @param inputs The tuple of input strings.
|
||||||
|
* @param outputBits The length of output.
|
||||||
|
* @param customization The customization string.
|
||||||
|
*/
|
||||||
|
update(inputs: TupleInput, outputBits: number, customization: Message): TupleHash;
|
||||||
|
}
|
||||||
|
|
||||||
export var sha3_512: Hash;
|
export var sha3_512: Hash;
|
||||||
export var sha3_384: Hash;
|
export var sha3_384: Hash;
|
||||||
export var sha3_256: Hash;
|
export var sha3_256: Hash;
|
||||||
@@ -315,3 +405,104 @@ 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_256: TupleHashMethod;
|
||||||
|
export var tuplehash128: TupleHashMethod;
|
||||||
|
export var tuplehash256: TupleHashMethod;
|
||||||
|
export var tuplehashxof_128: TupleHashMethod;
|
||||||
|
export var tuplehashxof_256: TupleHashMethod;
|
||||||
|
export var tuplehashxof128: 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;
|
||||||
|
|||||||
Generated
+2626
-1191
File diff suppressed because it is too large
Load Diff
+33
-6
@@ -1,20 +1,41 @@
|
|||||||
{
|
{
|
||||||
"name": "js-sha3",
|
"name": "js-sha3",
|
||||||
"version": "0.9.3",
|
"version": "0.13.0",
|
||||||
"description": "A simple SHA-3 / Keccak / Shake 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",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./index.d.ts",
|
||||||
|
"import": "./build/sha3.mjs",
|
||||||
|
"require": "./src/sha3.js",
|
||||||
|
"default": "./src/sha3.js"
|
||||||
|
},
|
||||||
|
"./src/sha3.js": "./src/sha3.js",
|
||||||
|
"./build/sha3.min.js": "./build/sha3.min.js",
|
||||||
|
"./build/sha3.mjs": "./build/sha3.mjs",
|
||||||
|
"./build/sha3.min.mjs": "./build/sha3.min.mjs",
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"types": "./index.d.ts",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-commonjs": "^28.0.5",
|
||||||
|
"@rollup/plugin-terser": "^1.0.0",
|
||||||
"expect.js": "~0.3.1",
|
"expect.js": "~0.3.1",
|
||||||
"mocha": "~10.2.0",
|
"mocha": "^11.8.0",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^18.0.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": "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",
|
||||||
@@ -26,6 +47,8 @@
|
|||||||
"shake",
|
"shake",
|
||||||
"cshake",
|
"cshake",
|
||||||
"kmac",
|
"kmac",
|
||||||
|
"tuplehash",
|
||||||
|
"parallelhash",
|
||||||
"hash",
|
"hash",
|
||||||
"encryption",
|
"encryption",
|
||||||
"cryptography",
|
"cryptography",
|
||||||
@@ -41,5 +64,9 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"tests"
|
"tests"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"diff": "^8.0.3",
|
||||||
|
"serialize-javascript": "^7.0.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
import terser from '@rollup/plugin-terser';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
input: 'src/sha3.mjs',
|
||||||
|
output: {
|
||||||
|
file: 'build/sha3.mjs',
|
||||||
|
format: 'es'
|
||||||
|
},
|
||||||
|
plugins: [commonjs({
|
||||||
|
strictRequires: false
|
||||||
|
})]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: 'build/sha3.mjs',
|
||||||
|
output: {
|
||||||
|
file: 'build/sha3.min.mjs',
|
||||||
|
format: 'es'
|
||||||
|
},
|
||||||
|
plugins: [terser()]
|
||||||
|
}
|
||||||
|
];
|
||||||
+261
-14
@@ -1,9 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* [js-sha3]{@link https://github.com/emn178/js-sha3}
|
* [js-sha3]{@link https://github.com/emn178/js-sha3}
|
||||||
*
|
*
|
||||||
* @version 0.9.3
|
* @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 */
|
||||||
@@ -12,6 +12,11 @@
|
|||||||
|
|
||||||
var INPUT_ERROR = 'input is invalid type';
|
var INPUT_ERROR = 'input is invalid type';
|
||||||
var FINALIZE_ERROR = 'finalize already called';
|
var FINALIZE_ERROR = 'finalize already called';
|
||||||
|
var TUPLE_ACTIVE_ERROR = 'no active tuple input';
|
||||||
|
var TUPLE_INCOMPLETE_ERROR = 'tuple input is incomplete';
|
||||||
|
var TUPLE_LENGTH_ERROR = 'tuple input exceeds declared length';
|
||||||
|
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) {
|
||||||
@@ -107,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]();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -159,16 +176,59 @@
|
|||||||
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 createTupleHashMethod = function (bits, padding, xof) {
|
||||||
|
var w = CSHAKE_BYTEPAD[bits];
|
||||||
|
var method = createTupleHashOutputMethod(bits, padding, xof, 'hex');
|
||||||
|
method.create = function (outputBits, s) {
|
||||||
|
return new TupleHash(bits, padding, outputBits, xof).bytepad(['TupleHash', s], w);
|
||||||
|
};
|
||||||
|
method.update = function (inputs, outputBits, s) {
|
||||||
|
if (!isArray(inputs)) {
|
||||||
|
throw new Error(INPUT_ERROR);
|
||||||
|
}
|
||||||
|
var hash = method.create(outputBits, s);
|
||||||
|
for (var i = 0; i < inputs.length; ++i) {
|
||||||
|
hash.update(inputs[i]);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
return createOutputMethods(method, function (b, p, outputType) {
|
||||||
|
return createTupleHashOutputMethod(b, p, xof, outputType);
|
||||||
|
}, 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 = [
|
||||||
@@ -176,7 +236,24 @@
|
|||||||
{ 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) {
|
||||||
|
return createTupleHashMethod(bits, padding, false);
|
||||||
|
}},
|
||||||
|
{ name: 'tuplehashxof', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: function (bits, padding) {
|
||||||
|
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);
|
||||||
|
}}
|
||||||
];
|
];
|
||||||
|
|
||||||
var methods = {}, methodNames = [];
|
var methods = {}, methodNames = [];
|
||||||
@@ -290,7 +367,7 @@
|
|||||||
} else {
|
} else {
|
||||||
bytes.unshift(n);
|
bytes.unshift(n);
|
||||||
}
|
}
|
||||||
this.update(bytes);
|
Keccak.prototype.update.call(this, bytes);
|
||||||
return bytes.length;
|
return bytes.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -317,7 +394,7 @@
|
|||||||
bytes = length;
|
bytes = length;
|
||||||
}
|
}
|
||||||
bytes += this.encode(bytes * 8);
|
bytes += this.encode(bytes * 8);
|
||||||
this.update(str);
|
Keccak.prototype.update.call(this, str);
|
||||||
return bytes;
|
return bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -329,7 +406,7 @@
|
|||||||
var paddingBytes = (w - bytes % w) % w;
|
var paddingBytes = (w - bytes % w) % w;
|
||||||
var zeros = [];
|
var zeros = [];
|
||||||
zeros.length = paddingBytes;
|
zeros.length = paddingBytes;
|
||||||
this.update(zeros);
|
Keccak.prototype.update.call(this, zeros);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -451,17 +528,187 @@
|
|||||||
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 () {
|
||||||
this.encode(this.outputBits, true);
|
if (!this.finalized) {
|
||||||
|
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) {
|
||||||
|
Kmac.call(this, bits, padding, outputBits, xof);
|
||||||
|
this.inputActive = false;
|
||||||
|
this.inputBytesRemaining = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TupleHash.prototype = new Kmac();
|
||||||
|
|
||||||
|
TupleHash.prototype.getMessageByteLength = function (message) {
|
||||||
|
var result = formatMessage(message);
|
||||||
|
message = result[0];
|
||||||
|
if (!result[1]) {
|
||||||
|
return message.length;
|
||||||
|
}
|
||||||
|
var bytes = 0;
|
||||||
|
for (var i = 0; i < message.length; ++i) {
|
||||||
|
var code = message.charCodeAt(i);
|
||||||
|
if (code < 0x80) {
|
||||||
|
bytes += 1;
|
||||||
|
} else if (code < 0x800) {
|
||||||
|
bytes += 2;
|
||||||
|
} else if (code < 0xd800 || code >= 0xe000) {
|
||||||
|
bytes += 3;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
bytes += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
TupleHash.prototype.beginInput = function (byteLength) {
|
||||||
|
if (this.inputActive) {
|
||||||
|
throw new Error(TUPLE_INCOMPLETE_ERROR);
|
||||||
|
}
|
||||||
|
if (typeof byteLength !== 'number' || !isFinite(byteLength) || byteLength < 0 ||
|
||||||
|
Math.floor(byteLength) !== byteLength || byteLength > 0x0fffffff) {
|
||||||
|
throw new Error(TUPLE_BYTE_LENGTH_ERROR);
|
||||||
|
}
|
||||||
|
this.encode(byteLength * 8, false);
|
||||||
|
if (byteLength !== 0) {
|
||||||
|
this.inputActive = true;
|
||||||
|
this.inputBytesRemaining = byteLength;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
TupleHash.prototype._updateChunk = function (message, byteLength) {
|
||||||
|
Kmac.prototype.update.call(this, message);
|
||||||
|
this.inputBytesRemaining -= byteLength;
|
||||||
|
if (this.inputBytesRemaining === 0) {
|
||||||
|
this.inputActive = false;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
TupleHash.prototype.updateChunk = function (message) {
|
||||||
|
if (!this.inputActive) {
|
||||||
|
throw new Error(TUPLE_ACTIVE_ERROR);
|
||||||
|
}
|
||||||
|
var byteLength = this.getMessageByteLength(message);
|
||||||
|
if (byteLength > this.inputBytesRemaining) {
|
||||||
|
throw new Error(TUPLE_LENGTH_ERROR);
|
||||||
|
}
|
||||||
|
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 () {
|
||||||
|
if (this.inputActive) {
|
||||||
|
throw new Error(TUPLE_INCOMPLETE_ERROR);
|
||||||
|
}
|
||||||
|
return Kmac.prototype.finalize.call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
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,
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import sha3 from './sha3.js';
|
||||||
|
|
||||||
|
export const {
|
||||||
|
sha3_224,
|
||||||
|
sha3_256,
|
||||||
|
sha3_384,
|
||||||
|
sha3_512,
|
||||||
|
|
||||||
|
keccak_224,
|
||||||
|
keccak_256,
|
||||||
|
keccak_384,
|
||||||
|
keccak_512,
|
||||||
|
keccak224,
|
||||||
|
keccak256,
|
||||||
|
keccak384,
|
||||||
|
keccak512,
|
||||||
|
|
||||||
|
shake_128,
|
||||||
|
shake_256,
|
||||||
|
shake128,
|
||||||
|
shake256,
|
||||||
|
|
||||||
|
cshake_128,
|
||||||
|
cshake_256,
|
||||||
|
cshake128,
|
||||||
|
cshake256,
|
||||||
|
|
||||||
|
kmac_128,
|
||||||
|
kmac_256,
|
||||||
|
kmac128,
|
||||||
|
kmac256,
|
||||||
|
kmacxof_128,
|
||||||
|
kmacxof_256,
|
||||||
|
kmacxof128,
|
||||||
|
kmacxof256,
|
||||||
|
|
||||||
|
tuplehash_128,
|
||||||
|
tuplehash_256,
|
||||||
|
tuplehash128,
|
||||||
|
tuplehash256,
|
||||||
|
tuplehashxof_128,
|
||||||
|
tuplehashxof_256,
|
||||||
|
tuplehashxof128,
|
||||||
|
tuplehashxof256,
|
||||||
|
|
||||||
|
parallelhash_128,
|
||||||
|
parallelhash_256,
|
||||||
|
parallelhash128,
|
||||||
|
parallelhash256,
|
||||||
|
parallelhashxof_128,
|
||||||
|
parallelhashxof_256,
|
||||||
|
parallelhashxof128,
|
||||||
|
parallelhashxof256
|
||||||
|
} = sha3;
|
||||||
|
|
||||||
|
export default sha3;
|
||||||
@@ -16,6 +16,16 @@ function unset() {
|
|||||||
shake256 = null;
|
shake256 = null;
|
||||||
kmac128 = null;
|
kmac128 = null;
|
||||||
kmac256 = null;
|
kmac256 = null;
|
||||||
|
kmacxof128 = null;
|
||||||
|
kmacxof256 = null;
|
||||||
|
tuplehash128 = null;
|
||||||
|
tuplehash256 = null;
|
||||||
|
tuplehashxof128 = 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;
|
||||||
@@ -41,6 +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;
|
||||||
|
tuplehash256 = sha3.tuplehash256;
|
||||||
|
tuplehashxof128 = sha3.tuplehashxof128;
|
||||||
|
tuplehashxof256 = sha3.tuplehashxof256;
|
||||||
|
parallelhash128 = sha3.parallelhash128;
|
||||||
|
parallelhash256 = sha3.parallelhash256;
|
||||||
|
parallelhashxof128 = sha3.parallelhashxof128;
|
||||||
|
parallelhashxof256 = sha3.parallelhashxof256;
|
||||||
}
|
}
|
||||||
|
|
||||||
function runCommonJsTest() {
|
function runCommonJsTest() {
|
||||||
@@ -57,6 +77,8 @@ function runWindowTest(extra) {
|
|||||||
require('./test-shake.js');
|
require('./test-shake.js');
|
||||||
require('./test-cshake.js');
|
require('./test-cshake.js');
|
||||||
require('./test-kmac.js');
|
require('./test-kmac.js');
|
||||||
|
require('./test-tuplehash.js');
|
||||||
|
require('./test-parallelhash.js');
|
||||||
}
|
}
|
||||||
unset();
|
unset();
|
||||||
}
|
}
|
||||||
@@ -108,6 +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;
|
||||||
|
tuplehash256 = sha3.tuplehash256;
|
||||||
|
tuplehashxof128 = sha3.tuplehashxof128;
|
||||||
|
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;
|
||||||
|
|||||||
+95
-56
@@ -1,42 +1,47 @@
|
|||||||
(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
|
||||||
|
// 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];
|
||||||
|
var shortInput = [0x00, 0x01, 0x02, 0x03];
|
||||||
|
var 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
|
||||||
|
];
|
||||||
|
|
||||||
var testCases = [
|
var testCases = [
|
||||||
{
|
{
|
||||||
name: 'kmac128',
|
name: 'kmac128',
|
||||||
method: kmac128,
|
method: kmac128,
|
||||||
cases: [
|
cases: [
|
||||||
{
|
{
|
||||||
input: [0x00, 0x01, 0x02, 0x03],
|
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: '',
|
s: '',
|
||||||
output: 'e5780b0d3ea6f7d3a429c5706aa43a00fadbd7d49628839e3187243f456ee14e'
|
output: 'e5780b0d3ea6f7d3a429c5706aa43a00fadbd7d49628839e3187243f456ee14e'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: [0x00, 0x01, 0x02, 0x03],
|
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: 'My Tagged Application',
|
s: 'My Tagged Application',
|
||||||
output: '3b1fba963cd8b0b59e8c1a6d71888b7143651af8ba0a7070c0979e2811324aa5'
|
output: '3b1fba963cd8b0b59e8c1a6d71888b7143651af8ba0a7070c0979e2811324aa5'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
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: 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: '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);
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -0,0 +1,262 @@
|
|||||||
|
(function (tuplehash256, tuplehash128, tuplehashxof256, tuplehashxof128, kmac128) {
|
||||||
|
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/TupleHash_samples.pdf
|
||||||
|
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/TupleHashXOF_samples.pdf
|
||||||
|
var t1 = [0x00, 0x01, 0x02];
|
||||||
|
var t2 = [0x10, 0x11, 0x12, 0x13, 0x14, 0x15];
|
||||||
|
var t3 = [0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28];
|
||||||
|
|
||||||
|
var testCases = [
|
||||||
|
{
|
||||||
|
name: 'tuplehash128',
|
||||||
|
method: tuplehash128,
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
inputs: [t1, t2],
|
||||||
|
bits: 256,
|
||||||
|
s: '',
|
||||||
|
output: 'c5d8786c1afb9b82111ab34b65b2c0048fa64e6d48e263264ce1707d3ffc8ed1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [t1, t2],
|
||||||
|
bits: 256,
|
||||||
|
s: 'My Tuple App',
|
||||||
|
output: '75cdb20ff4db1154e841d758e24160c54bae86eb8c13e7f5f40eb35588e96dfb'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [t1, t2, t3],
|
||||||
|
bits: 256,
|
||||||
|
s: 'My Tuple App',
|
||||||
|
output: 'e60f202c89a2631eda8d4c588ca5fd07f39e5151998deccf973adb3804bb6e84'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'tuplehash256',
|
||||||
|
method: tuplehash256,
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
inputs: [t1, t2],
|
||||||
|
bits: 512,
|
||||||
|
s: '',
|
||||||
|
output: 'cfb7058caca5e668f81a12a20a2195ce97a925f1dba3e7449a56f82201ec607311ac2696b1ab5ea2352df1423bde7bd4bb78c9aed1a853c78672f9eb23bbe194'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [t1, t2],
|
||||||
|
bits: 512,
|
||||||
|
s: 'My Tuple App',
|
||||||
|
output: '147c2191d5ed7efd98dbd96d7ab5a11692576f5fe2a5065f3e33de6bba9f3aa1c4e9a068a289c61c95aab30aee1e410b0b607de3620e24a4e3bf9852a1d4367e'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [t1, t2, t3],
|
||||||
|
bits: 512,
|
||||||
|
s: 'My Tuple App',
|
||||||
|
output: '45000be63f9b6bfd89f54717670f69a9bc763591a4f05c50d68891a744bcc6e7d6d5b5e82c018da999ed35b0bb49c9678e526abd8e85c13ed254021db9e790ce'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'tuplehashxof128',
|
||||||
|
method: tuplehashxof128,
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
inputs: [t1, t2],
|
||||||
|
bits: 256,
|
||||||
|
s: '',
|
||||||
|
output: '2f103cd7c32320353495c68de1a8129245c6325f6f2a3d608d92179c96e68488'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [t1, t2],
|
||||||
|
bits: 256,
|
||||||
|
s: 'My Tuple App',
|
||||||
|
output: '3fc8ad69453128292859a18b6c67d7ad85f01b32815e22ce839c49ec374e9b9a'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [t1, t2, t3],
|
||||||
|
bits: 256,
|
||||||
|
s: 'My Tuple App',
|
||||||
|
output: '900fe16cad098d28e74d632ed852f99daab7f7df4d99e775657885b4bf76d6f8'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'tuplehashxof256',
|
||||||
|
method: tuplehashxof256,
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
inputs: [t1, t2],
|
||||||
|
bits: 512,
|
||||||
|
s: '',
|
||||||
|
output: '03ded4610ed6450a1e3f8bc44951d14fbc384ab0efe57b000df6b6df5aae7cd568e77377daf13f37ec75cf5fc598b6841d51dd207c991cd45d210ba60ac52eb9'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [t1, t2],
|
||||||
|
bits: 512,
|
||||||
|
s: 'My Tuple App',
|
||||||
|
output: '6483cb3c9952eb20e830af4785851fc597ee3bf93bb7602c0ef6a65d741aeca7e63c3b128981aa05c6d27438c79d2754bb1b7191f125d6620fca12ce658b2442'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [t1, t2, t3],
|
||||||
|
bits: 512,
|
||||||
|
s: 'My Tuple App',
|
||||||
|
output: '0c59b11464f2336c34663ed51b2b950bec743610856f36c28d1d088d8a2446284dd09830a6a178dc752376199fae935d86cfdee5913d4922dfd369b66a53c897'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
testCases.forEach(function (testCase) {
|
||||||
|
describe('#' + testCase.name, function () {
|
||||||
|
testCase.cases.forEach(function (c) {
|
||||||
|
it('should match NIST sample vector', function () {
|
||||||
|
expect(testCase.method(c.inputs, c.bits, c.s)).to.be(c.output);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#tuplehash API', function () {
|
||||||
|
it('should treat empty tuple and empty inputs as valid', function () {
|
||||||
|
var emptyTuple = tuplehash128([], 256, '');
|
||||||
|
var oneEmpty = tuplehash128([''], 256, '');
|
||||||
|
var twoEmpty = tuplehash128(['', ''], 256, '');
|
||||||
|
expect(emptyTuple).to.not.be(oneEmpty);
|
||||||
|
expect(oneEmpty).to.not.be(twoEmpty);
|
||||||
|
expect(twoEmpty).to.not.be(tuplehash128(['', '', ''], 256, ''));
|
||||||
|
expect(tuplehash128.create(256, '').update('').update(t1).hex()).to.be(tuplehash128(['', t1], 256, ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should distinguish tuple boundaries', function () {
|
||||||
|
expect(tuplehash128(['abc', 'd'], 256, '')).to.not.be(tuplehash128(['ab', 'cd'], 256, ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should match instance update and method update with one-shot', function () {
|
||||||
|
var expected = tuplehash128(['abc', 'd'], 256, 'cache');
|
||||||
|
var incremental = tuplehash128.create(256, 'cache').update('abc').update('d').hex();
|
||||||
|
var methodUpdate = tuplehash128.update(['abc'], 256, 'cache').update('d').hex();
|
||||||
|
expect(incremental).to.be(expected);
|
||||||
|
expect(methodUpdate).to.be(expected);
|
||||||
|
expect(tuplehash128.update(['abc', 'd'], 256, 'cache').hex()).to.be(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should stream binary messages in irregular chunks', function () {
|
||||||
|
var bytes = [];
|
||||||
|
for (var i = 0; i < 200; ++i) {
|
||||||
|
bytes.push(i & 0xff);
|
||||||
|
}
|
||||||
|
var expected = tuplehash128([bytes, t1], 256, '');
|
||||||
|
var hash = tuplehash128.create(256, '');
|
||||||
|
hash.beginInput(bytes.length);
|
||||||
|
hash.updateChunk(bytes.slice(0, 1));
|
||||||
|
hash.updateChunk(bytes.slice(1, 17));
|
||||||
|
hash.updateChunk(bytes.slice(17, 168));
|
||||||
|
hash.updateChunk(bytes.slice(168));
|
||||||
|
hash.beginInput(t1.length);
|
||||||
|
hash.updateChunk(t1);
|
||||||
|
expect(hash.hex()).to.be(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should stream ArrayBuffer and Uint8Array views', function () {
|
||||||
|
var expected = tuplehash128([t1, t2], 256, '');
|
||||||
|
var buffer = new Uint8Array(t1).buffer;
|
||||||
|
var view = new Uint8Array(new Uint8Array(t2).buffer, 0, t2.length);
|
||||||
|
var hash = tuplehash128.create(256, '');
|
||||||
|
hash.beginInput(t1.length).updateChunk(buffer);
|
||||||
|
hash.beginInput(t2.length).updateChunk(view);
|
||||||
|
expect(hash.hex()).to.be(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support zero-length streaming input', function () {
|
||||||
|
var expected = tuplehash128(['', t1], 256, '');
|
||||||
|
var hash = tuplehash128.create(256, '');
|
||||||
|
hash.beginInput(0);
|
||||||
|
hash.beginInput(t1.length).updateChunk(t1);
|
||||||
|
expect(hash.hex()).to.be(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject invalid streaming usage', function () {
|
||||||
|
var hash = tuplehash128.create(256, '');
|
||||||
|
expect(function () { hash.updateChunk(t1); }).to.throwError(/no active tuple input/);
|
||||||
|
hash.beginInput(2);
|
||||||
|
expect(function () { hash.updateChunk([1, 2, 3]); }).to.throwError(/exceeds declared length/);
|
||||||
|
expect(function () { hash.beginInput(1); }).to.throwError(/incomplete/);
|
||||||
|
expect(function () { hash.update(t1); }).to.throwError(/incomplete/);
|
||||||
|
expect(function () { hash.hex(); }).to.throwError(/incomplete/);
|
||||||
|
hash.updateChunk([1]);
|
||||||
|
expect(function () { hash.hex(); }).to.throwError(/incomplete/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject invalid beginInput lengths', function () {
|
||||||
|
var hash = tuplehash128.create(256, '');
|
||||||
|
expect(function () { hash.beginInput(-1); }).to.throwError(/byte length is invalid/);
|
||||||
|
expect(function () { hash.beginInput(1.5); }).to.throwError(/byte length is invalid/);
|
||||||
|
expect(function () { hash.beginInput(NaN); }).to.throwError(/byte length is invalid/);
|
||||||
|
expect(function () { hash.beginInput(0x20000000); }).to.throwError(/byte length is invalid/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow repeated output representations', function () {
|
||||||
|
var hash = tuplehash128.create(256, '').update(t1).update(t2);
|
||||||
|
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(t1); }).to.throwError(/finalize already called/);
|
||||||
|
expect(function () { hash.updateChunk(t1); }).to.throwError(/no active tuple input/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should require customization like KMAC', function () {
|
||||||
|
expect(function () { tuplehash128([t1], 256); }).to.throwError(/input is invalid type/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should require inputs to be an array', function () {
|
||||||
|
expect(function () { tuplehash128('abc', 256, ''); }).to.throwError(/input is invalid type/);
|
||||||
|
expect(function () { tuplehash128.update(t1, 256, ''); }).to.throwError(/input is invalid type/);
|
||||||
|
expect(function () { tuplehash128.hex(null, 256, ''); }).to.throwError(/input is invalid type/);
|
||||||
|
expect(function () { tuplehashxof128(undefined, 256, ''); }).to.throwError(/input is invalid type/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should export identical aliases', function () {
|
||||||
|
var sha3 = require('../src/sha3.js');
|
||||||
|
expect(sha3.tuplehash128).to.be(sha3.tuplehash_128);
|
||||||
|
expect(sha3.tuplehash256).to.be(sha3.tuplehash_256);
|
||||||
|
expect(sha3.tuplehashxof128).to.be(sha3.tuplehashxof_128);
|
||||||
|
expect(sha3.tuplehashxof256).to.be(sha3.tuplehashxof_256);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should count UTF-8 string bytes for streaming', function () {
|
||||||
|
var message = 'åbc'; // 2 + 1 + 1 = 4 UTF-8 bytes
|
||||||
|
var expected = tuplehash128([message], 256, '');
|
||||||
|
var hash = tuplehash128.create(256, '');
|
||||||
|
hash.beginInput(4).updateChunk('å').updateChunk('bc');
|
||||||
|
expect(hash.hex()).to.be(expected);
|
||||||
|
expect(message.length).to.be(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should count 3-byte and 4-byte UTF-8 string bytes for streaming', function () {
|
||||||
|
var message = '中\uE000\uD83D\uDE00'; // 3 + 3 + 4 = 10 UTF-8 bytes
|
||||||
|
var expected = tuplehash128([message], 256, '');
|
||||||
|
var hash = tuplehash128.create(256, '');
|
||||||
|
hash.beginInput(10).updateChunk('中').updateChunk('\uE000').updateChunk('\uD83D\uDE00');
|
||||||
|
expect(hash.hex()).to.be(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject update and beginInput after finalize', function () {
|
||||||
|
var hash = tuplehash128.create(256, '').update([0x00]);
|
||||||
|
hash.hex();
|
||||||
|
expect(function () { hash.update([0x01]); }).to.throwError(/finalize already called/);
|
||||||
|
expect(function () { hash.beginInput(1); }).to.throwError(/finalize already called/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#kmac repeated output', function () {
|
||||||
|
it('should allow repeated output reads after finalize fix', function () {
|
||||||
|
var hash = kmac128.create([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], 256, '');
|
||||||
|
hash.update([0x00, 0x01, 0x02, 0x03]);
|
||||||
|
var hex = hash.hex();
|
||||||
|
expect(hash.hex()).to.be(hex);
|
||||||
|
expect(hash.array().length).to.be(32);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})(tuplehash256, tuplehash128, tuplehashxof256, tuplehashxof128, kmac128);
|
||||||
Reference in New Issue
Block a user