@noble/hashes
Advanced tools
Comparing version 1.0.0 to 1.1.0
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.BLAKE2 = exports.SIGMA = void 0; | ||
const _assert_js_1 = require("./_assert.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -30,5 +31,5 @@ // prettier-ignore | ||
this.destroyed = false; | ||
(0, utils_js_1.assertNumber)(blockLen); | ||
(0, utils_js_1.assertNumber)(outputLen); | ||
(0, utils_js_1.assertNumber)(keyLen); | ||
_assert_js_1.default.number(blockLen); | ||
_assert_js_1.default.number(outputLen); | ||
_assert_js_1.default.number(keyLen); | ||
if (outputLen < 0 || outputLen > keyLen) | ||
@@ -45,4 +46,3 @@ throw new Error('Blake2: outputLen bigger than keyLen'); | ||
update(data) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
_assert_js_1.default.exists(this); | ||
// Main difference with other hashes: there is flag for last block, | ||
@@ -52,5 +52,3 @@ // so we cannot process current block before we know that there | ||
// to do zero-copy processing | ||
const { finished, blockLen, buffer, buffer32 } = this; | ||
if (finished) | ||
throw new Error('digest() was already called'); | ||
const { blockLen, buffer, buffer32 } = this; | ||
data = (0, utils_js_1.toBytes)(data); | ||
@@ -83,9 +81,5 @@ const len = data.length; | ||
digestInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array) || out.length < this.outputLen) | ||
throw new Error('_Blake2: Invalid output buffer'); | ||
const { finished, pos, buffer32 } = this; | ||
if (finished) | ||
throw new Error('digest() was already called'); | ||
_assert_js_1.default.exists(this); | ||
_assert_js_1.default.output(out, this); | ||
const { pos, buffer32 } = this; | ||
this.finished = true; | ||
@@ -92,0 +86,0 @@ // Padding |
20
_sha2.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SHA2 = void 0; | ||
const _assert_js_1 = require("./_assert.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -34,7 +35,4 @@ // Polyfill for Safari 14 | ||
update(data) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
const { view, buffer, blockLen, finished } = this; | ||
if (finished) | ||
throw new Error('digest() was already called'); | ||
_assert_js_1.default.exists(this); | ||
const { view, buffer, blockLen } = this; | ||
data = (0, utils_js_1.toBytes)(data); | ||
@@ -64,8 +62,4 @@ const len = data.length; | ||
digestInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array) || out.length < this.outputLen) | ||
throw new Error('_Sha2: Invalid output buffer'); | ||
if (this.finished) | ||
throw new Error('digest() was already called'); | ||
_assert_js_1.default.exists(this); | ||
_assert_js_1.default.output(out, this); | ||
this.finished = true; | ||
@@ -88,5 +82,5 @@ // Padding | ||
buffer[i] = 0; | ||
// NOTE: sha512 requires length to be 128bit integer, but length in JS will overflow before that | ||
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that | ||
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen. | ||
// So we just write lowest 64bit of that value. | ||
// So we just write lowest 64 bits of that value. | ||
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE); | ||
@@ -93,0 +87,0 @@ this.process(view, 0); |
@@ -7,14 +7,2 @@ export declare function fromBig(n: bigint, le?: boolean): { | ||
export declare const toBig: (h: number, l: number) => bigint; | ||
export declare const shrSH: (h: number, l: number, s: number) => number; | ||
export declare const shrSL: (h: number, l: number, s: number) => number; | ||
export declare const rotrSH: (h: number, l: number, s: number) => number; | ||
export declare const rotrSL: (h: number, l: number, s: number) => number; | ||
export declare const rotrBH: (h: number, l: number, s: number) => number; | ||
export declare const rotrBL: (h: number, l: number, s: number) => number; | ||
export declare const rotr32H: (h: number, l: number) => number; | ||
export declare const rotr32L: (h: number, l: number) => number; | ||
export declare const rotlSH: (h: number, l: number, s: number) => number; | ||
export declare const rotlSL: (h: number, l: number, s: number) => number; | ||
export declare const rotlBH: (h: number, l: number, s: number) => number; | ||
export declare const rotlBL: (h: number, l: number, s: number) => number; | ||
export declare function add(Ah: number, Al: number, Bh: number, Bl: number): { | ||
@@ -24,7 +12,26 @@ h: number; | ||
}; | ||
export declare const add3L: (Al: number, Bl: number, Cl: number) => number; | ||
export declare const add3H: (low: number, Ah: number, Bh: number, Ch: number) => number; | ||
export declare const add4L: (Al: number, Bl: number, Cl: number, Dl: number) => number; | ||
export declare const add4H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number) => number; | ||
export declare const add5L: (Al: number, Bl: number, Cl: number, Dl: number, El: number) => number; | ||
export declare const add5H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number) => number; | ||
declare const u64: { | ||
fromBig: typeof fromBig; | ||
split: typeof split; | ||
toBig: (h: number, l: number) => bigint; | ||
shrSH: (h: number, l: number, s: number) => number; | ||
shrSL: (h: number, l: number, s: number) => number; | ||
rotrSH: (h: number, l: number, s: number) => number; | ||
rotrSL: (h: number, l: number, s: number) => number; | ||
rotrBH: (h: number, l: number, s: number) => number; | ||
rotrBL: (h: number, l: number, s: number) => number; | ||
rotr32H: (h: number, l: number) => number; | ||
rotr32L: (h: number, l: number) => number; | ||
rotlSH: (h: number, l: number, s: number) => number; | ||
rotlSL: (h: number, l: number, s: number) => number; | ||
rotlBH: (h: number, l: number, s: number) => number; | ||
rotlBL: (h: number, l: number, s: number) => number; | ||
add: typeof add; | ||
add3L: (Al: number, Bl: number, Cl: number) => number; | ||
add3H: (low: number, Ah: number, Bh: number, Ch: number) => number; | ||
add4L: (Al: number, Bl: number, Cl: number, Dl: number) => number; | ||
add4H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number) => number; | ||
add5H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number) => number; | ||
add5L: (Al: number, Bl: number, Cl: number, Dl: number, El: number) => number; | ||
}; | ||
export default u64; |
32
_u64.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.add5H = exports.add5L = exports.add4H = exports.add4L = exports.add3H = exports.add3L = exports.add = exports.rotlBL = exports.rotlBH = exports.rotlSL = exports.rotlSH = exports.rotr32L = exports.rotr32H = exports.rotrBL = exports.rotrBH = exports.rotrSL = exports.rotrSH = exports.shrSL = exports.shrSH = exports.toBig = exports.split = exports.fromBig = void 0; | ||
exports.add = exports.toBig = exports.split = exports.fromBig = void 0; | ||
const U32_MASK64 = BigInt(2 ** 32 - 1); | ||
const _32n = BigInt(32); | ||
// We are not using BigUint64Array, because they are extremely slow as per 2022 | ||
function fromBig(n, le = false) { | ||
@@ -26,32 +27,21 @@ if (le) | ||
const shrSH = (h, l, s) => h >>> s; | ||
exports.shrSH = shrSH; | ||
const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); | ||
exports.shrSL = shrSL; | ||
// Right rotate for Shift in [1, 32) | ||
const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s)); | ||
exports.rotrSH = rotrSH; | ||
const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); | ||
exports.rotrSL = rotrSL; | ||
// Right rotate for Shift in (32, 64), NOTE: 32 is special case. | ||
const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32)); | ||
exports.rotrBH = rotrBH; | ||
const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s)); | ||
exports.rotrBL = rotrBL; | ||
// Right rotate for shift===32 (just swaps l&h) | ||
const rotr32H = (h, l) => l; | ||
exports.rotr32H = rotr32H; | ||
const rotr32L = (h, l) => h; | ||
exports.rotr32L = rotr32L; | ||
// Left rotate for Shift in [1, 32) | ||
const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s)); | ||
exports.rotlSH = rotlSH; | ||
const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s)); | ||
exports.rotlSL = rotlSL; | ||
// Left rotate for Shift in (32, 64), NOTE: 32 is special case. | ||
const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s)); | ||
exports.rotlBH = rotlBH; | ||
const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s)); | ||
exports.rotlBL = rotlBL; | ||
// JS uses 32-bit signed integers for bitwise operations which means we cannot | ||
// simple take carry out of low bit sum by shift, we need to use division. | ||
// Removing "export" has 5% perf penalty -_- | ||
function add(Ah, Al, Bh, Bl) { | ||
@@ -64,12 +54,16 @@ const l = (Al >>> 0) + (Bl >>> 0); | ||
const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0); | ||
exports.add3L = add3L; | ||
const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0; | ||
exports.add3H = add3H; | ||
const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0); | ||
exports.add4L = add4L; | ||
const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0; | ||
exports.add4H = add4H; | ||
const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0); | ||
exports.add5L = add5L; | ||
const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0; | ||
exports.add5H = add5H; | ||
// prettier-ignore | ||
const u64 = { | ||
fromBig, split, toBig: exports.toBig, | ||
shrSH, shrSL, | ||
rotrSH, rotrSL, rotrBH, rotrBL, | ||
rotr32H, rotr32L, | ||
rotlSH, rotlSL, rotlBH, rotlBL, | ||
add, add3L, add3H, add4L, add4H, add5H, add5L, | ||
}; | ||
exports.default = u64; |
@@ -1,3 +0,3 @@ | ||
import * as blake2 from './_blake2.js'; | ||
declare class BLAKE2b extends blake2.BLAKE2<BLAKE2b> { | ||
import { BLAKE2, BlakeOpts } from './_blake2.js'; | ||
declare class BLAKE2b extends BLAKE2<BLAKE2b> { | ||
private v0l; | ||
@@ -19,3 +19,3 @@ private v0h; | ||
private v7h; | ||
constructor(opts?: blake2.BlakeOpts); | ||
constructor(opts?: BlakeOpts); | ||
protected get(): [ | ||
@@ -49,7 +49,7 @@ number, | ||
export declare const blake2b: { | ||
(msg: import("./utils.js").Input, opts?: blake2.BlakeOpts | undefined): Uint8Array; | ||
(msg: import("./utils.js").Input, opts?: BlakeOpts | undefined): Uint8Array; | ||
outputLen: number; | ||
blockLen: number; | ||
create(opts: blake2.BlakeOpts): import("./utils.js").Hash<BLAKE2b>; | ||
create(opts: BlakeOpts): import("./utils.js").Hash<BLAKE2b>; | ||
}; | ||
export {}; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.blake2b = void 0; | ||
const blake2 = __importStar(require("./_blake2.js")); | ||
const u64 = __importStar(require("./_u64.js")); | ||
const _blake2_js_1 = require("./_blake2.js"); | ||
const _u64_js_1 = require("./_u64.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -43,13 +24,13 @@ // Same as SHA-512 but LE | ||
// v[a] = (v[a] + v[b] + x) | 0; | ||
let ll = u64.add3L(Al, Bl, Xl); | ||
Ah = u64.add3H(ll, Ah, Bh, Xh); | ||
let ll = _u64_js_1.default.add3L(Al, Bl, Xl); | ||
Ah = _u64_js_1.default.add3H(ll, Ah, Bh, Xh); | ||
Al = ll | 0; | ||
// v[d] = rotr(v[d] ^ v[a], 32) | ||
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al }); | ||
({ Dh, Dl } = { Dh: u64.rotr32H(Dh, Dl), Dl: u64.rotr32L(Dh, Dl) }); | ||
({ Dh, Dl } = { Dh: _u64_js_1.default.rotr32H(Dh, Dl), Dl: _u64_js_1.default.rotr32L(Dh, Dl) }); | ||
// v[c] = (v[c] + v[d]) | 0; | ||
({ h: Ch, l: Cl } = u64.add(Ch, Cl, Dh, Dl)); | ||
({ h: Ch, l: Cl } = _u64_js_1.default.add(Ch, Cl, Dh, Dl)); | ||
// v[b] = rotr(v[b] ^ v[c], 24) | ||
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl }); | ||
({ Bh, Bl } = { Bh: u64.rotrSH(Bh, Bl, 24), Bl: u64.rotrSL(Bh, Bl, 24) }); | ||
({ Bh, Bl } = { Bh: _u64_js_1.default.rotrSH(Bh, Bl, 24), Bl: _u64_js_1.default.rotrSL(Bh, Bl, 24) }); | ||
(BUF[2 * a] = Al), (BUF[2 * a + 1] = Ah); | ||
@@ -68,13 +49,13 @@ (BUF[2 * b] = Bl), (BUF[2 * b + 1] = Bh); | ||
// v[a] = (v[a] + v[b] + x) | 0; | ||
let ll = u64.add3L(Al, Bl, Xl); | ||
Ah = u64.add3H(ll, Ah, Bh, Xh); | ||
let ll = _u64_js_1.default.add3L(Al, Bl, Xl); | ||
Ah = _u64_js_1.default.add3H(ll, Ah, Bh, Xh); | ||
Al = ll | 0; | ||
// v[d] = rotr(v[d] ^ v[a], 16) | ||
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al }); | ||
({ Dh, Dl } = { Dh: u64.rotrSH(Dh, Dl, 16), Dl: u64.rotrSL(Dh, Dl, 16) }); | ||
({ Dh, Dl } = { Dh: _u64_js_1.default.rotrSH(Dh, Dl, 16), Dl: _u64_js_1.default.rotrSL(Dh, Dl, 16) }); | ||
// v[c] = (v[c] + v[d]) | 0; | ||
({ h: Ch, l: Cl } = u64.add(Ch, Cl, Dh, Dl)); | ||
({ h: Ch, l: Cl } = _u64_js_1.default.add(Ch, Cl, Dh, Dl)); | ||
// v[b] = rotr(v[b] ^ v[c], 63) | ||
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl }); | ||
({ Bh, Bl } = { Bh: u64.rotrBH(Bh, Bl, 63), Bl: u64.rotrBL(Bh, Bl, 63) }); | ||
({ Bh, Bl } = { Bh: _u64_js_1.default.rotrBH(Bh, Bl, 63), Bl: _u64_js_1.default.rotrBL(Bh, Bl, 63) }); | ||
(BUF[2 * a] = Al), (BUF[2 * a + 1] = Ah); | ||
@@ -85,3 +66,3 @@ (BUF[2 * b] = Bl), (BUF[2 * b + 1] = Bh); | ||
} | ||
class BLAKE2b extends blake2.BLAKE2 { | ||
class BLAKE2b extends _blake2_js_1.BLAKE2 { | ||
constructor(opts = {}) { | ||
@@ -156,3 +137,3 @@ super(128, opts.dkLen === undefined ? 64 : opts.dkLen, opts, 64, 16, 16); | ||
BUF.set(IV, 16); // Second half from IV. | ||
let { h, l } = u64.fromBig(BigInt(this.length)); | ||
let { h, l } = _u64_js_1.default.fromBig(BigInt(this.length)); | ||
BUF[24] = IV[8] ^ l; // Low word of the offset. | ||
@@ -166,3 +147,3 @@ BUF[25] = IV[9] ^ h; // High word. | ||
let j = 0; | ||
const s = blake2.SIGMA; | ||
const s = _blake2_js_1.SIGMA; | ||
for (let i = 0; i < 12; i++) { | ||
@@ -169,0 +150,0 @@ G1(0, 4, 8, 12, msg, offset + 2 * s[j++]); |
@@ -1,2 +0,2 @@ | ||
import * as blake2 from './_blake2.js'; | ||
import { BLAKE2, BlakeOpts } from './_blake2.js'; | ||
export declare const IV: Uint32Array; | ||
@@ -21,3 +21,3 @@ export declare function compress(s: Uint8Array, offset: number, msg: Uint32Array, rounds: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number, v15: number): { | ||
}; | ||
declare class BLAKE2s extends blake2.BLAKE2<BLAKE2s> { | ||
declare class BLAKE2s extends BLAKE2<BLAKE2s> { | ||
private v0; | ||
@@ -31,3 +31,3 @@ private v1; | ||
private v7; | ||
constructor(opts?: blake2.BlakeOpts); | ||
constructor(opts?: BlakeOpts); | ||
protected get(): [number, number, number, number, number, number, number, number]; | ||
@@ -44,7 +44,7 @@ protected set(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number): void; | ||
export declare const blake2s: { | ||
(msg: import("./utils.js").Input, opts?: blake2.BlakeOpts | undefined): Uint8Array; | ||
(msg: import("./utils.js").Input, opts?: BlakeOpts | undefined): Uint8Array; | ||
outputLen: number; | ||
blockLen: number; | ||
create(opts: blake2.BlakeOpts): import("./utils.js").Hash<BLAKE2s>; | ||
create(opts: BlakeOpts): import("./utils.js").Hash<BLAKE2s>; | ||
}; | ||
export {}; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.blake2s = exports.compress = exports.IV = void 0; | ||
const u64 = __importStar(require("./_u64.js")); | ||
const blake2 = __importStar(require("./_blake2.js")); | ||
const _blake2_js_1 = require("./_blake2.js"); | ||
const _u64_js_1 = require("./_u64.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -72,3 +53,3 @@ // Initial state: | ||
exports.compress = compress; | ||
class BLAKE2s extends blake2.BLAKE2 { | ||
class BLAKE2s extends _blake2_js_1.BLAKE2 { | ||
constructor(opts = {}) { | ||
@@ -120,5 +101,5 @@ super(64, opts.dkLen === undefined ? 32 : opts.dkLen, opts, 32, 8, 8); | ||
compress(msg, offset, isLast) { | ||
const { h, l } = u64.fromBig(BigInt(this.length)); | ||
const { h, l } = _u64_js_1.default.fromBig(BigInt(this.length)); | ||
// prettier-ignore | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(blake2.SIGMA, offset, msg, 10, this.v0, this.v1, this.v2, this.v3, this.v4, this.v5, this.v6, this.v7, exports.IV[0], exports.IV[1], exports.IV[2], exports.IV[3], l ^ exports.IV[4], h ^ exports.IV[5], isLast ? ~exports.IV[6] : exports.IV[6], exports.IV[7]); | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(_blake2_js_1.SIGMA, offset, msg, 10, this.v0, this.v1, this.v2, this.v3, this.v4, this.v5, this.v6, this.v7, exports.IV[0], exports.IV[1], exports.IV[2], exports.IV[3], l ^ exports.IV[4], h ^ exports.IV[5], isLast ? ~exports.IV[6] : exports.IV[6], exports.IV[7]); | ||
this.v0 ^= v0 ^ v8; | ||
@@ -125,0 +106,0 @@ this.v1 ^= v1 ^ v9; |
@@ -1,2 +0,2 @@ | ||
import * as blake2 from './_blake2.js'; | ||
import { BLAKE2 } from './_blake2.js'; | ||
import { Input, HashXOF } from './utils.js'; | ||
@@ -8,3 +8,3 @@ export declare type Blake3Opts = { | ||
}; | ||
declare class BLAKE3 extends blake2.BLAKE2<BLAKE3> implements HashXOF<BLAKE3> { | ||
declare class BLAKE3 extends BLAKE2<BLAKE3> implements HashXOF<BLAKE3> { | ||
private IV; | ||
@@ -11,0 +11,0 @@ private flags; |
107
blake3.js
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.blake3 = void 0; | ||
const u64 = __importStar(require("./_u64.js")); | ||
const blake2 = __importStar(require("./_blake2.js")); | ||
const blake2s = __importStar(require("./blake2s.js")); | ||
const _assert_js_1 = require("./_assert.js"); | ||
const _u64_js_1 = require("./_u64.js"); | ||
const _blake2_js_1 = require("./_blake2.js"); | ||
const blake2s_js_1 = require("./blake2s.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -54,3 +36,3 @@ // Flag bitset | ||
// which won't really benefit small inputs. | ||
class BLAKE3 extends blake2.BLAKE2 { | ||
class BLAKE3 extends _blake2_js_1.BLAKE2 { | ||
constructor(opts = {}, flags = 0) { | ||
@@ -68,3 +50,3 @@ super(64, opts.dkLen === undefined ? 32 : opts.dkLen, {}, Number.MAX_SAFE_INTEGER, 0, 0); | ||
this.outputLen = opts.dkLen === undefined ? 32 : opts.dkLen; | ||
(0, utils_js_1.assertNumber)(this.outputLen); | ||
_assert_js_1.default.number(this.outputLen); | ||
if (opts.key !== undefined && opts.context !== undefined) | ||
@@ -87,3 +69,3 @@ throw new Error('Blake3: only key or context can be specified at same time'); | ||
else { | ||
this.IV = blake2s.IV.slice(); | ||
this.IV = blake2s_js_1.IV.slice(); | ||
this.flags = flags; | ||
@@ -100,14 +82,14 @@ } | ||
b2Compress(counter, flags, buf, bufPos = 0) { | ||
const { state, pos } = this; | ||
const { h, l } = u64.fromBig(BigInt(counter), true); | ||
const { state: s, pos } = this; | ||
const { h, l } = _u64_js_1.default.fromBig(BigInt(counter), true); | ||
// prettier-ignore | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = blake2s.compress(SIGMA, bufPos, buf, 7, state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7], blake2s.IV[0], blake2s.IV[1], blake2s.IV[2], blake2s.IV[3], h, l, pos, flags); | ||
state[0] = v0 ^ v8; | ||
state[1] = v1 ^ v9; | ||
state[2] = v2 ^ v10; | ||
state[3] = v3 ^ v11; | ||
state[4] = v4 ^ v12; | ||
state[5] = v5 ^ v13; | ||
state[6] = v6 ^ v14; | ||
state[7] = v7 ^ v15; | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = (0, blake2s_js_1.compress)(SIGMA, bufPos, buf, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], blake2s_js_1.IV[0], blake2s_js_1.IV[1], blake2s_js_1.IV[2], blake2s_js_1.IV[3], h, l, pos, flags); | ||
s[0] = v0 ^ v8; | ||
s[1] = v1 ^ v9; | ||
s[2] = v2 ^ v10; | ||
s[3] = v3 ^ v11; | ||
s[4] = v4 ^ v12; | ||
s[5] = v5 ^ v13; | ||
s[6] = v6 ^ v14; | ||
s[7] = v7 ^ v15; | ||
} | ||
@@ -177,22 +159,22 @@ compress(buf, bufPos = 0, isLast = false) { | ||
b2CompressOut() { | ||
const { state, pos, flags, buffer32, bufferOut32 } = this; | ||
const { h, l } = u64.fromBig(BigInt(this.chunkOut++)); | ||
const { state: s, pos, flags, buffer32, bufferOut32: out32 } = this; | ||
const { h, l } = _u64_js_1.default.fromBig(BigInt(this.chunkOut++)); | ||
// prettier-ignore | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = blake2s.compress(SIGMA, 0, buffer32, 7, state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7], blake2s.IV[0], blake2s.IV[1], blake2s.IV[2], blake2s.IV[3], l, h, pos, flags); | ||
bufferOut32[0] = v0 ^ v8; | ||
bufferOut32[1] = v1 ^ v9; | ||
bufferOut32[2] = v2 ^ v10; | ||
bufferOut32[3] = v3 ^ v11; | ||
bufferOut32[4] = v4 ^ v12; | ||
bufferOut32[5] = v5 ^ v13; | ||
bufferOut32[6] = v6 ^ v14; | ||
bufferOut32[7] = v7 ^ v15; | ||
bufferOut32[8] = state[0] ^ v8; | ||
bufferOut32[9] = state[1] ^ v9; | ||
bufferOut32[10] = state[2] ^ v10; | ||
bufferOut32[11] = state[3] ^ v11; | ||
bufferOut32[12] = state[4] ^ v12; | ||
bufferOut32[13] = state[5] ^ v13; | ||
bufferOut32[14] = state[6] ^ v14; | ||
bufferOut32[15] = state[7] ^ v15; | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = (0, blake2s_js_1.compress)(SIGMA, 0, buffer32, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], blake2s_js_1.IV[0], blake2s_js_1.IV[1], blake2s_js_1.IV[2], blake2s_js_1.IV[3], l, h, pos, flags); | ||
out32[0] = v0 ^ v8; | ||
out32[1] = v1 ^ v9; | ||
out32[2] = v2 ^ v10; | ||
out32[3] = v3 ^ v11; | ||
out32[4] = v4 ^ v12; | ||
out32[5] = v5 ^ v13; | ||
out32[6] = v6 ^ v14; | ||
out32[7] = v7 ^ v15; | ||
out32[8] = s[0] ^ v8; | ||
out32[9] = s[1] ^ v9; | ||
out32[10] = s[2] ^ v10; | ||
out32[11] = s[3] ^ v11; | ||
out32[12] = s[4] ^ v12; | ||
out32[13] = s[5] ^ v13; | ||
out32[14] = s[6] ^ v14; | ||
out32[15] = s[7] ^ v15; | ||
this.posOut = 0; | ||
@@ -221,6 +203,4 @@ } | ||
writeInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array)) | ||
throw new Error('Blake3: Invalid output buffer'); | ||
_assert_js_1.default.exists(this, false); | ||
_assert_js_1.default.bytes(out); | ||
this.finish(); | ||
@@ -231,3 +211,3 @@ const { blockLen, bufferOut } = this; | ||
this.b2CompressOut(); | ||
const take = Math.min(this.blockLen - this.posOut, len - pos); | ||
const take = Math.min(blockLen - this.posOut, len - pos); | ||
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); | ||
@@ -241,12 +221,11 @@ this.posOut += take; | ||
if (!this.enableXOF) | ||
throw new Error('XOF impossible after digest call'); | ||
throw new Error('XOF is not possible after digest call'); | ||
return this.writeInto(out); | ||
} | ||
xof(bytes) { | ||
(0, utils_js_1.assertNumber)(bytes); | ||
_assert_js_1.default.number(bytes); | ||
return this.xofInto(new Uint8Array(bytes)); | ||
} | ||
digestInto(out) { | ||
if (out.length < this.outputLen) | ||
throw new Error('Blake3: Invalid output buffer'); | ||
_assert_js_1.default.output(out, this); | ||
if (this.finished) | ||
@@ -253,0 +232,0 @@ throw new Error('digest() was already called'); |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.crypto = void 0; | ||
const crypto_1 = __importDefault(require("crypto")); | ||
const nodeCrypto = require("crypto"); | ||
exports.crypto = { | ||
node: crypto_1.default, | ||
node: nodeCrypto, | ||
web: undefined, | ||
}; |
export declare function scrypt(password: string, salt: string): Uint8Array; | ||
export declare function pbkdf2(password: string, salt: string): Uint8Array; | ||
/** | ||
* Derives main seed. Takes a lot of time. | ||
* Prefer `eskdf` method instead. | ||
* Derives main seed. Takes a lot of time. Prefer `eskdf` method instead. | ||
*/ | ||
export declare function deriveMainSeed(username: string, password: string): Uint8Array; | ||
/** | ||
* Derives a child key. Prefer `eskdf` method instead. | ||
* @example deriveChildKey(seed, 'aes', 0) | ||
*/ | ||
export declare function deriveChildKey(seed: Uint8Array, protocol: string, accountId?: number | string, keyLength?: number): Uint8Array; | ||
declare type AccountID = number | string; | ||
declare type OptsLength = { | ||
keyLength: number; | ||
}; | ||
declare type OptsMod = { | ||
modulus: bigint; | ||
}; | ||
declare type KeyOpts = undefined | OptsLength | OptsMod; | ||
declare type ESKDF = Promise<Readonly<{ | ||
@@ -17,8 +19,9 @@ /** | ||
* other child key because of properties of underlying KDF. | ||
* | ||
* @param protocol - 3-15 character protocol name | ||
* @param accountId - numeric identifier of account | ||
* @param keyLength - (default: 32) key length | ||
* @param options - `keyLength: 64` or `modulus: 41920438n` | ||
* @example deriveChildKey('aes', 0) | ||
*/ | ||
deriveChildKey: (protocol: string, accountId: number | string) => Uint8Array; | ||
deriveChildKey: (protocol: string, accountId: AccountID, options?: KeyOpts) => Uint8Array; | ||
/** | ||
@@ -25,0 +28,0 @@ * Deletes the main seed from eskdf instance |
92
eskdf.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.eskdf = exports.deriveChildKey = exports.deriveMainSeed = exports.pbkdf2 = exports.scrypt = void 0; | ||
exports.eskdf = exports.deriveMainSeed = exports.pbkdf2 = exports.scrypt = void 0; | ||
const _assert_js_1 = require("./_assert.js"); | ||
const hkdf_js_1 = require("./hkdf.js"); | ||
@@ -12,6 +13,2 @@ const sha256_js_1 = require("./sha256.js"); | ||
const PBKDF2_FACTOR = 2 ** 17; | ||
const PROTOCOLS_ALLOWING_STR = ['ssh', 'tor', 'file']; | ||
function strHasLength(str, min, max) { | ||
return typeof str === 'string' && str.length >= min && str.length <= max; | ||
} | ||
// Scrypt KDF | ||
@@ -29,4 +26,4 @@ function scrypt(password, salt) { | ||
function xor32(a, b) { | ||
(0, utils_js_1.assertBytes)(a, 32); | ||
(0, utils_js_1.assertBytes)(b, 32); | ||
(0, _assert_js_1.bytes)(a, 32); | ||
(0, _assert_js_1.bytes)(b, 32); | ||
const arr = new Uint8Array(32); | ||
@@ -38,5 +35,18 @@ for (let i = 0; i < 32; i++) { | ||
} | ||
function bytesToNumber(bytes) { | ||
return BigInt('0x' + (0, utils_js_1.bytesToHex)(bytes)); | ||
} | ||
function numberToBytes(num, byteLength) { | ||
if (num < BigInt(0)) | ||
throw new Error('expected positive number'); | ||
const res = (0, utils_js_1.hexToBytes)(num.toString(16).padStart(byteLength * 2, '0')); | ||
if (res.length !== byteLength) | ||
throw new Error('invalid length of result key'); | ||
return res; | ||
} | ||
function strHasLength(str, min, max) { | ||
return typeof str === 'string' && str.length >= min && str.length <= max; | ||
} | ||
/** | ||
* Derives main seed. Takes a lot of time. | ||
* Prefer `eskdf` method instead. | ||
* Derives main seed. Takes a lot of time. Prefer `eskdf` method instead. | ||
*/ | ||
@@ -57,7 +67,5 @@ function deriveMainSeed(username, password) { | ||
/** | ||
* Derives a child key. Prefer `eskdf` method instead. | ||
* @example deriveChildKey(seed, 'aes', 0) | ||
* Converts protocol & accountId pair to HKDF salt & info params. | ||
*/ | ||
function deriveChildKey(seed, protocol, accountId = 0, keyLength = 32) { | ||
(0, utils_js_1.assertBytes)(seed, 32); | ||
function getSaltInfo(protocol, accountId = 0) { | ||
// Note that length here also repeats two lines below | ||
@@ -68,3 +76,4 @@ // We do an additional length check here to reduce the scope of DoS attacks | ||
} | ||
const allowsStr = PROTOCOLS_ALLOWING_STR.includes(protocol); | ||
// Allow string account ids for some protocols | ||
const allowsStr = /^password\d{0,3}|ssh|tor|file$/.test(protocol); | ||
let salt; // Extract salt. Default is undefined. | ||
@@ -89,6 +98,39 @@ if (typeof accountId === 'string') { | ||
const info = (0, utils_js_1.toBytes)(protocol); | ||
return (0, hkdf_js_1.hkdf)(sha256_js_1.sha256, seed, salt, info, keyLength); | ||
return { salt, info }; | ||
} | ||
exports.deriveChildKey = deriveChildKey; | ||
function countBytes(num) { | ||
if (typeof num !== 'bigint' || num <= BigInt(128)) | ||
throw new Error('invalid number'); | ||
return Math.ceil(num.toString(2).length / 8); | ||
} | ||
/** | ||
* Parses keyLength and modulus options to extract length of result key. | ||
* If modulus is used, adds 64 bits to it as per FIPS 186 B.4.1 to combat modulo bias. | ||
*/ | ||
function getKeyLength(options) { | ||
if (!options || typeof options !== 'object') | ||
return 32; | ||
const hasLen = 'keyLength' in options; | ||
const hasMod = 'modulus' in options; | ||
if (hasLen && hasMod) | ||
throw new Error('cannot combine keyLength and modulus options'); | ||
if (!hasLen && !hasMod) | ||
throw new Error('must have either keyLength or modulus option'); | ||
// FIPS 186 B.4.1 requires at least 64 more bits | ||
const l = hasMod ? countBytes(options.modulus) + 8 : options.keyLength; | ||
if (!(typeof l === 'number' && l >= 16 && l <= 8192)) | ||
throw new Error('invalid keyLength'); | ||
return l; | ||
} | ||
/** | ||
* Converts key to bigint and divides it by modulus. Big Endian. | ||
* Implements FIPS 186 B.4.1, which removes 0 and modulo bias from output. | ||
*/ | ||
function modReduceKey(key, modulus) { | ||
const num = bytesToNumber(key); | ||
const _1 = BigInt(1); | ||
const reduced = (num % (modulus - _1)) + _1; | ||
return numberToBytes(reduced, key.length - 8); // .reverse() for LE | ||
} | ||
/** | ||
* ESKDF | ||
@@ -106,6 +148,12 @@ * @param username - username, email, or identifier, min: 8 characters, should have enough entropy | ||
// we want to make `seed` non-accessible for any external function. | ||
let seed = await deriveMainSeed(username, password); | ||
function derive(protocol, accountId = 0) { | ||
(0, utils_js_1.assertBytes)(seed, 32); | ||
return deriveChildKey(seed, protocol, accountId); | ||
let seed = deriveMainSeed(username, password); | ||
function deriveCK(protocol, accountId = 0, options) { | ||
(0, _assert_js_1.bytes)(seed, 32); | ||
// Validates protocol & accountId | ||
const { salt, info } = getSaltInfo(protocol, accountId); | ||
// Validates options | ||
const keyLength = getKeyLength(options); | ||
const key = (0, hkdf_js_1.hkdf)(sha256_js_1.sha256, seed, salt, info, keyLength); | ||
// Modulus has already been validated | ||
return options && 'modulus' in options ? modReduceKey(key, options.modulus) : key; | ||
} | ||
@@ -118,8 +166,8 @@ function expire() { | ||
// prettier-ignore | ||
const fingerprint = Array.from(derive('fingerprint', 0)) | ||
const fingerprint = Array.from(deriveCK('fingerprint', 0)) | ||
.slice(0, 6) | ||
.map((char) => char.toString(16).padStart(2, '0').toUpperCase()) | ||
.join(':'); | ||
return Object.freeze({ deriveChildKey: derive, expire, fingerprint }); | ||
return Object.freeze({ deriveChildKey: deriveCK, expire, fingerprint }); | ||
} | ||
exports.eskdf = eskdf; |
@@ -1,2 +0,3 @@ | ||
import { assertNumber, Hash, toBytes, u32 } from './utils.js'; | ||
import assert from './_assert.js'; | ||
import { Hash, toBytes, u32 } from './utils.js'; | ||
// prettier-ignore | ||
@@ -27,5 +28,5 @@ export const SIGMA = new Uint8Array([ | ||
this.destroyed = false; | ||
assertNumber(blockLen); | ||
assertNumber(outputLen); | ||
assertNumber(keyLen); | ||
assert.number(blockLen); | ||
assert.number(outputLen); | ||
assert.number(keyLen); | ||
if (outputLen < 0 || outputLen > keyLen) | ||
@@ -42,4 +43,3 @@ throw new Error('Blake2: outputLen bigger than keyLen'); | ||
update(data) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
assert.exists(this); | ||
// Main difference with other hashes: there is flag for last block, | ||
@@ -49,5 +49,3 @@ // so we cannot process current block before we know that there | ||
// to do zero-copy processing | ||
const { finished, blockLen, buffer, buffer32 } = this; | ||
if (finished) | ||
throw new Error('digest() was already called'); | ||
const { blockLen, buffer, buffer32 } = this; | ||
data = toBytes(data); | ||
@@ -80,9 +78,5 @@ const len = data.length; | ||
digestInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array) || out.length < this.outputLen) | ||
throw new Error('_Blake2: Invalid output buffer'); | ||
const { finished, pos, buffer32 } = this; | ||
if (finished) | ||
throw new Error('digest() was already called'); | ||
assert.exists(this); | ||
assert.output(out, this); | ||
const { pos, buffer32 } = this; | ||
this.finished = true; | ||
@@ -89,0 +83,0 @@ // Padding |
@@ -0,1 +1,2 @@ | ||
import assert from './_assert.js'; | ||
import { Hash, createView, toBytes } from './utils.js'; | ||
@@ -31,7 +32,4 @@ // Polyfill for Safari 14 | ||
update(data) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
const { view, buffer, blockLen, finished } = this; | ||
if (finished) | ||
throw new Error('digest() was already called'); | ||
assert.exists(this); | ||
const { view, buffer, blockLen } = this; | ||
data = toBytes(data); | ||
@@ -61,8 +59,4 @@ const len = data.length; | ||
digestInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array) || out.length < this.outputLen) | ||
throw new Error('_Sha2: Invalid output buffer'); | ||
if (this.finished) | ||
throw new Error('digest() was already called'); | ||
assert.exists(this); | ||
assert.output(out, this); | ||
this.finished = true; | ||
@@ -85,5 +79,5 @@ // Padding | ||
buffer[i] = 0; | ||
// NOTE: sha512 requires length to be 128bit integer, but length in JS will overflow before that | ||
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that | ||
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen. | ||
// So we just write lowest 64bit of that value. | ||
// So we just write lowest 64 bits of that value. | ||
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE); | ||
@@ -90,0 +84,0 @@ this.process(view, 0); |
const U32_MASK64 = BigInt(2 ** 32 - 1); | ||
const _32n = BigInt(32); | ||
// We are not using BigUint64Array, because they are extremely slow as per 2022 | ||
export function fromBig(n, le = false) { | ||
@@ -19,21 +20,22 @@ if (le) | ||
// for Shift in [0, 32) | ||
export const shrSH = (h, l, s) => h >>> s; | ||
export const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); | ||
const shrSH = (h, l, s) => h >>> s; | ||
const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); | ||
// Right rotate for Shift in [1, 32) | ||
export const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s)); | ||
export const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); | ||
const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s)); | ||
const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); | ||
// Right rotate for Shift in (32, 64), NOTE: 32 is special case. | ||
export const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32)); | ||
export const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s)); | ||
const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32)); | ||
const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s)); | ||
// Right rotate for shift===32 (just swaps l&h) | ||
export const rotr32H = (h, l) => l; | ||
export const rotr32L = (h, l) => h; | ||
const rotr32H = (h, l) => l; | ||
const rotr32L = (h, l) => h; | ||
// Left rotate for Shift in [1, 32) | ||
export const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s)); | ||
export const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s)); | ||
const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s)); | ||
const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s)); | ||
// Left rotate for Shift in (32, 64), NOTE: 32 is special case. | ||
export const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s)); | ||
export const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s)); | ||
const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s)); | ||
const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s)); | ||
// JS uses 32-bit signed integers for bitwise operations which means we cannot | ||
// simple take carry out of low bit sum by shift, we need to use division. | ||
// Removing "export" has 5% perf penalty -_- | ||
export function add(Ah, Al, Bh, Bl) { | ||
@@ -44,7 +46,17 @@ const l = (Al >>> 0) + (Bl >>> 0); | ||
// Addition with more than 2 elements | ||
export const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0); | ||
export const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0; | ||
export const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0); | ||
export const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0; | ||
export const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0); | ||
export const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0; | ||
const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0); | ||
const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0; | ||
const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0); | ||
const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0; | ||
const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0); | ||
const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0; | ||
// prettier-ignore | ||
const u64 = { | ||
fromBig, split, toBig, | ||
shrSH, shrSL, | ||
rotrSH, rotrSL, rotrBH, rotrBL, | ||
rotr32H, rotr32L, | ||
rotlSH, rotlSL, rotlBH, rotlBL, | ||
add, add3L, add3H, add4L, add4H, add5H, add5L, | ||
}; | ||
export default u64; |
@@ -1,3 +0,3 @@ | ||
import * as blake2 from './_blake2.js'; | ||
import * as u64 from './_u64.js'; | ||
import { BLAKE2, SIGMA } from './_blake2.js'; | ||
import u64 from './_u64.js'; | ||
import { toBytes, u32, wrapConstructorWithOpts } from './utils.js'; | ||
@@ -61,3 +61,3 @@ // Same as SHA-512 but LE | ||
} | ||
class BLAKE2b extends blake2.BLAKE2 { | ||
class BLAKE2b extends BLAKE2 { | ||
constructor(opts = {}) { | ||
@@ -141,3 +141,3 @@ super(128, opts.dkLen === undefined ? 64 : opts.dkLen, opts, 64, 16, 16); | ||
let j = 0; | ||
const s = blake2.SIGMA; | ||
const s = SIGMA; | ||
for (let i = 0; i < 12; i++) { | ||
@@ -144,0 +144,0 @@ G1(0, 4, 8, 12, msg, offset + 2 * s[j++]); |
@@ -1,3 +0,3 @@ | ||
import * as u64 from './_u64.js'; | ||
import * as blake2 from './_blake2.js'; | ||
import { BLAKE2, SIGMA } from './_blake2.js'; | ||
import u64 from './_u64.js'; | ||
import { rotr, toBytes, wrapConstructorWithOpts, u32 } from './utils.js'; | ||
@@ -49,3 +49,3 @@ // Initial state: | ||
} | ||
class BLAKE2s extends blake2.BLAKE2 { | ||
class BLAKE2s extends BLAKE2 { | ||
constructor(opts = {}) { | ||
@@ -99,3 +99,3 @@ super(64, opts.dkLen === undefined ? 32 : opts.dkLen, opts, 32, 8, 8); | ||
// prettier-ignore | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(blake2.SIGMA, offset, msg, 10, this.v0, this.v1, this.v2, this.v3, this.v4, this.v5, this.v6, this.v7, IV[0], IV[1], IV[2], IV[3], l ^ IV[4], h ^ IV[5], isLast ? ~IV[6] : IV[6], IV[7]); | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(SIGMA, offset, msg, 10, this.v0, this.v1, this.v2, this.v3, this.v4, this.v5, this.v6, this.v7, IV[0], IV[1], IV[2], IV[3], l ^ IV[4], h ^ IV[5], isLast ? ~IV[6] : IV[6], IV[7]); | ||
this.v0 ^= v0 ^ v8; | ||
@@ -102,0 +102,0 @@ this.v1 ^= v1 ^ v9; |
@@ -1,5 +0,6 @@ | ||
import * as u64 from './_u64.js'; | ||
import * as blake2 from './_blake2.js'; | ||
import * as blake2s from './blake2s.js'; | ||
import { u8, u32, toBytes, wrapConstructorWithOpts, assertNumber, } from './utils.js'; | ||
import assert from './_assert.js'; | ||
import u64 from './_u64.js'; | ||
import { BLAKE2 } from './_blake2.js'; | ||
import { compress, IV } from './blake2s.js'; | ||
import { u8, u32, toBytes, wrapConstructorWithOpts } from './utils.js'; | ||
// Flag bitset | ||
@@ -32,3 +33,3 @@ var Flags; | ||
// which won't really benefit small inputs. | ||
class BLAKE3 extends blake2.BLAKE2 { | ||
class BLAKE3 extends BLAKE2 { | ||
constructor(opts = {}, flags = 0) { | ||
@@ -46,3 +47,3 @@ super(64, opts.dkLen === undefined ? 32 : opts.dkLen, {}, Number.MAX_SAFE_INTEGER, 0, 0); | ||
this.outputLen = opts.dkLen === undefined ? 32 : opts.dkLen; | ||
assertNumber(this.outputLen); | ||
assert.number(this.outputLen); | ||
if (opts.key !== undefined && opts.context !== undefined) | ||
@@ -65,3 +66,3 @@ throw new Error('Blake3: only key or context can be specified at same time'); | ||
else { | ||
this.IV = blake2s.IV.slice(); | ||
this.IV = IV.slice(); | ||
this.flags = flags; | ||
@@ -78,14 +79,14 @@ } | ||
b2Compress(counter, flags, buf, bufPos = 0) { | ||
const { state, pos } = this; | ||
const { state: s, pos } = this; | ||
const { h, l } = u64.fromBig(BigInt(counter), true); | ||
// prettier-ignore | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = blake2s.compress(SIGMA, bufPos, buf, 7, state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7], blake2s.IV[0], blake2s.IV[1], blake2s.IV[2], blake2s.IV[3], h, l, pos, flags); | ||
state[0] = v0 ^ v8; | ||
state[1] = v1 ^ v9; | ||
state[2] = v2 ^ v10; | ||
state[3] = v3 ^ v11; | ||
state[4] = v4 ^ v12; | ||
state[5] = v5 ^ v13; | ||
state[6] = v6 ^ v14; | ||
state[7] = v7 ^ v15; | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(SIGMA, bufPos, buf, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], IV[0], IV[1], IV[2], IV[3], h, l, pos, flags); | ||
s[0] = v0 ^ v8; | ||
s[1] = v1 ^ v9; | ||
s[2] = v2 ^ v10; | ||
s[3] = v3 ^ v11; | ||
s[4] = v4 ^ v12; | ||
s[5] = v5 ^ v13; | ||
s[6] = v6 ^ v14; | ||
s[7] = v7 ^ v15; | ||
} | ||
@@ -155,22 +156,22 @@ compress(buf, bufPos = 0, isLast = false) { | ||
b2CompressOut() { | ||
const { state, pos, flags, buffer32, bufferOut32 } = this; | ||
const { state: s, pos, flags, buffer32, bufferOut32: out32 } = this; | ||
const { h, l } = u64.fromBig(BigInt(this.chunkOut++)); | ||
// prettier-ignore | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = blake2s.compress(SIGMA, 0, buffer32, 7, state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7], blake2s.IV[0], blake2s.IV[1], blake2s.IV[2], blake2s.IV[3], l, h, pos, flags); | ||
bufferOut32[0] = v0 ^ v8; | ||
bufferOut32[1] = v1 ^ v9; | ||
bufferOut32[2] = v2 ^ v10; | ||
bufferOut32[3] = v3 ^ v11; | ||
bufferOut32[4] = v4 ^ v12; | ||
bufferOut32[5] = v5 ^ v13; | ||
bufferOut32[6] = v6 ^ v14; | ||
bufferOut32[7] = v7 ^ v15; | ||
bufferOut32[8] = state[0] ^ v8; | ||
bufferOut32[9] = state[1] ^ v9; | ||
bufferOut32[10] = state[2] ^ v10; | ||
bufferOut32[11] = state[3] ^ v11; | ||
bufferOut32[12] = state[4] ^ v12; | ||
bufferOut32[13] = state[5] ^ v13; | ||
bufferOut32[14] = state[6] ^ v14; | ||
bufferOut32[15] = state[7] ^ v15; | ||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(SIGMA, 0, buffer32, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], IV[0], IV[1], IV[2], IV[3], l, h, pos, flags); | ||
out32[0] = v0 ^ v8; | ||
out32[1] = v1 ^ v9; | ||
out32[2] = v2 ^ v10; | ||
out32[3] = v3 ^ v11; | ||
out32[4] = v4 ^ v12; | ||
out32[5] = v5 ^ v13; | ||
out32[6] = v6 ^ v14; | ||
out32[7] = v7 ^ v15; | ||
out32[8] = s[0] ^ v8; | ||
out32[9] = s[1] ^ v9; | ||
out32[10] = s[2] ^ v10; | ||
out32[11] = s[3] ^ v11; | ||
out32[12] = s[4] ^ v12; | ||
out32[13] = s[5] ^ v13; | ||
out32[14] = s[6] ^ v14; | ||
out32[15] = s[7] ^ v15; | ||
this.posOut = 0; | ||
@@ -199,6 +200,4 @@ } | ||
writeInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array)) | ||
throw new Error('Blake3: Invalid output buffer'); | ||
assert.exists(this, false); | ||
assert.bytes(out); | ||
this.finish(); | ||
@@ -209,3 +208,3 @@ const { blockLen, bufferOut } = this; | ||
this.b2CompressOut(); | ||
const take = Math.min(this.blockLen - this.posOut, len - pos); | ||
const take = Math.min(blockLen - this.posOut, len - pos); | ||
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); | ||
@@ -219,12 +218,11 @@ this.posOut += take; | ||
if (!this.enableXOF) | ||
throw new Error('XOF impossible after digest call'); | ||
throw new Error('XOF is not possible after digest call'); | ||
return this.writeInto(out); | ||
} | ||
xof(bytes) { | ||
assertNumber(bytes); | ||
assert.number(bytes); | ||
return this.xofInto(new Uint8Array(bytes)); | ||
} | ||
digestInto(out) { | ||
if (out.length < this.outputLen) | ||
throw new Error('Blake3: Invalid output buffer'); | ||
assert.output(out, this); | ||
if (this.finished) | ||
@@ -231,0 +229,0 @@ throw new Error('digest() was already called'); |
@@ -1,2 +0,2 @@ | ||
import nodeCrypto from 'crypto'; | ||
import * as nodeCrypto from 'crypto'; | ||
export const crypto = { | ||
@@ -3,0 +3,0 @@ node: nodeCrypto, |
@@ -0,1 +1,2 @@ | ||
import { bytes as assertBytes } from './_assert.js'; | ||
import { hkdf } from './hkdf.js'; | ||
@@ -5,10 +6,6 @@ import { sha256 } from './sha256.js'; | ||
import { scrypt as _scrypt } from './scrypt.js'; | ||
import { assertBytes, createView, toBytes } from './utils.js'; | ||
import { bytesToHex, createView, hexToBytes, toBytes } from './utils.js'; | ||
// A tiny KDF for various applications like AES key-gen | ||
const SCRYPT_FACTOR = 2 ** 19; | ||
const PBKDF2_FACTOR = 2 ** 17; | ||
const PROTOCOLS_ALLOWING_STR = ['ssh', 'tor', 'file']; | ||
function strHasLength(str, min, max) { | ||
return typeof str === 'string' && str.length >= min && str.length <= max; | ||
} | ||
// Scrypt KDF | ||
@@ -32,5 +29,18 @@ export function scrypt(password, salt) { | ||
} | ||
function bytesToNumber(bytes) { | ||
return BigInt('0x' + bytesToHex(bytes)); | ||
} | ||
function numberToBytes(num, byteLength) { | ||
if (num < BigInt(0)) | ||
throw new Error('expected positive number'); | ||
const res = hexToBytes(num.toString(16).padStart(byteLength * 2, '0')); | ||
if (res.length !== byteLength) | ||
throw new Error('invalid length of result key'); | ||
return res; | ||
} | ||
function strHasLength(str, min, max) { | ||
return typeof str === 'string' && str.length >= min && str.length <= max; | ||
} | ||
/** | ||
* Derives main seed. Takes a lot of time. | ||
* Prefer `eskdf` method instead. | ||
* Derives main seed. Takes a lot of time. Prefer `eskdf` method instead. | ||
*/ | ||
@@ -50,7 +60,5 @@ export function deriveMainSeed(username, password) { | ||
/** | ||
* Derives a child key. Prefer `eskdf` method instead. | ||
* @example deriveChildKey(seed, 'aes', 0) | ||
* Converts protocol & accountId pair to HKDF salt & info params. | ||
*/ | ||
export function deriveChildKey(seed, protocol, accountId = 0, keyLength = 32) { | ||
assertBytes(seed, 32); | ||
function getSaltInfo(protocol, accountId = 0) { | ||
// Note that length here also repeats two lines below | ||
@@ -61,3 +69,4 @@ // We do an additional length check here to reduce the scope of DoS attacks | ||
} | ||
const allowsStr = PROTOCOLS_ALLOWING_STR.includes(protocol); | ||
// Allow string account ids for some protocols | ||
const allowsStr = /^password\d{0,3}|ssh|tor|file$/.test(protocol); | ||
let salt; // Extract salt. Default is undefined. | ||
@@ -82,5 +91,39 @@ if (typeof accountId === 'string') { | ||
const info = toBytes(protocol); | ||
return hkdf(sha256, seed, salt, info, keyLength); | ||
return { salt, info }; | ||
} | ||
function countBytes(num) { | ||
if (typeof num !== 'bigint' || num <= BigInt(128)) | ||
throw new Error('invalid number'); | ||
return Math.ceil(num.toString(2).length / 8); | ||
} | ||
/** | ||
* Parses keyLength and modulus options to extract length of result key. | ||
* If modulus is used, adds 64 bits to it as per FIPS 186 B.4.1 to combat modulo bias. | ||
*/ | ||
function getKeyLength(options) { | ||
if (!options || typeof options !== 'object') | ||
return 32; | ||
const hasLen = 'keyLength' in options; | ||
const hasMod = 'modulus' in options; | ||
if (hasLen && hasMod) | ||
throw new Error('cannot combine keyLength and modulus options'); | ||
if (!hasLen && !hasMod) | ||
throw new Error('must have either keyLength or modulus option'); | ||
// FIPS 186 B.4.1 requires at least 64 more bits | ||
const l = hasMod ? countBytes(options.modulus) + 8 : options.keyLength; | ||
if (!(typeof l === 'number' && l >= 16 && l <= 8192)) | ||
throw new Error('invalid keyLength'); | ||
return l; | ||
} | ||
/** | ||
* Converts key to bigint and divides it by modulus. Big Endian. | ||
* Implements FIPS 186 B.4.1, which removes 0 and modulo bias from output. | ||
*/ | ||
function modReduceKey(key, modulus) { | ||
const num = bytesToNumber(key); | ||
const _1 = BigInt(1); | ||
const reduced = (num % (modulus - _1)) + _1; | ||
return numberToBytes(reduced, key.length - 8); // .reverse() for LE | ||
} | ||
/** | ||
* ESKDF | ||
@@ -98,6 +141,12 @@ * @param username - username, email, or identifier, min: 8 characters, should have enough entropy | ||
// we want to make `seed` non-accessible for any external function. | ||
let seed = await deriveMainSeed(username, password); | ||
function derive(protocol, accountId = 0) { | ||
let seed = deriveMainSeed(username, password); | ||
function deriveCK(protocol, accountId = 0, options) { | ||
assertBytes(seed, 32); | ||
return deriveChildKey(seed, protocol, accountId); | ||
// Validates protocol & accountId | ||
const { salt, info } = getSaltInfo(protocol, accountId); | ||
// Validates options | ||
const keyLength = getKeyLength(options); | ||
const key = hkdf(sha256, seed, salt, info, keyLength); | ||
// Modulus has already been validated | ||
return options && 'modulus' in options ? modReduceKey(key, options.modulus) : key; | ||
} | ||
@@ -110,7 +159,7 @@ function expire() { | ||
// prettier-ignore | ||
const fingerprint = Array.from(derive('fingerprint', 0)) | ||
const fingerprint = Array.from(deriveCK('fingerprint', 0)) | ||
.slice(0, 6) | ||
.map((char) => char.toString(16).padStart(2, '0').toUpperCase()) | ||
.join(':'); | ||
return Object.freeze({ deriveChildKey: derive, expire, fingerprint }); | ||
return Object.freeze({ deriveChildKey: deriveCK, expire, fingerprint }); | ||
} |
@@ -1,2 +0,3 @@ | ||
import { assertHash, assertNumber, toBytes } from './utils.js'; | ||
import assert from './_assert.js'; | ||
import { toBytes } from './utils.js'; | ||
import { hmac } from './hmac.js'; | ||
@@ -14,3 +15,3 @@ // HKDF (RFC 5869) | ||
export function extract(hash, ikm, salt) { | ||
assertHash(hash); | ||
assert.hash(hash); | ||
// NOTE: some libraries treat zero-length array as 'not provided'; | ||
@@ -33,4 +34,4 @@ // we don't, since we have undefined as 'not provided' | ||
export function expand(hash, prk, info, length = 32) { | ||
assertHash(hash); | ||
assertNumber(length); | ||
assert.hash(hash); | ||
assert.number(length); | ||
if (length > 255 * hash.outputLen) | ||
@@ -37,0 +38,0 @@ throw new Error('Length should be <= 255*HashLen'); |
@@ -1,2 +0,3 @@ | ||
import { assertHash, Hash, toBytes } from './utils.js'; | ||
import assert from './_assert.js'; | ||
import { Hash, toBytes } from './utils.js'; | ||
// HMAC (RFC 2104) | ||
@@ -8,3 +9,3 @@ class HMAC extends Hash { | ||
this.destroyed = false; | ||
assertHash(hash); | ||
assert.hash(hash); | ||
const key = toBytes(_key); | ||
@@ -31,4 +32,3 @@ this.iHash = hash.create(); | ||
update(buf) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
assert.exists(this); | ||
this.iHash.update(buf); | ||
@@ -38,8 +38,4 @@ return this; | ||
digestInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array) || out.length !== this.outputLen) | ||
throw new Error('HMAC: Invalid output buffer'); | ||
if (this.finished) | ||
throw new Error('digest() was already called'); | ||
assert.exists(this); | ||
assert.bytes(out, this.outputLen); | ||
this.finished = true; | ||
@@ -46,0 +42,0 @@ this.iHash.digestInto(out); |
@@ -0,12 +1,12 @@ | ||
import assert from './_assert.js'; | ||
import { hmac } from './hmac.js'; | ||
// prettier-ignore | ||
import { createView, toBytes, assertNumber, assertHash, checkOpts, asyncLoop } from './utils.js'; | ||
import { createView, toBytes, checkOpts, asyncLoop } from './utils.js'; | ||
// Common prologue and epilogue for sync/async functions | ||
function pbkdf2Init(hash, _password, _salt, _opts) { | ||
assertHash(hash); | ||
assert.hash(hash); | ||
const opts = checkOpts({ dkLen: 32, asyncTick: 10 }, _opts); | ||
const { c, dkLen, asyncTick } = opts; | ||
assertNumber(c); | ||
assertNumber(dkLen); | ||
assertNumber(asyncTick); | ||
assert.number(c); | ||
assert.number(dkLen); | ||
assert.number(asyncTick); | ||
if (c < 1) | ||
@@ -13,0 +13,0 @@ throw new Error('PBKDF2: iterations (c) should be >= 1'); |
@@ -0,4 +1,5 @@ | ||
import assert from './_assert.js'; | ||
import { sha256 } from './sha256.js'; | ||
import { pbkdf2 } from './pbkdf2.js'; | ||
import { assertNumber, asyncLoop, checkOpts, u32 } from './utils.js'; | ||
import { asyncLoop, checkOpts, u32 } from './utils.js'; | ||
// RFC 7914 Scrypt KDF | ||
@@ -99,8 +100,8 @@ // Left rotate for uint32 | ||
const { N, r, p, dkLen, asyncTick, maxmem, onProgress } = opts; | ||
assertNumber(N); | ||
assertNumber(r); | ||
assertNumber(p); | ||
assertNumber(dkLen); | ||
assertNumber(asyncTick); | ||
assertNumber(maxmem); | ||
assert.number(N); | ||
assert.number(r); | ||
assert.number(p); | ||
assert.number(dkLen); | ||
assert.number(asyncTick); | ||
assert.number(maxmem); | ||
if (onProgress !== undefined && typeof onProgress !== 'function') | ||
@@ -107,0 +108,0 @@ throw new Error('progressCb should be function'); |
@@ -1,2 +0,3 @@ | ||
import { toBytes, wrapConstructorWithOpts, assertNumber, u32, } from './utils.js'; | ||
import { number as assertNumber } from './_assert'; | ||
import { toBytes, wrapConstructorWithOpts, u32 } from './utils.js'; | ||
import { Keccak } from './sha3.js'; | ||
@@ -20,2 +21,5 @@ // cSHAKE && KMAC (NIST SP800-185) | ||
} | ||
function chooseLen(opts, outputLen) { | ||
return opts.dkLen === undefined ? outputLen : opts.dkLen; | ||
} | ||
const toBytesOptional = (buf) => (buf !== undefined ? toBytes(buf) : new Uint8Array([])); | ||
@@ -43,3 +47,3 @@ // NOTE: second modulo is necessary since we don't need to add padding if current element takes whole block | ||
} | ||
const gencShake = (suffix, blockLen, outputLen) => wrapConstructorWithOpts((opts = {}) => cshakePers(new Keccak(blockLen, suffix, opts.dkLen !== undefined ? opts.dkLen : outputLen, true), opts)); | ||
const gencShake = (suffix, blockLen, outputLen) => wrapConstructorWithOpts((opts = {}) => cshakePers(new Keccak(blockLen, suffix, chooseLen(opts, outputLen), true), opts)); | ||
export const cshake128 = gencShake(0x1f, 168, 128 / 8); | ||
@@ -81,3 +85,3 @@ export const cshake256 = gencShake(0x1f, 136, 256 / 8); | ||
const kmac = (key, message, opts) => kmac.create(key, opts).update(message).digest(); | ||
kmac.create = (key, opts = {}) => new KMAC(blockLen, opts.dkLen !== undefined ? opts.dkLen : outputLen, xof, key, opts); | ||
kmac.create = (key, opts = {}) => new KMAC(blockLen, chooseLen(opts, outputLen), xof, key, opts); | ||
return kmac; | ||
@@ -123,3 +127,3 @@ } | ||
}; | ||
tuple.create = (opts = {}) => new TupleHash(blockLen, opts.dkLen !== undefined ? opts.dkLen : outputLen, xof, opts); | ||
tuple.create = (opts = {}) => new TupleHash(blockLen, chooseLen(opts, outputLen), xof, opts); | ||
return tuple; | ||
@@ -195,3 +199,3 @@ } | ||
const parallel = (message, opts) => parallel.create(opts).update(message).digest(); | ||
parallel.create = (opts = {}) => new ParallelHash(blockLen, opts.dkLen !== undefined ? opts.dkLen : outputLen, () => leaf.create({ dkLen: 2 * outputLen }), xof, opts); | ||
parallel.create = (opts = {}) => new ParallelHash(blockLen, chooseLen(opts, outputLen), () => leaf.create({ dkLen: 2 * outputLen }), xof, opts); | ||
return parallel; | ||
@@ -286,5 +290,5 @@ } | ||
// Default to 32 bytes, so it can be used without opts | ||
export const k12 = wrapConstructorWithOpts((opts = {}) => new KangarooTwelve(168, 32, opts.dkLen !== undefined ? opts.dkLen : 32, 12, opts)); | ||
export const k12 = wrapConstructorWithOpts((opts = {}) => new KangarooTwelve(168, 32, chooseLen(opts, 32), 12, opts)); | ||
// MarsupilamiFourteen | ||
export const m14 = wrapConstructorWithOpts((opts = {}) => new KangarooTwelve(136, 64, opts.dkLen !== undefined ? opts.dkLen : 64, 14, opts)); | ||
export const m14 = wrapConstructorWithOpts((opts = {}) => new KangarooTwelve(136, 64, chooseLen(opts, 64), 14, opts)); | ||
// https://keccak.team/files/CSF-0.1.pdf | ||
@@ -291,0 +295,0 @@ // + https://github.com/XKCP/XKCP/tree/master/lib/high/Keccak/PRG |
@@ -1,3 +0,4 @@ | ||
import * as u64 from './_u64.js'; | ||
import { Hash, u32, toBytes, wrapConstructor, wrapConstructorWithOpts, assertNumber, } from './utils.js'; | ||
import assert from './_assert.js'; | ||
import u64 from './_u64.js'; | ||
import { Hash, u32, toBytes, wrapConstructor, wrapConstructorWithOpts, } from './utils.js'; | ||
// Various per round constants calculations | ||
@@ -90,3 +91,3 @@ const [SHA3_PI, SHA3_ROTL, _SHA3_IOTA] = [[], [], []]; | ||
// Can be passed from user as dkLen | ||
assertNumber(outputLen); | ||
assert.number(outputLen); | ||
// 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes | ||
@@ -104,6 +105,3 @@ if (0 >= this.blockLen || this.blockLen >= 200) | ||
update(data) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (this.finished) | ||
throw new Error('digest() was already called'); | ||
assert.exists(this); | ||
const { blockLen, state } = this; | ||
@@ -134,12 +132,12 @@ data = toBytes(data); | ||
writeInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array)) | ||
throw new Error('Keccak: invalid output buffer'); | ||
assert.exists(this, false); | ||
assert.bytes(out); | ||
this.finish(); | ||
const bufferOut = this.state; | ||
const { blockLen } = this; | ||
for (let pos = 0, len = out.length; pos < len;) { | ||
if (this.posOut >= this.blockLen) | ||
if (this.posOut >= blockLen) | ||
this.keccak(); | ||
const take = Math.min(this.blockLen - this.posOut, len - pos); | ||
out.set(this.state.subarray(this.posOut, this.posOut + take), pos); | ||
const take = Math.min(blockLen - this.posOut, len - pos); | ||
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); | ||
this.posOut += take; | ||
@@ -157,11 +155,9 @@ pos += take; | ||
xof(bytes) { | ||
assertNumber(bytes); | ||
assert.number(bytes); | ||
return this.xofInto(new Uint8Array(bytes)); | ||
} | ||
digestInto(out) { | ||
if (out.length < this.outputLen) | ||
throw new Error('Keccak: invalid output buffer'); | ||
assert.output(out, this); | ||
if (this.finished) | ||
throw new Error('digest() was already called'); | ||
this.finish(); | ||
this.writeInto(out); | ||
@@ -211,4 +207,4 @@ this.destroy(); | ||
export const keccak_512 = gen(0x01, 72, 512 / 8); | ||
const genShake = (suffix, blockLen, outputLen) => wrapConstructorWithOpts((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen !== undefined ? opts.dkLen : outputLen, true)); | ||
const genShake = (suffix, blockLen, outputLen) => wrapConstructorWithOpts((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true)); | ||
export const shake128 = genShake(0x1f, 168, 128 / 8); | ||
export const shake256 = genShake(0x1f, 136, 256 / 8); |
import { SHA2 } from './_sha2.js'; | ||
import * as u64 from './_u64.js'; | ||
import u64 from './_u64.js'; | ||
import { wrapConstructor } from './utils.js'; | ||
@@ -4,0 +4,0 @@ // Round contants (first 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409): |
@@ -13,3 +13,3 @@ /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ | ||
export const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44; | ||
// There is almost no big endian hardware, but js typed arrays uses platform specific endianess. | ||
// There is almost no big endian hardware, but js typed arrays uses platform specific endianness. | ||
// So, just to be sure not to corrupt anything. | ||
@@ -24,2 +24,4 @@ if (!isLE) | ||
// pre-caching improves the speed 6x | ||
if (!(uint8a instanceof Uint8Array)) | ||
throw new Error('Uint8Array expected'); | ||
let hex = ''; | ||
@@ -45,3 +47,3 @@ for (let i = 0; i < uint8a.length; i++) { | ||
const byte = Number.parseInt(hexByte, 16); | ||
if (Number.isNaN(byte)) | ||
if (Number.isNaN(byte) || byte < 0) | ||
throw new Error('Invalid byte sequence'); | ||
@@ -52,17 +54,5 @@ array[i] = byte; | ||
} | ||
// Currently avoid insertion of polyfills with packers (browserify/webpack/etc) | ||
// But setTimeout is pretty slow, maybe worth to investigate howto do minimal polyfill here | ||
export const nextTick = (() => { | ||
const nodeRequire = typeof module !== 'undefined' && | ||
typeof module.require === 'function' && | ||
module.require.bind(module); | ||
try { | ||
if (nodeRequire) { | ||
const { setImmediate } = nodeRequire('timers'); | ||
return () => new Promise((resolve) => setImmediate(resolve)); | ||
} | ||
} | ||
catch (e) { } | ||
return () => new Promise((resolve) => setTimeout(resolve, 0)); | ||
})(); | ||
// There is no setImmediate in browser and setTimeout is slow. However, call to async function will return Promise | ||
// which will be fullfiled only on next scheduler queue processing step and this is exactly what we need. | ||
export const nextTick = async () => { }; | ||
// Returns control to thread each 'tick' ms to avoid blocking | ||
@@ -112,23 +102,2 @@ export async function asyncLoop(iters, tick, cb) { | ||
} | ||
export function assertNumber(n) { | ||
if (!Number.isSafeInteger(n) || n < 0) | ||
throw new Error(`Wrong positive integer: ${n}`); | ||
} | ||
export function assertBool(b) { | ||
if (typeof b !== 'boolean') { | ||
throw new Error(`Expected boolean, not ${b}`); | ||
} | ||
} | ||
export function assertBytes(bytes, ...lengths) { | ||
if (bytes instanceof Uint8Array && (!lengths.length || lengths.includes(bytes.length))) { | ||
return; | ||
} | ||
throw new TypeError(`Expected ${lengths} bytes, not ${typeof bytes} with length=${bytes.length}`); | ||
} | ||
export function assertHash(hash) { | ||
if (typeof hash !== 'function' || typeof hash.create !== 'function') | ||
throw new Error('Hash should be wrapped by utils.wrapConstructor'); | ||
assertNumber(hash.outputLen); | ||
assertNumber(hash.blockLen); | ||
} | ||
// For runtime check if class implements interface | ||
@@ -143,7 +112,7 @@ export class Hash { | ||
const isPlainObject = (obj) => Object.prototype.toString.call(obj) === '[object Object]' && obj.constructor === Object; | ||
export function checkOpts(def, _opts) { | ||
if (_opts !== undefined && (typeof _opts !== 'object' || !isPlainObject(_opts))) | ||
export function checkOpts(defaults, opts) { | ||
if (opts !== undefined && (typeof opts !== 'object' || !isPlainObject(opts))) | ||
throw new TypeError('Options should be object or undefined'); | ||
const opts = Object.assign(def, _opts); | ||
return opts; | ||
const merged = Object.assign(defaults, opts); | ||
return merged; | ||
} | ||
@@ -150,0 +119,0 @@ export function wrapConstructor(hashConstructor) { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.hkdf = exports.expand = exports.extract = void 0; | ||
const _assert_js_1 = require("./_assert.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -17,3 +18,3 @@ const hmac_js_1 = require("./hmac.js"); | ||
function extract(hash, ikm, salt) { | ||
(0, utils_js_1.assertHash)(hash); | ||
_assert_js_1.default.hash(hash); | ||
// NOTE: some libraries treat zero-length array as 'not provided'; | ||
@@ -37,4 +38,4 @@ // we don't, since we have undefined as 'not provided' | ||
function expand(hash, prk, info, length = 32) { | ||
(0, utils_js_1.assertHash)(hash); | ||
(0, utils_js_1.assertNumber)(length); | ||
_assert_js_1.default.hash(hash); | ||
_assert_js_1.default.number(length); | ||
if (length > 255 * hash.outputLen) | ||
@@ -41,0 +42,0 @@ throw new Error('Length should be <= 255*HashLen'); |
14
hmac.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.hmac = void 0; | ||
const _assert_js_1 = require("./_assert.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -11,3 +12,3 @@ // HMAC (RFC 2104) | ||
this.destroyed = false; | ||
(0, utils_js_1.assertHash)(hash); | ||
_assert_js_1.default.hash(hash); | ||
const key = (0, utils_js_1.toBytes)(_key); | ||
@@ -34,4 +35,3 @@ this.iHash = hash.create(); | ||
update(buf) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
_assert_js_1.default.exists(this); | ||
this.iHash.update(buf); | ||
@@ -41,8 +41,4 @@ return this; | ||
digestInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array) || out.length !== this.outputLen) | ||
throw new Error('HMAC: Invalid output buffer'); | ||
if (this.finished) | ||
throw new Error('digest() was already called'); | ||
_assert_js_1.default.exists(this); | ||
_assert_js_1.default.bytes(out, this.outputLen); | ||
this.finished = true; | ||
@@ -49,0 +45,0 @@ this.iHash.digestInto(out); |
{ | ||
"name": "@noble/hashes", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Audited & minimal 0-dependency JS implementation of SHA2, SHA3, RIPEMD, BLAKE2/3, HMAC, HKDF, PBKDF2, Scrypt", | ||
@@ -13,3 +13,4 @@ "files": [ | ||
"scripts": { | ||
"bench": "node test/benchmark/index.js", | ||
"bench": "node test/benchmark/index.js noble", | ||
"bench:all": "node test/benchmark/index.js", | ||
"bench:install": "cd test/benchmark && npm install && cd ../../", | ||
@@ -36,8 +37,8 @@ "build": "tsc -d && tsc -p tsconfig.esm.json", | ||
"devDependencies": { | ||
"@rollup/plugin-node-resolve": "13.0.6", | ||
"@rollup/plugin-node-resolve": "13.3.0", | ||
"micro-bmark": "^0.1.3", | ||
"micro-should": "^0.2.0", | ||
"prettier": "2.4.1", | ||
"rollup": "~2.60.1", | ||
"typescript": "4.5.4" | ||
"prettier": "2.6.2", | ||
"rollup": "2.75.5", | ||
"typescript": "4.7.3" | ||
}, | ||
@@ -152,3 +153,9 @@ "exports": { | ||
"noble" | ||
], | ||
"funding": [ | ||
{ | ||
"type": "individual", | ||
"url": "https://paulmillr.com/funding/" | ||
} | ||
] | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.pbkdf2Async = exports.pbkdf2 = void 0; | ||
const _assert_js_1 = require("./_assert.js"); | ||
const hmac_js_1 = require("./hmac.js"); | ||
// prettier-ignore | ||
const utils_js_1 = require("./utils.js"); | ||
// Common prologue and epilogue for sync/async functions | ||
function pbkdf2Init(hash, _password, _salt, _opts) { | ||
(0, utils_js_1.assertHash)(hash); | ||
_assert_js_1.default.hash(hash); | ||
const opts = (0, utils_js_1.checkOpts)({ dkLen: 32, asyncTick: 10 }, _opts); | ||
const { c, dkLen, asyncTick } = opts; | ||
(0, utils_js_1.assertNumber)(c); | ||
(0, utils_js_1.assertNumber)(dkLen); | ||
(0, utils_js_1.assertNumber)(asyncTick); | ||
_assert_js_1.default.number(c); | ||
_assert_js_1.default.number(dkLen); | ||
_assert_js_1.default.number(asyncTick); | ||
if (c < 1) | ||
@@ -16,0 +16,0 @@ throw new Error('PBKDF2: iterations (c) should be >= 1'); |
@@ -14,3 +14,3 @@ # noble-hashes ![Node CI](https://github.com/paulmillr/noble-hashes/workflows/Node%20CI/badge.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) | ||
- 🦘 SHA3 supports Keccak, TupleHash, KangarooTwelve and MarsupilamiFourteen | ||
- 🪶 Just 2.8k lines / 14KB gzipped. SHA256-only is 240 lines / 3KB gzipped | ||
- 🪶 Just 2.3k lines / 14KB gzipped. SHA256-only is 240 lines / 3KB gzipped | ||
@@ -391,3 +391,3 @@ The library's initial development was funded by [Ethereum Foundation](https://ethereum.org/). | ||
1. The library has been audited on Jan 5, 2022 by an independent security firm cure53: [PDF](https://cure53.de/pentest-report_hashing-libs.pdf). No vulnerabilities have been found. The audit has been funded by Ethereum Foundation with help of [Nomic Labs](https://nomiclabs.io). Modules `blake3` and `sha3-addons` have not been audited. | ||
1. The library has been audited on Jan 5, 2022 by an independent security firm cure53: [PDF](https://cure53.de/pentest-report_hashing-libs.pdf). No vulnerabilities have been found. The audit has been funded by Ethereum Foundation with help of [Nomic Labs](https://nomiclabs.io). Modules `blake3` and `sha3-addons` have not been audited. See [changes since audit](https://github.com/paulmillr/noble-hashes/compare/1.0.0..main). | ||
2. The library has been fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz). You can run the fuzzer by yourself to check it. | ||
@@ -414,14 +414,14 @@ 3. [Timing attack](https://en.wikipedia.org/wiki/Timing_attack) considerations: _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library can't have constant-timeness_. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time. | ||
SHA512 32B x 467,945 ops/sec @ 2μs/op | ||
SHA3-256, keccak256, shake256 32B x 184,026 ops/sec @ 5μs/op | ||
Kangaroo12 32B x 312,891 ops/sec @ 3μs/op | ||
Marsupilami14 32B x 278,164 ops/sec @ 3μs/op | ||
BLAKE2b 32B x 297,353 ops/sec @ 3μs/op | ||
BLAKE2s 32B x 507,614 ops/sec @ 1μs/op | ||
BLAKE3 32B x 591,016 ops/sec @ 1μs/op | ||
SHA3-256, keccak256, shake256 32B x 192,049 ops/sec @ 5μs/op | ||
Kangaroo12 32B x 318,066 ops/sec @ 3μs/op | ||
Marsupilami14 32B x 283,929 ops/sec @ 3μs/op | ||
BLAKE2b 32B x 352,112 ops/sec @ 2μs/op | ||
BLAKE2s 32B x 511,770 ops/sec @ 1μs/op | ||
BLAKE3 32B x 582,072 ops/sec @ 1μs/op | ||
RIPEMD160 32B x 1,230,012 ops/sec @ 813ns/op | ||
HMAC-SHA256 32B x 346,860 ops/sec @ 2μs/op | ||
HKDF-SHA256 32B x 153,397 ops/sec @ 6μs/op | ||
HMAC-SHA256 32B x 238,663 ops/sec @ 4μs/op | ||
HKDF-SHA256 32B x 108,377 ops/sec @ 9μs/op | ||
PBKDF2-HMAC-SHA256 262144 x 3 ops/sec @ 326ms/op | ||
PBKDF2-HMAC-SHA512 262144 x 1 ops/sec @ 970ms/op | ||
Scrypt r: 8, p: 1, n: 262144 x 1 ops/sec @ 636ms/op | ||
Scrypt r: 8, p: 1, n: 262144 x 1 ops/sec @ 616ms/op | ||
``` | ||
@@ -428,0 +428,0 @@ |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.scryptAsync = exports.scrypt = void 0; | ||
const _assert_js_1 = require("./_assert.js"); | ||
const sha256_js_1 = require("./sha256.js"); | ||
@@ -102,8 +103,8 @@ const pbkdf2_js_1 = require("./pbkdf2.js"); | ||
const { N, r, p, dkLen, asyncTick, maxmem, onProgress } = opts; | ||
(0, utils_js_1.assertNumber)(N); | ||
(0, utils_js_1.assertNumber)(r); | ||
(0, utils_js_1.assertNumber)(p); | ||
(0, utils_js_1.assertNumber)(dkLen); | ||
(0, utils_js_1.assertNumber)(asyncTick); | ||
(0, utils_js_1.assertNumber)(maxmem); | ||
_assert_js_1.default.number(N); | ||
_assert_js_1.default.number(r); | ||
_assert_js_1.default.number(p); | ||
_assert_js_1.default.number(dkLen); | ||
_assert_js_1.default.number(asyncTick); | ||
_assert_js_1.default.number(maxmem); | ||
if (onProgress !== undefined && typeof onProgress !== 'function') | ||
@@ -110,0 +111,0 @@ throw new Error('progressCb should be function'); |
@@ -26,15 +26,15 @@ import { Input, Hash, HashXOF } from './utils.js'; | ||
export declare const kmac128: { | ||
(key: Input, message: Input, opts?: cShakeOpts | undefined): Uint8Array; | ||
(key: Input, message: Input, opts?: cShakeOpts): Uint8Array; | ||
create(key: Input, opts?: cShakeOpts): KMAC; | ||
}; | ||
export declare const kmac256: { | ||
(key: Input, message: Input, opts?: cShakeOpts | undefined): Uint8Array; | ||
(key: Input, message: Input, opts?: cShakeOpts): Uint8Array; | ||
create(key: Input, opts?: cShakeOpts): KMAC; | ||
}; | ||
export declare const kmac128xof: { | ||
(key: Input, message: Input, opts?: cShakeOpts | undefined): Uint8Array; | ||
(key: Input, message: Input, opts?: cShakeOpts): Uint8Array; | ||
create(key: Input, opts?: cShakeOpts): KMAC; | ||
}; | ||
export declare const kmac256xof: { | ||
(key: Input, message: Input, opts?: cShakeOpts | undefined): Uint8Array; | ||
(key: Input, message: Input, opts?: cShakeOpts): Uint8Array; | ||
create(key: Input, opts?: cShakeOpts): KMAC; | ||
@@ -49,15 +49,15 @@ }; | ||
export declare const tuplehash128: { | ||
(messages: Input[], opts?: cShakeOpts | undefined): Uint8Array; | ||
(messages: Input[], opts?: cShakeOpts): Uint8Array; | ||
create(opts?: cShakeOpts): TupleHash; | ||
}; | ||
export declare const tuplehash256: { | ||
(messages: Input[], opts?: cShakeOpts | undefined): Uint8Array; | ||
(messages: Input[], opts?: cShakeOpts): Uint8Array; | ||
create(opts?: cShakeOpts): TupleHash; | ||
}; | ||
export declare const tuplehash128xof: { | ||
(messages: Input[], opts?: cShakeOpts | undefined): Uint8Array; | ||
(messages: Input[], opts?: cShakeOpts): Uint8Array; | ||
create(opts?: cShakeOpts): TupleHash; | ||
}; | ||
export declare const tuplehash256xof: { | ||
(messages: Input[], opts?: cShakeOpts | undefined): Uint8Array; | ||
(messages: Input[], opts?: cShakeOpts): Uint8Array; | ||
create(opts?: cShakeOpts): TupleHash; | ||
@@ -81,15 +81,15 @@ }; | ||
export declare const parallelhash128: { | ||
(message: Input, opts?: ParallelOpts | undefined): Uint8Array; | ||
(message: Input, opts?: ParallelOpts): Uint8Array; | ||
create(opts?: ParallelOpts): ParallelHash; | ||
}; | ||
export declare const parallelhash256: { | ||
(message: Input, opts?: ParallelOpts | undefined): Uint8Array; | ||
(message: Input, opts?: ParallelOpts): Uint8Array; | ||
create(opts?: ParallelOpts): ParallelHash; | ||
}; | ||
export declare const parallelhash128xof: { | ||
(message: Input, opts?: ParallelOpts | undefined): Uint8Array; | ||
(message: Input, opts?: ParallelOpts): Uint8Array; | ||
create(opts?: ParallelOpts): ParallelHash; | ||
}; | ||
export declare const parallelhash256xof: { | ||
(message: Input, opts?: ParallelOpts | undefined): Uint8Array; | ||
(message: Input, opts?: ParallelOpts): Uint8Array; | ||
create(opts?: ParallelOpts): ParallelHash; | ||
@@ -96,0 +96,0 @@ }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.keccakprg = exports.m14 = exports.k12 = exports.parallelhash256xof = exports.parallelhash128xof = exports.parallelhash256 = exports.parallelhash128 = exports.tuplehash256xof = exports.tuplehash128xof = exports.tuplehash256 = exports.tuplehash128 = exports.kmac256xof = exports.kmac128xof = exports.kmac256 = exports.kmac128 = exports.cshake256 = exports.cshake128 = void 0; | ||
const _assert_1 = require("./_assert"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -23,2 +24,5 @@ const sha3_js_1 = require("./sha3.js"); | ||
} | ||
function chooseLen(opts, outputLen) { | ||
return opts.dkLen === undefined ? outputLen : opts.dkLen; | ||
} | ||
const toBytesOptional = (buf) => (buf !== undefined ? (0, utils_js_1.toBytes)(buf) : new Uint8Array([])); | ||
@@ -46,3 +50,3 @@ // NOTE: second modulo is necessary since we don't need to add padding if current element takes whole block | ||
} | ||
const gencShake = (suffix, blockLen, outputLen) => (0, utils_js_1.wrapConstructorWithOpts)((opts = {}) => cshakePers(new sha3_js_1.Keccak(blockLen, suffix, opts.dkLen !== undefined ? opts.dkLen : outputLen, true), opts)); | ||
const gencShake = (suffix, blockLen, outputLen) => (0, utils_js_1.wrapConstructorWithOpts)((opts = {}) => cshakePers(new sha3_js_1.Keccak(blockLen, suffix, chooseLen(opts, outputLen), true), opts)); | ||
exports.cshake128 = gencShake(0x1f, 168, 128 / 8); | ||
@@ -84,3 +88,3 @@ exports.cshake256 = gencShake(0x1f, 136, 256 / 8); | ||
const kmac = (key, message, opts) => kmac.create(key, opts).update(message).digest(); | ||
kmac.create = (key, opts = {}) => new KMAC(blockLen, opts.dkLen !== undefined ? opts.dkLen : outputLen, xof, key, opts); | ||
kmac.create = (key, opts = {}) => new KMAC(blockLen, chooseLen(opts, outputLen), xof, key, opts); | ||
return kmac; | ||
@@ -126,3 +130,3 @@ } | ||
}; | ||
tuple.create = (opts = {}) => new TupleHash(blockLen, opts.dkLen !== undefined ? opts.dkLen : outputLen, xof, opts); | ||
tuple.create = (opts = {}) => new TupleHash(blockLen, chooseLen(opts, outputLen), xof, opts); | ||
return tuple; | ||
@@ -143,3 +147,3 @@ } | ||
B || (B = 8); | ||
(0, utils_js_1.assertNumber)(B); | ||
(0, _assert_1.number)(B); | ||
this.chunkLen = B; | ||
@@ -199,3 +203,3 @@ super.update(leftEncode(B)); | ||
const parallel = (message, opts) => parallel.create(opts).update(message).digest(); | ||
parallel.create = (opts = {}) => new ParallelHash(blockLen, opts.dkLen !== undefined ? opts.dkLen : outputLen, () => leaf.create({ dkLen: 2 * outputLen }), xof, opts); | ||
parallel.create = (opts = {}) => new ParallelHash(blockLen, chooseLen(opts, outputLen), () => leaf.create({ dkLen: 2 * outputLen }), xof, opts); | ||
return parallel; | ||
@@ -290,5 +294,5 @@ } | ||
// Default to 32 bytes, so it can be used without opts | ||
exports.k12 = (0, utils_js_1.wrapConstructorWithOpts)((opts = {}) => new KangarooTwelve(168, 32, opts.dkLen !== undefined ? opts.dkLen : 32, 12, opts)); | ||
exports.k12 = (0, utils_js_1.wrapConstructorWithOpts)((opts = {}) => new KangarooTwelve(168, 32, chooseLen(opts, 32), 12, opts)); | ||
// MarsupilamiFourteen | ||
exports.m14 = (0, utils_js_1.wrapConstructorWithOpts)((opts = {}) => new KangarooTwelve(136, 64, opts.dkLen !== undefined ? opts.dkLen : 64, 14, opts)); | ||
exports.m14 = (0, utils_js_1.wrapConstructorWithOpts)((opts = {}) => new KangarooTwelve(136, 64, chooseLen(opts, 64), 14, opts)); | ||
// https://keccak.team/files/CSF-0.1.pdf | ||
@@ -298,3 +302,3 @@ // + https://github.com/XKCP/XKCP/tree/master/lib/high/Keccak/PRG | ||
constructor(capacity) { | ||
(0, utils_js_1.assertNumber)(capacity); | ||
(0, _assert_1.number)(capacity); | ||
// Rho should be full bytes | ||
@@ -301,0 +305,0 @@ if (capacity < 0 || capacity > 1600 - 10 || (1600 - capacity - 2) % 8) |
57
sha3.js
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.shake256 = exports.shake128 = exports.keccak_512 = exports.keccak_384 = exports.keccak_256 = exports.keccak_224 = exports.sha3_512 = exports.sha3_384 = exports.sha3_256 = exports.sha3_224 = exports.Keccak = exports.keccakP = void 0; | ||
const u64 = __importStar(require("./_u64.js")); | ||
const _assert_js_1 = require("./_assert.js"); | ||
const _u64_js_1 = require("./_u64.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -48,6 +30,6 @@ // Various per round constants calculations | ||
} | ||
const [SHA3_IOTA_H, SHA3_IOTA_L] = u64.split(_SHA3_IOTA, true); | ||
const [SHA3_IOTA_H, SHA3_IOTA_L] = _u64_js_1.default.split(_SHA3_IOTA, true); | ||
// Left rotation (without 0, 32, 64) | ||
const rotlH = (h, l, s) => s > 32 ? u64.rotlBH(h, l, s) : u64.rotlSH(h, l, s); | ||
const rotlL = (h, l, s) => s > 32 ? u64.rotlBL(h, l, s) : u64.rotlSL(h, l, s); | ||
const rotlH = (h, l, s) => s > 32 ? _u64_js_1.default.rotlBH(h, l, s) : _u64_js_1.default.rotlSH(h, l, s); | ||
const rotlL = (h, l, s) => s > 32 ? _u64_js_1.default.rotlBL(h, l, s) : _u64_js_1.default.rotlSL(h, l, s); | ||
// Same as keccakf1600, but allows to skip some rounds | ||
@@ -114,3 +96,3 @@ function keccakP(s, rounds = 24) { | ||
// Can be passed from user as dkLen | ||
(0, utils_js_1.assertNumber)(outputLen); | ||
_assert_js_1.default.number(outputLen); | ||
// 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes | ||
@@ -128,6 +110,3 @@ if (0 >= this.blockLen || this.blockLen >= 200) | ||
update(data) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (this.finished) | ||
throw new Error('digest() was already called'); | ||
_assert_js_1.default.exists(this); | ||
const { blockLen, state } = this; | ||
@@ -158,12 +137,12 @@ data = (0, utils_js_1.toBytes)(data); | ||
writeInto(out) { | ||
if (this.destroyed) | ||
throw new Error('instance is destroyed'); | ||
if (!(out instanceof Uint8Array)) | ||
throw new Error('Keccak: invalid output buffer'); | ||
_assert_js_1.default.exists(this, false); | ||
_assert_js_1.default.bytes(out); | ||
this.finish(); | ||
const bufferOut = this.state; | ||
const { blockLen } = this; | ||
for (let pos = 0, len = out.length; pos < len;) { | ||
if (this.posOut >= this.blockLen) | ||
if (this.posOut >= blockLen) | ||
this.keccak(); | ||
const take = Math.min(this.blockLen - this.posOut, len - pos); | ||
out.set(this.state.subarray(this.posOut, this.posOut + take), pos); | ||
const take = Math.min(blockLen - this.posOut, len - pos); | ||
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); | ||
this.posOut += take; | ||
@@ -181,11 +160,9 @@ pos += take; | ||
xof(bytes) { | ||
(0, utils_js_1.assertNumber)(bytes); | ||
_assert_js_1.default.number(bytes); | ||
return this.xofInto(new Uint8Array(bytes)); | ||
} | ||
digestInto(out) { | ||
if (out.length < this.outputLen) | ||
throw new Error('Keccak: invalid output buffer'); | ||
_assert_js_1.default.output(out, this); | ||
if (this.finished) | ||
throw new Error('digest() was already called'); | ||
this.finish(); | ||
this.writeInto(out); | ||
@@ -236,4 +213,4 @@ this.destroy(); | ||
exports.keccak_512 = gen(0x01, 72, 512 / 8); | ||
const genShake = (suffix, blockLen, outputLen) => (0, utils_js_1.wrapConstructorWithOpts)((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen !== undefined ? opts.dkLen : outputLen, true)); | ||
const genShake = (suffix, blockLen, outputLen) => (0, utils_js_1.wrapConstructorWithOpts)((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true)); | ||
exports.shake128 = genShake(0x1f, 168, 128 / 8); | ||
exports.shake256 = genShake(0x1f, 136, 256 / 8); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.sha384 = exports.sha512_256 = exports.sha512 = exports.SHA512 = void 0; | ||
const _sha2_js_1 = require("./_sha2.js"); | ||
const u64 = __importStar(require("./_u64.js")); | ||
const _u64_js_1 = require("./_u64.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
// Round contants (first 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409): | ||
// prettier-ignore | ||
const [SHA512_Kh, SHA512_Kl] = u64.split([ | ||
const [SHA512_Kh, SHA512_Kl] = _u64_js_1.default.split([ | ||
'0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc', | ||
@@ -111,12 +92,12 @@ '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118', | ||
const W15l = SHA512_W_L[i - 15] | 0; | ||
const s0h = u64.rotrSH(W15h, W15l, 1) ^ u64.rotrSH(W15h, W15l, 8) ^ u64.shrSH(W15h, W15l, 7); | ||
const s0l = u64.rotrSL(W15h, W15l, 1) ^ u64.rotrSL(W15h, W15l, 8) ^ u64.shrSL(W15h, W15l, 7); | ||
const s0h = _u64_js_1.default.rotrSH(W15h, W15l, 1) ^ _u64_js_1.default.rotrSH(W15h, W15l, 8) ^ _u64_js_1.default.shrSH(W15h, W15l, 7); | ||
const s0l = _u64_js_1.default.rotrSL(W15h, W15l, 1) ^ _u64_js_1.default.rotrSL(W15h, W15l, 8) ^ _u64_js_1.default.shrSL(W15h, W15l, 7); | ||
// s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6) | ||
const W2h = SHA512_W_H[i - 2] | 0; | ||
const W2l = SHA512_W_L[i - 2] | 0; | ||
const s1h = u64.rotrSH(W2h, W2l, 19) ^ u64.rotrBH(W2h, W2l, 61) ^ u64.shrSH(W2h, W2l, 6); | ||
const s1l = u64.rotrSL(W2h, W2l, 19) ^ u64.rotrBL(W2h, W2l, 61) ^ u64.shrSL(W2h, W2l, 6); | ||
const s1h = _u64_js_1.default.rotrSH(W2h, W2l, 19) ^ _u64_js_1.default.rotrBH(W2h, W2l, 61) ^ _u64_js_1.default.shrSH(W2h, W2l, 6); | ||
const s1l = _u64_js_1.default.rotrSL(W2h, W2l, 19) ^ _u64_js_1.default.rotrBL(W2h, W2l, 61) ^ _u64_js_1.default.shrSL(W2h, W2l, 6); | ||
// SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16]; | ||
const SUMl = u64.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]); | ||
const SUMh = u64.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]); | ||
const SUMl = _u64_js_1.default.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]); | ||
const SUMh = _u64_js_1.default.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]); | ||
SHA512_W_H[i] = SUMh | 0; | ||
@@ -129,4 +110,4 @@ SHA512_W_L[i] = SUMl | 0; | ||
// S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41) | ||
const sigma1h = u64.rotrSH(Eh, El, 14) ^ u64.rotrSH(Eh, El, 18) ^ u64.rotrBH(Eh, El, 41); | ||
const sigma1l = u64.rotrSL(Eh, El, 14) ^ u64.rotrSL(Eh, El, 18) ^ u64.rotrBL(Eh, El, 41); | ||
const sigma1h = _u64_js_1.default.rotrSH(Eh, El, 14) ^ _u64_js_1.default.rotrSH(Eh, El, 18) ^ _u64_js_1.default.rotrBH(Eh, El, 41); | ||
const sigma1l = _u64_js_1.default.rotrSL(Eh, El, 14) ^ _u64_js_1.default.rotrSL(Eh, El, 18) ^ _u64_js_1.default.rotrBL(Eh, El, 41); | ||
//const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0; | ||
@@ -137,8 +118,8 @@ const CHIh = (Eh & Fh) ^ (~Eh & Gh); | ||
// prettier-ignore | ||
const T1ll = u64.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]); | ||
const T1h = u64.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]); | ||
const T1ll = _u64_js_1.default.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]); | ||
const T1h = _u64_js_1.default.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]); | ||
const T1l = T1ll | 0; | ||
// S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39) | ||
const sigma0h = u64.rotrSH(Ah, Al, 28) ^ u64.rotrBH(Ah, Al, 34) ^ u64.rotrBH(Ah, Al, 39); | ||
const sigma0l = u64.rotrSL(Ah, Al, 28) ^ u64.rotrBL(Ah, Al, 34) ^ u64.rotrBL(Ah, Al, 39); | ||
const sigma0h = _u64_js_1.default.rotrSH(Ah, Al, 28) ^ _u64_js_1.default.rotrBH(Ah, Al, 34) ^ _u64_js_1.default.rotrBH(Ah, Al, 39); | ||
const sigma0l = _u64_js_1.default.rotrSL(Ah, Al, 28) ^ _u64_js_1.default.rotrBL(Ah, Al, 34) ^ _u64_js_1.default.rotrBL(Ah, Al, 39); | ||
const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch); | ||
@@ -152,3 +133,3 @@ const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl); | ||
Fl = El | 0; | ||
({ h: Eh, l: El } = u64.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0)); | ||
({ h: Eh, l: El } = _u64_js_1.default.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0)); | ||
Dh = Ch | 0; | ||
@@ -160,15 +141,15 @@ Dl = Cl | 0; | ||
Bl = Al | 0; | ||
const All = u64.add3L(T1l, sigma0l, MAJl); | ||
Ah = u64.add3H(All, T1h, sigma0h, MAJh); | ||
const All = _u64_js_1.default.add3L(T1l, sigma0l, MAJl); | ||
Ah = _u64_js_1.default.add3H(All, T1h, sigma0h, MAJh); | ||
Al = All | 0; | ||
} | ||
// Add the compressed chunk to the current hash value | ||
({ h: Ah, l: Al } = u64.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0)); | ||
({ h: Bh, l: Bl } = u64.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0)); | ||
({ h: Ch, l: Cl } = u64.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0)); | ||
({ h: Dh, l: Dl } = u64.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0)); | ||
({ h: Eh, l: El } = u64.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0)); | ||
({ h: Fh, l: Fl } = u64.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0)); | ||
({ h: Gh, l: Gl } = u64.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0)); | ||
({ h: Hh, l: Hl } = u64.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0)); | ||
({ h: Ah, l: Al } = _u64_js_1.default.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0)); | ||
({ h: Bh, l: Bl } = _u64_js_1.default.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0)); | ||
({ h: Ch, l: Cl } = _u64_js_1.default.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0)); | ||
({ h: Dh, l: Dl } = _u64_js_1.default.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0)); | ||
({ h: Eh, l: El } = _u64_js_1.default.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0)); | ||
({ h: Fh, l: Fl } = _u64_js_1.default.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0)); | ||
({ h: Gh, l: Gl } = _u64_js_1.default.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0)); | ||
({ h: Hh, l: Hl } = _u64_js_1.default.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0)); | ||
this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl); | ||
@@ -175,0 +156,0 @@ } |
@@ -16,3 +16,3 @@ /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ | ||
export declare function hexToBytes(hex: string): Uint8Array; | ||
export declare const nextTick: () => Promise<unknown>; | ||
export declare const nextTick: () => Promise<void>; | ||
export declare function asyncLoop(iters: number, tick: number, cb: (i: number) => void): Promise<void>; | ||
@@ -27,6 +27,2 @@ export declare function utf8ToBytes(str: string): Uint8Array; | ||
export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array; | ||
export declare function assertNumber(n: number): void; | ||
export declare function assertBool(b: boolean): void; | ||
export declare function assertBytes(bytes: Uint8Array, ...lengths: number[]): void; | ||
export declare function assertHash(hash: CHash): void; | ||
export declare abstract class Hash<T extends Hash<T>> { | ||
@@ -52,3 +48,3 @@ abstract blockLen: number; | ||
declare type EmptyObj = {}; | ||
export declare function checkOpts<T1 extends EmptyObj, T2 extends EmptyObj>(def: T1, _opts?: T2): T1 & T2; | ||
export declare function checkOpts<T1 extends EmptyObj, T2 extends EmptyObj>(defaults: T1, opts?: T2): T1 & T2; | ||
export declare type CHash = ReturnType<typeof wrapConstructor>; | ||
@@ -62,3 +58,3 @@ export declare function wrapConstructor<T extends Hash<T>>(hashConstructor: () => Hash<T>): { | ||
export declare function wrapConstructorWithOpts<H extends Hash<H>, T extends Object>(hashCons: (opts?: T) => Hash<H>): { | ||
(msg: Input, opts?: T | undefined): Uint8Array; | ||
(msg: Input, opts?: T): Uint8Array; | ||
outputLen: number; | ||
@@ -65,0 +61,0 @@ blockLen: number; |
60
utils.js
"use strict"; | ||
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.randomBytes = exports.wrapConstructorWithOpts = exports.wrapConstructor = exports.checkOpts = exports.Hash = exports.assertHash = exports.assertBytes = exports.assertBool = exports.assertNumber = exports.concatBytes = exports.toBytes = exports.utf8ToBytes = exports.asyncLoop = exports.nextTick = exports.hexToBytes = exports.bytesToHex = exports.isLE = exports.rotr = exports.createView = exports.u32 = exports.u8 = void 0; | ||
exports.randomBytes = exports.wrapConstructorWithOpts = exports.wrapConstructor = exports.checkOpts = exports.Hash = exports.concatBytes = exports.toBytes = exports.utf8ToBytes = exports.asyncLoop = exports.nextTick = exports.hexToBytes = exports.bytesToHex = exports.isLE = exports.rotr = exports.createView = exports.u32 = exports.u8 = void 0; | ||
// The import here is via the package name. This is to ensure | ||
@@ -20,3 +20,3 @@ // that exports mapping/resolution does fall into place. | ||
exports.isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44; | ||
// There is almost no big endian hardware, but js typed arrays uses platform specific endianess. | ||
// There is almost no big endian hardware, but js typed arrays uses platform specific endianness. | ||
// So, just to be sure not to corrupt anything. | ||
@@ -31,2 +31,4 @@ if (!exports.isLE) | ||
// pre-caching improves the speed 6x | ||
if (!(uint8a instanceof Uint8Array)) | ||
throw new Error('Uint8Array expected'); | ||
let hex = ''; | ||
@@ -53,3 +55,3 @@ for (let i = 0; i < uint8a.length; i++) { | ||
const byte = Number.parseInt(hexByte, 16); | ||
if (Number.isNaN(byte)) | ||
if (Number.isNaN(byte) || byte < 0) | ||
throw new Error('Invalid byte sequence'); | ||
@@ -61,17 +63,6 @@ array[i] = byte; | ||
exports.hexToBytes = hexToBytes; | ||
// Currently avoid insertion of polyfills with packers (browserify/webpack/etc) | ||
// But setTimeout is pretty slow, maybe worth to investigate howto do minimal polyfill here | ||
exports.nextTick = (() => { | ||
const nodeRequire = typeof module !== 'undefined' && | ||
typeof module.require === 'function' && | ||
module.require.bind(module); | ||
try { | ||
if (nodeRequire) { | ||
const { setImmediate } = nodeRequire('timers'); | ||
return () => new Promise((resolve) => setImmediate(resolve)); | ||
} | ||
} | ||
catch (e) { } | ||
return () => new Promise((resolve) => setTimeout(resolve, 0)); | ||
})(); | ||
// There is no setImmediate in browser and setTimeout is slow. However, call to async function will return Promise | ||
// which will be fullfiled only on next scheduler queue processing step and this is exactly what we need. | ||
const nextTick = async () => { }; | ||
exports.nextTick = nextTick; | ||
// Returns control to thread each 'tick' ms to avoid blocking | ||
@@ -125,27 +116,2 @@ async function asyncLoop(iters, tick, cb) { | ||
exports.concatBytes = concatBytes; | ||
function assertNumber(n) { | ||
if (!Number.isSafeInteger(n) || n < 0) | ||
throw new Error(`Wrong positive integer: ${n}`); | ||
} | ||
exports.assertNumber = assertNumber; | ||
function assertBool(b) { | ||
if (typeof b !== 'boolean') { | ||
throw new Error(`Expected boolean, not ${b}`); | ||
} | ||
} | ||
exports.assertBool = assertBool; | ||
function assertBytes(bytes, ...lengths) { | ||
if (bytes instanceof Uint8Array && (!lengths.length || lengths.includes(bytes.length))) { | ||
return; | ||
} | ||
throw new TypeError(`Expected ${lengths} bytes, not ${typeof bytes} with length=${bytes.length}`); | ||
} | ||
exports.assertBytes = assertBytes; | ||
function assertHash(hash) { | ||
if (typeof hash !== 'function' || typeof hash.create !== 'function') | ||
throw new Error('Hash should be wrapped by utils.wrapConstructor'); | ||
assertNumber(hash.outputLen); | ||
assertNumber(hash.blockLen); | ||
} | ||
exports.assertHash = assertHash; | ||
// For runtime check if class implements interface | ||
@@ -161,7 +127,7 @@ class Hash { | ||
const isPlainObject = (obj) => Object.prototype.toString.call(obj) === '[object Object]' && obj.constructor === Object; | ||
function checkOpts(def, _opts) { | ||
if (_opts !== undefined && (typeof _opts !== 'object' || !isPlainObject(_opts))) | ||
function checkOpts(defaults, opts) { | ||
if (opts !== undefined && (typeof opts !== 'object' || !isPlainObject(opts))) | ||
throw new TypeError('Options should be object or undefined'); | ||
const opts = Object.assign(def, _opts); | ||
return opts; | ||
const merged = Object.assign(defaults, opts); | ||
return merged; | ||
} | ||
@@ -168,0 +134,0 @@ exports.checkOpts = checkOpts; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
67
6072
268178