clean up blake2b external lib

This commit is contained in:
2023-08-27 16:37:04 -06:00
parent f9ee10047b
commit 2b44db1ee7
6 changed files with 6 additions and 693 deletions
+6 -118
View File
@@ -1,121 +1,9 @@
blakejs
====
# blakejs
[![travis ci](https://travis-ci.org/dcposch/blakejs.svg?branch=master)](https://travis-ci.org/dcposch/blakejs)
[![npm version](https://badge.fury.io/js/blakejs.svg)](https://badge.fury.io/js/blakejs)
This is the [blakejs](https://www.npmjs.com/package/blakejs) library adapted
for [the jex package manager](../../utils/jex).
**blakejs is a pure Javascript implementation of the BLAKE2b and BLAKE2s hash functions.**
I (Peter) only included the subset of blake which is actually used, the blake2b
module. The package is modified to "just work" with the ES6 module system.
![blake1](https://cloud.githubusercontent.com/assets/169280/25921238/9bf1877a-3589-11e7-8a93-74b69c3874bb.jpg)
---
[RFC 7693: The BLAKE Cryptographic Hash and MAC](https://tools.ietf.org/html/rfc7693)
BLAKE is the default family of hash functions in the venerable NaCl crypto library. Like SHA2 and SHA3 but unlike MD5 and SHA1, BLAKE offers solid security. With an optimized assembly implementation, BLAKE can be faster than all of those other hash functions.
Of course, this implementation is in Javascript, so it won't be winning any speed records. More under Performance below. It's short and sweet, less than 500 LOC.
**As far as I know, this package is the easiest way to compute Blake2 in the browser.**
Other options to consider:
- [@nazar-pc](https://github.com/nazar-pc) has WebAssembly implementation for higher performance where supported: [blake2.wasm](https://github.com/nazar-pc/blake2.wasm)
- [@emilbayes](https://github.com/emilbayes) has a Blake2b-only implementation with salt support; WASM with automatic JS fallback: [blake2b](https://github.com/emilbayes/blake2b)
- On node, you probably want the native wrapper [node-blake2](https://github.com/ludios/node-blake2)
Quick Start
---
```
$ npm install --save blakejs
```
```js
var blake = require('blakejs')
console.log(blake.blake2bHex('abc'))
// prints ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923
console.log(blake.blake2sHex('abc'))
// prints 508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982
```
API
---
### 1. Use `blake2b` to compute a BLAKE2b hash
Pass it a string, `Buffer`, or `Uint8Array` containing bytes to hash, and it will return a `Uint8Array` containing the hash.
```js
// Computes the BLAKE2B hash of a string or byte array, and returns a Uint8Array
//
// Returns a n-byte Uint8Array
//
// Parameters:
// - input - the input bytes, as a string, Buffer, or Uint8Array
// Strings are converted to UTF8 bytes
// - key - optional key Uint8Array, up to 64 bytes
// - outlen - optional output length in bytes, default 64
function blake2b(input, key, outlen) {
[...]
}
```
For convenience, `blake2bHex` takes the same arguments and works the same way, but returns a hex string.
### 2. Use `blake2b[Init,Update,Final]` to compute a streaming hash
```js
var KEY = null // optional key
var OUTPUT_LENGTH = 64 // bytes
var context = blake2bInit(OUTPUT_LENGTH, KEY)
...
// each time you get a byte array from the stream:
blake2bUpdate(context, bytes)
...
// finally, once the stream has been exhausted
var hash = blake2bFinal(context)
// returns a 64-byte hash, as a Uint8Array
```
### 3. All `blake2b*` functions have `blake2s*` equivalents
BLAKE2b: `blake2b`, `blake2bHex`, `blake2bInit`, `blake2bUpdate`, and `blake2bFinal`
BLAKE2s: `blake2s`, `blake2sHex`, `blake2sInit`, `blake2sUpdate`, and `blake2sFinal`
The inputs are identical except that maximum key size and maximum output size are 32 bytes instead of 64.
Limitations
---
* Can only handle up to 2**53 bytes of input
If your webapp is hashing more than 8 petabytes, you may have other problems :)
Testing
---
* Examples from the RFC
* BLAKE2s self-test from the RFC
* Examples from http://pythonhosted.org/pyblake2/examples.html
* A longer set of test vectors generated by https://github.com/jedisct1/crypto-test-vectors/tree/master/crypto/hash/blake2/blake2b/nosalt-nopersonalization/generators/libsodium
Performance
---
```
BLAKE2b: 15.2 MB / second on a 2.2GHz i7-4770HQ
BLAKE2s: 20.4 MB / second
¯\_(ツ)_/¯
```
If you're using BLAKE2b in server side node.js code, you probably want the [native wrapper](https://www.npmjs.com/package/blake2) which should be able to do several hundred MB / second on the same processor.
If you're using BLAKE2b in a web app, 15 MB/sec might be fine.
Javascript doesn't have 64-bit integers, and BLAKE2b is a 64-bit integer algorithm. Writing it with`Uint32Array` is not that fast. BLAKE2s is a 32-bit algorithm, so it's a bit faster.
If we want better machine code at the expense of gross-looking Javascript, we could use asm.js
License
---
Creative Commons CC0. Ported from the reference C implementation in
[RFC 7693](https://tools.ietf.org/html/rfc7693).
For internal use in Jack Russell
-353
View File
@@ -1,353 +0,0 @@
// BLAKE2s hash function in pure Javascript
// Adapted from the reference implementation in RFC7693
// Ported to Javascript by DC - https://github.com/dcposch
const util = require('./util')
// Little-endian byte access.
// Expects a Uint8Array and an index
// Returns the little-endian uint32 at v[i..i+3]
function B2S_GET32 (v, i) {
return v[i] ^ (v[i + 1] << 8) ^ (v[i + 2] << 16) ^ (v[i + 3] << 24)
}
// Mixing function G.
function B2S_G (a, b, c, d, x, y) {
v[a] = v[a] + v[b] + x
v[d] = ROTR32(v[d] ^ v[a], 16)
v[c] = v[c] + v[d]
v[b] = ROTR32(v[b] ^ v[c], 12)
v[a] = v[a] + v[b] + y
v[d] = ROTR32(v[d] ^ v[a], 8)
v[c] = v[c] + v[d]
v[b] = ROTR32(v[b] ^ v[c], 7)
}
// 32-bit right rotation
// x should be a uint32
// y must be between 1 and 31, inclusive
function ROTR32 (x, y) {
return (x >>> y) ^ (x << (32 - y))
}
// Initialization Vector.
const BLAKE2S_IV = new Uint32Array([
0x6a09e667,
0xbb67ae85,
0x3c6ef372,
0xa54ff53a,
0x510e527f,
0x9b05688c,
0x1f83d9ab,
0x5be0cd19
])
const SIGMA = new Uint8Array([
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,
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,
12,
5,
1,
15,
14,
13,
4,
10,
0,
7,
6,
3,
9,
2,
8,
11,
13,
11,
7,
14,
12,
1,
3,
9,
5,
0,
15,
4,
8,
6,
2,
10,
6,
15,
14,
9,
11,
3,
0,
8,
12,
2,
13,
7,
1,
4,
10,
5,
10,
2,
8,
4,
7,
6,
1,
5,
15,
11,
9,
14,
3,
12,
13,
0
])
// Compression function. "last" flag indicates last block
const v = new Uint32Array(16)
const m = new Uint32Array(16)
function blake2sCompress (ctx, last) {
let i = 0
for (i = 0; i < 8; i++) {
// init work variables
v[i] = ctx.h[i]
v[i + 8] = BLAKE2S_IV[i]
}
v[12] ^= ctx.t // low 32 bits of offset
v[13] ^= ctx.t / 0x100000000 // high 32 bits
if (last) {
// last block flag set ?
v[14] = ~v[14]
}
for (i = 0; i < 16; i++) {
// get little-endian words
m[i] = B2S_GET32(ctx.b, 4 * i)
}
// ten rounds of mixing
// uncomment the DebugPrint calls to log the computation
// and match the RFC sample documentation
// util.debugPrint(' m[16]', m, 32)
for (i = 0; i < 10; i++) {
// util.debugPrint(' (i=' + i + ') v[16]', v, 32)
B2S_G(0, 4, 8, 12, m[SIGMA[i * 16 + 0]], m[SIGMA[i * 16 + 1]])
B2S_G(1, 5, 9, 13, m[SIGMA[i * 16 + 2]], m[SIGMA[i * 16 + 3]])
B2S_G(2, 6, 10, 14, m[SIGMA[i * 16 + 4]], m[SIGMA[i * 16 + 5]])
B2S_G(3, 7, 11, 15, m[SIGMA[i * 16 + 6]], m[SIGMA[i * 16 + 7]])
B2S_G(0, 5, 10, 15, m[SIGMA[i * 16 + 8]], m[SIGMA[i * 16 + 9]])
B2S_G(1, 6, 11, 12, m[SIGMA[i * 16 + 10]], m[SIGMA[i * 16 + 11]])
B2S_G(2, 7, 8, 13, m[SIGMA[i * 16 + 12]], m[SIGMA[i * 16 + 13]])
B2S_G(3, 4, 9, 14, m[SIGMA[i * 16 + 14]], m[SIGMA[i * 16 + 15]])
}
// util.debugPrint(' (i=10) v[16]', v, 32)
for (i = 0; i < 8; i++) {
ctx.h[i] ^= v[i] ^ v[i + 8]
}
// util.debugPrint('h[8]', ctx.h, 32)
}
// Creates a BLAKE2s hashing context
// Requires an output length between 1 and 32 bytes
// Takes an optional Uint8Array key
function blake2sInit (outlen, key) {
if (!(outlen > 0 && outlen <= 32)) {
throw new Error('Incorrect output length, should be in [1, 32]')
}
const keylen = key ? key.length : 0
if (key && !(keylen > 0 && keylen <= 32)) {
throw new Error('Incorrect key length, should be in [1, 32]')
}
const ctx = {
h: new Uint32Array(BLAKE2S_IV), // hash state
b: new Uint8Array(64), // input block
c: 0, // pointer within block
t: 0, // input count
outlen: outlen // output length in bytes
}
ctx.h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen
if (keylen > 0) {
blake2sUpdate(ctx, key)
ctx.c = 64 // at the end
}
return ctx
}
// Updates a BLAKE2s streaming hash
// Requires hash context and Uint8Array (byte array)
function blake2sUpdate (ctx, input) {
for (let i = 0; i < input.length; i++) {
if (ctx.c === 64) {
// buffer full ?
ctx.t += ctx.c // add counters
blake2sCompress(ctx, false) // compress (not last)
ctx.c = 0 // counter to zero
}
ctx.b[ctx.c++] = input[i]
}
}
// Completes a BLAKE2s streaming hash
// Returns a Uint8Array containing the message digest
function blake2sFinal (ctx) {
ctx.t += ctx.c // mark last block offset
while (ctx.c < 64) {
// fill up with zeros
ctx.b[ctx.c++] = 0
}
blake2sCompress(ctx, true) // final block flag = 1
// little endian convert and store
const out = new Uint8Array(ctx.outlen)
for (let i = 0; i < ctx.outlen; i++) {
out[i] = (ctx.h[i >> 2] >> (8 * (i & 3))) & 0xff
}
return out
}
// Computes the BLAKE2S hash of a string or byte array, and returns a Uint8Array
//
// Returns a n-byte Uint8Array
//
// Parameters:
// - input - the input bytes, as a string, Buffer, or Uint8Array
// - key - optional key Uint8Array, up to 32 bytes
// - outlen - optional output length in bytes, default 64
function blake2s (input, key, outlen) {
// preprocess inputs
outlen = outlen || 32
input = util.normalizeInput(input)
// do the math
const ctx = blake2sInit(outlen, key)
blake2sUpdate(ctx, input)
return blake2sFinal(ctx)
}
// Computes the BLAKE2S hash of a string or byte array
//
// Returns an n-byte hash in hex, all lowercase
//
// Parameters:
// - input - the input bytes, as a string, Buffer, or Uint8Array
// - key - optional key Uint8Array, up to 32 bytes
// - outlen - optional output length in bytes, default 64
function blake2sHex (input, key, outlen) {
const output = blake2s(input, key, outlen)
return util.toHex(output)
}
module.exports = {
blake2s: blake2s,
blake2sHex: blake2sHex,
blake2sInit: blake2sInit,
blake2sUpdate: blake2sUpdate,
blake2sFinal: blake2sFinal
}
-96
View File
@@ -1,96 +0,0 @@
export interface Blake2bCTX {
b: Uint8Array;
h: Uint32Array;
t: number;
c: number;
outlen: number;
}
/**
* Creates a Blake2b hashing context
* @param outlen between 1 and 64
* @param key optional
* @returns the hashing context
*/
export declare function blake2bInit(outlen?: number, key?: Uint8Array): Blake2bCTX;
/**
* Updates a Blake2b streaming hash
* @param ctx hashing context from blake2bInit()
* @param input Byte array
*/
export declare function blake2bUpdate(ctx: Blake2bCTX, input: ArrayLike<number>): void;
/**
* Completes a Blake2b streaming hash
* @param ctx hashing context from blake2bInit()
* @returns the final hash
*/
export declare function blake2bFinal(ctx: Blake2bCTX): Uint8Array;
/**
*
* @param input the input bytes, as a string, Buffer, or Uint8Array
* @param key optional key Uint8Array, up to 64 bytes
* @param outlen optional output length in bytes, defaults to 64
* @returns an n-byte Uint8Array
*/
export declare function blake2b(input: string | Uint8Array, key?: Uint8Array, outlen?: number): Uint8Array;
/**
* Computes the Blake2b hash of a string or byte array
*
* @param input the input bytes, as a string, Buffer, or Uint8Array
* @param key optional key Uint8Array, up to 64 bytes
* @param outlen outlen - optional output length in bytes, defaults to 64
* @returns an n-byte hash in hex, all lowercase
*/
export declare function blake2bHex(input: string | Uint8Array, key?: Uint8Array, outlen?: number): string;
export interface Blake2sCTX {
h: Uint32Array;
b: Uint8Array;
c: number;
t: number;
outlen: number;
}
/**
* Creates a Blake2s hashing context
* @param outlen between 1 and 32
* @param key optional Uint8Array key
* @returns the hashing context
*/
export declare function blake2sInit(outlen: number, key?: Uint8Array): Blake2sCTX;
/**
* Updates a Blake2s streaming hash
* @param ctx hashing context from blake2sinit()
* @param input byte array
*/
export declare function blake2sUpdate(ctx: Blake2sCTX, input: ArrayLike<number>): void;
/**
* Completes a Blake2s streaming hash
* @param ctx hashing context from blake2sinit()
* @returns Uint8Array containing the message digest
*/
export declare function blake2sFinal(ctx: Blake2sCTX): Uint8Array;
/**
* Computes the Blake2s hash of a string or byte array, and returns a Uint8Array
* @param input the input bytes, as a string, Buffer, or Uint8Array
* @param key optional key Uint8Array, up to 32 bytes
* @param outlen optional output length in bytes, defaults to 64
* @returns an n-byte Uint8Array
*/
export declare function blake2s(input: string | Uint8Array, key?: Uint8Array, outlen?: number): Uint8Array;
/**
*
* @param input the input bytes, as a string, Buffer, or Uint8Array
* @param key optional key Uint8Array, up to 32 bytes
* @param outlen optional output length in bytes, defaults to 64
* @returns an n-byte hash in hex, all lowercase
*/
export declare function blake2sHex(input: string | Uint8Array, key?: Uint8Array, outlen?: number): string;
-15
View File
@@ -1,15 +0,0 @@
const b2b = require('./blake2b')
const b2s = require('./blake2s')
module.exports = {
blake2b: b2b.blake2b,
blake2bHex: b2b.blake2bHex,
blake2bInit: b2b.blake2bInit,
blake2bUpdate: b2b.blake2bUpdate,
blake2bFinal: b2b.blake2bFinal,
blake2s: b2s.blake2s,
blake2sHex: b2s.blake2sHex,
blake2sInit: b2s.blake2sInit,
blake2sUpdate: b2s.blake2sUpdate,
blake2sFinal: b2s.blake2sFinal
}
-96
View File
@@ -1,96 +0,0 @@
export interface Blake2bCTX {
b: Uint8Array;
h: Uint32Array;
t: number;
c: number;
outlen: number;
}
/**
* Creates a Blake2b hashing context
* @param outlen between 1 and 64
* @param key optional
* @returns the hashing context
*/
export declare function blake2bInit(outlen?: number, key?: Uint8Array): Blake2bCTX;
/**
* Updates a Blake2b streaming hash
* @param ctx hashing context from blake2bInit()
* @param input Byte array
*/
export declare function blake2bUpdate(ctx: Blake2bCTX, input: ArrayLike<number>): void;
/**
* Completes a Blake2b streaming hash
* @param ctx hashing context from blake2bInit()
* @returns the final hash
*/
export declare function blake2bFinal(ctx: Blake2bCTX): Uint8Array;
/**
*
* @param input the input bytes, as a string, Buffer, or Uint8Array
* @param key optional key Uint8Array, up to 64 bytes
* @param outlen optional output length in bytes, defaults to 64
* @returns an n-byte Uint8Array
*/
export declare function blake2b(input: string | Uint8Array, key?: Uint8Array, outlen?: number): Uint8Array;
/**
* Computes the Blake2b hash of a string or byte array
*
* @param input the input bytes, as a string, Buffer, or Uint8Array
* @param key optional key Uint8Array, up to 64 bytes
* @param outlen outlen - optional output length in bytes, defaults to 64
* @returns an n-byte hash in hex, all lowercase
*/
export declare function blake2bHex(input: string | Uint8Array, key?: Uint8Array, outlen?: number): string;
export interface Blake2sCTX {
h: Uint32Array;
b: Uint8Array;
c: number;
t: number;
outlen: number;
}
/**
* Creates a Blake2s hashing context
* @param outlen between 1 and 32
* @param key optional Uint8Array key
* @returns the hashing context
*/
export declare function blake2sInit(outlen: number, key?: Uint8Array): Blake2sCTX;
/**
* Updates a Blake2s streaming hash
* @param ctx hashing context from blake2sinit()
* @param input byte array
*/
export declare function blake2sUpdate(ctx: Blake2sCTX, input: ArrayLike<number>): void;
/**
* Completes a Blake2s streaming hash
* @param ctx hashing context from blake2sinit()
* @returns Uint8Array containing the message digest
*/
export declare function blake2sFinal(ctx: Blake2sCTX): Uint8Array;
/**
* Computes the Blake2s hash of a string or byte array, and returns a Uint8Array
* @param input the input bytes, as a string, Buffer, or Uint8Array
* @param key optional key Uint8Array, up to 32 bytes
* @param outlen optional output length in bytes, defaults to 64
* @returns an n-byte Uint8Array
*/
export declare function blake2s(input: string | Uint8Array, key?: Uint8Array, outlen?: number): Uint8Array;
/**
*
* @param input the input bytes, as a string, Buffer, or Uint8Array
* @param key optional key Uint8Array, up to 32 bytes
* @param outlen optional output length in bytes, defaults to 64
* @returns an n-byte hash in hex, all lowercase
*/
export declare function blake2sHex(input: string | Uint8Array, key?: Uint8Array, outlen?: number): string;
-15
View File
@@ -1,15 +0,0 @@
const b2b = require('./blake2b')
const b2s = require('./blake2s')
module.exports = {
blake2b: b2b.blake2b,
blake2bHex: b2b.blake2bHex,
blake2bInit: b2b.blake2bInit,
blake2bUpdate: b2b.blake2bUpdate,
blake2bFinal: b2b.blake2bFinal,
blake2s: b2s.blake2s,
blake2sHex: b2s.blake2sHex,
blake2sInit: b2s.blake2sInit,
blake2sUpdate: b2s.blake2sUpdate,
blake2sFinal: b2s.blake2sFinal
}