Skip to content

Commit

Permalink
Implement blake1 (sha3 proposal)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmillr committed Jan 15, 2025
1 parent d7ed45a commit a4f13a6
Show file tree
Hide file tree
Showing 11 changed files with 763 additions and 17 deletions.
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ The library's initial development was funded by [Ethereum Foundation](https://et

## Usage

> npm install @noble/hashes
> `npm install @noble/hashes`
> deno add jsr:@noble/hashes
> `deno add jsr:@noble/hashes`
> deno doc jsr:@noble/hashes # command-line documentation
> `deno doc jsr:@noble/hashes` # command-line documentation
We support all major platforms and runtimes.
For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values).
Expand All @@ -55,7 +55,7 @@ console.log(sha256('abc')); // == sha256(new TextEncoder().encode('abc'))
- [sha2: sha256, sha384, sha512](#sha2-sha256-sha384-sha512-and-others)
- [sha3: FIPS, SHAKE, Keccak](#sha3-fips-shake-keccak)
- [sha3-addons: cSHAKE, KMAC, K12, M14, TurboSHAKE](#sha3-addons-cshake-kmac-k12-m14-turboshake)
- [ripemd160](#ripemd160) | [blake2b, blake2s, blake3](#blake2b-blake2s-blake3) | [sha1: legacy hash](#sha1-legacy-hash)
- [ripemd160](#ripemd160) | [blake, blake2b, blake2s, blake3](#blake-blake2b-blake2s-blake3) | [sha1: legacy hash](#sha1-legacy-hash)
- MACs: [hmac](#hmac) (also sha3-addons [kmac](#sha3-addons-cshake-kmac-k12-m14-turboshake), blake3 [key mode](#blake2b-blake2s-blake3))
- KDFs: [hkdf](#hkdf) | [pbkdf2](#pbkdf2) | [scrypt](#scrypt) | [argon2](#argon2)
- [utils](#utils)
Expand Down Expand Up @@ -193,13 +193,19 @@ const hash9 = ripemd160
See [RFC 2286](https://datatracker.ietf.org/doc/html/rfc2286),
[Website](https://homes.esat.kuleuven.be/~bosselae/ripemd160.html)

#### blake2b, blake2s, blake3
#### blake, blake2b, blake2s, blake3

```typescript
import { blake224, blake256, blake384, blake512 } from '@noble/hashes/blake1';
import { blake2b } from '@noble/hashes/blake2b';
import { blake2s } from '@noble/hashes/blake2s';
import { blake3 } from '@noble/hashes/blake3';

const h_b1_224 = blake224('abc');
const h_b1_256 = blake256('abc');
const h_b1_384 = blake384('abc');
const h_b1_512 = blake512('abc');

const h10a = blake2s('abc');
const b2params = { key: new Uint8Array([1]), personalization: t, salt: t, dkLen: 32 };
const h10b = blake2s('abc', b2params);
Expand All @@ -214,7 +220,9 @@ const h11_mac = blake3('abc', { key: new Uint8Array(32) });
const h11_kdf = blake3('abc', { context: 'application name' });
```

See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693), [Website](https://www.blake2.net).
* Blake1 is legacy hash, one of SHA3 proposals. It is rarely used anywhere. See [pdf](https://www.aumasson.jp/blake/blake.pdf).
* Blake2 is popular fast hash. blake2b focuses on 64-bit platforms while blake2s is for 8-bit to 32-bit ones. See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693), [Website](https://www.blake2.net)
* Blake3 is faster, reduced-round blake2. See [Website & specs](https://blake3.io)

#### sha1: legacy hash

Expand Down
18 changes: 18 additions & 0 deletions benchmark/hashes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { sha256, sha384, sha512 } from '@noble/hashes/sha2';
// import { sha224, sha512_256, sha512_384 } from '@noble/hashes/sha2';
import { sha3_256 } from '@noble/hashes/sha3';
import { k12, m14 } from '@noble/hashes/sha3-addons';
import { blake256, blake512 } from '@noble/hashes/blake1';
import { blake2b } from '@noble/hashes/blake2b';
import { blake2s } from '@noble/hashes/blake2s';
import { blake3 } from '@noble/hashes/blake3';
Expand All @@ -22,6 +23,7 @@ import stable2_512 from '@stablelib/sha512';
import stable3 from '@stablelib/sha3';
import stableb2b from '@stablelib/blake2b';
import stableb2s from '@stablelib/blake2s';
import _blakehash from 'blake-hash/js.js';
import jssha3 from 'js-sha3';
import nobleUnrolled from 'unrolled-nbl-hashes-sha3';
import { SHA3 as _SHA3 } from 'sha3';
Expand All @@ -31,6 +33,14 @@ const wasm = {};
const wrapBuf = (arrayBuffer) => new Uint8Array(arrayBuffer);
const ONLY_NOBLE = process.argv[2] === 'noble';

const blake_hash = (name) => {
return (buf) => {
const h = _blakehash(name);
h.update(Buffer.from(buf));
return Uint8Array.from(h.digest());
};
};

const HASHES = {
SHA256: {
node: (buf) => crypto_createHash('sha256').update(buf).digest(),
Expand Down Expand Up @@ -67,6 +77,14 @@ const HASHES = {
},
Kangaroo12: { noble: (buf) => k12(buf) },
Marsupilami14: { noble: (buf) => m14(buf) },
Blake256: {
'blake-hash': blake_hash('blake256'),
noble: blake256,
},
Blake512: {
'blake-hash': blake_hash('blake512'),
noble: blake512,
},
BLAKE2b: {
node: (buf) => crypto_createHash('blake2b512').update(buf).digest(),
'hash-wasm': (buf) => wasm.blake2b.init().update(buf).digest(),
Expand Down
1 change: 1 addition & 0 deletions benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@stablelib/sha384": "1.0.1",
"@stablelib/sha512": "1.0.1",
"@stablelib/sha512_256": "1.0.1",
"blake-hash": "2.0.0",
"create-hash": "1.2.0",
"create-hmac": "1.1.7",
"fast-sha256": "1.3.0",
Expand Down
1 change: 0 additions & 1 deletion build/input.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes, randomBytes } from '@noble/hashes/utils';

export { blake2b } from '@noble/hashes/blake2b';
export { blake2s } from '@noble/hashes/blake2s';
export { blake3 } from '@noble/hashes/blake3';
Expand Down
2 changes: 1 addition & 1 deletion build/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions jsr.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"./_assert": "./src/_assert.ts",
"./_md": "./src/_md.ts",
"./argon2": "./src/argon2.ts",
"./blake1": "./src/blake1.ts",
"./blake2b": "./src/blake2b.ts",
"./blake2s": "./src/blake2s.ts",
"./blake3": "./src/blake3.ts",
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"test": "node --import ./test/esm-register.js test/index.js",
"test:dos": "node --import ./test/esm-register.js test/slow-dos.test.js",
"test:big": "node --import ./test/esm-register.js test/slow-big.test.js",
"test:slowkdf": "node --import ./test/esm-register.js test/slow-kdf.test.js",
"test:coverage": "c8 npm test"
},
"author": "Paul Miller (https://paulmillr.com)",
Expand Down Expand Up @@ -67,6 +68,10 @@
"import": "./esm/argon2.js",
"require": "./argon2.js"
},
"./blake1": {
"import": "./esm/blake1.js",
"require": "./blake1.js"
},
"./blake2b": {
"import": "./esm/blake2b.js",
"require": "./blake2b.js"
Expand Down
12 changes: 11 additions & 1 deletion src/_blake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
import { anumber, aexists, aoutput } from './_assert.js';
import { Hash, Input, toBytes, u32, isLE, byteSwap32, byteSwapIfBE } from './utils.js';

// For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1].
/**
* Internal blake variable.
* For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1].
*/
// prettier-ignore
export const SIGMA: Uint8Array = /* @__PURE__ */ new Uint8Array([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
Expand All @@ -20,15 +23,22 @@ export const SIGMA: Uint8Array = /* @__PURE__ */ new Uint8Array([
10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
// Blake1, unused in others
11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
]);

/** Blake hash options. dkLen is output length. key is used in MAC mode. salt is used in KDF mode. */
export type BlakeOpts = {
dkLen?: number;
key?: Input;
salt?: Input;
personalization?: Input;
};

/** Class, from which others are subclassed. */
export abstract class BLAKE<T extends BLAKE<T>> extends Hash<T> {
protected abstract compress(msg: Uint32Array, offset: number, isLast: boolean): void;
protected abstract get(): number[];
Expand Down
Loading

0 comments on commit a4f13a6

Please sign in to comment.