UNPKG

@airgap/coinlib-core

Version:

The @airgap/coinlib-core is a protocol agnostic library to prepare, sign and broadcast cryptocurrency transactions.

455 lines 17.6 kB
"use strict"; // Copyright (C) 2017 Dmitry Chestnykh // MIT License. See LICENSE file for details. Object.defineProperty(exports, "__esModule", { value: true }); exports.hash = exports.BLAKE2b = exports.MAX_MAX_DEPTH = exports.MAX_FANOUT = exports.MAX_LEAF_SIZE = exports.SALT_LENGTH = exports.PERSONALIZATION_LENGTH = exports.KEY_LENGTH = exports.DIGEST_LENGTH = exports.BLOCK_SIZE = void 0; var binary_1 = require("../../../../@stablelib/binary-1.0.1/packages/binary/binary"); var wipe_1 = require("../../../../@stablelib/wipe-1.0.1/packages/wipe/wipe"); exports.BLOCK_SIZE = 128; exports.DIGEST_LENGTH = 64; exports.KEY_LENGTH = 64; exports.PERSONALIZATION_LENGTH = 16; exports.SALT_LENGTH = 16; exports.MAX_LEAF_SIZE = Math.pow(2, 32) - 1; exports.MAX_FANOUT = 255; exports.MAX_MAX_DEPTH = 255; // not a typo var IV = new Uint32Array([ // low bits // high bits 0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a, 0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19, ]); // Note: sigma values are doubled since we store // 64-bit ints as two 32-bit ints in arrays. var SIGMA = [ [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30], [28, 20, 8, 16, 18, 30, 26, 12, 2, 24, 0, 4, 22, 14, 10, 6], [22, 16, 24, 0, 10, 4, 30, 26, 20, 28, 6, 12, 14, 2, 18, 8], [14, 18, 6, 2, 26, 24, 22, 28, 4, 12, 10, 20, 8, 0, 30, 16], [18, 0, 10, 14, 4, 8, 20, 30, 28, 2, 22, 24, 12, 16, 6, 26], [4, 24, 12, 20, 0, 22, 16, 6, 8, 26, 14, 10, 30, 28, 2, 18], [24, 10, 2, 30, 28, 26, 8, 20, 0, 14, 12, 6, 18, 4, 16, 22], [26, 22, 14, 28, 24, 2, 6, 18, 10, 0, 30, 8, 16, 12, 4, 20], [12, 30, 28, 18, 22, 6, 0, 16, 24, 4, 26, 14, 2, 8, 20, 10], [20, 4, 16, 8, 14, 12, 2, 10, 30, 22, 18, 28, 6, 24, 26, 0], [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30], [28, 20, 8, 16, 18, 30, 26, 12, 2, 24, 0, 4, 22, 14, 10, 6] ]; /** * BLAKE2b hash function. */ var BLAKE2b = /** @class */ (function () { function BLAKE2b(digestLength, config) { if (digestLength === void 0) { digestLength = 64; } this.digestLength = digestLength; this.blockSize = exports.BLOCK_SIZE; // Note: Int32Arrays for state and message are used for performance reasons. this._state = new Int32Array(IV); // hash state, initialized with IV this._buffer = new Uint8Array(exports.BLOCK_SIZE); // buffer for data this._bufferLength = 0; // number of bytes in buffer this._ctr = new Uint32Array(4); this._flag = new Uint32Array(4); this._lastNode = false; this._finished = false; this._vtmp = new Uint32Array(32); this._mtmp = new Uint32Array(32); // Validate digest length. if (digestLength < 1 || digestLength > exports.DIGEST_LENGTH) { throw new Error("blake2b: wrong digest length"); } // Validate config, if present. if (config) { this.validateConfig(config); } // Get key length from config. var keyLength = 0; if (config && config.key) { keyLength = config.key.length; } // Get tree fanout and maxDepth from config. var fanout = 1; var maxDepth = 1; if (config && config.tree) { fanout = config.tree.fanout; maxDepth = config.tree.maxDepth; } // Xor common parameters into state. this._state[0] ^= digestLength | (keyLength << 8) | (fanout << 16) | (maxDepth << 24); // Xor tree parameters into state. if (config && config.tree) { this._state[1] ^= config.tree.leafSize; this._state[2] ^= config.tree.nodeOffsetLowBits; this._state[3] ^= config.tree.nodeOffsetHighBits; this._state[4] ^= config.tree.nodeDepth | (config.tree.innerDigestLength << 8); this._lastNode = config.tree.lastNode; } // Xor salt into state. if (config && config.salt) { this._state[8] ^= (0, binary_1.readUint32LE)(config.salt, 0); this._state[9] ^= (0, binary_1.readUint32LE)(config.salt, 4); this._state[10] ^= (0, binary_1.readUint32LE)(config.salt, 8); this._state[11] ^= (0, binary_1.readUint32LE)(config.salt, 12); } // Xor personalization into state. if (config && config.personalization) { this._state[12] ^= (0, binary_1.readUint32LE)(config.personalization, 0); this._state[13] ^= (0, binary_1.readUint32LE)(config.personalization, 4); this._state[14] ^= (0, binary_1.readUint32LE)(config.personalization, 8); this._state[15] ^= (0, binary_1.readUint32LE)(config.personalization, 12); } // Save a copy of initialized state for reset. this._initialState = new Uint32Array(this._state); // Process key. if (config && config.key && keyLength > 0) { this._paddedKey = new Uint8Array(exports.BLOCK_SIZE); this._paddedKey.set(config.key); // Put padded key into buffer. this._buffer.set(this._paddedKey); this._bufferLength = exports.BLOCK_SIZE; } } BLAKE2b.prototype.reset = function () { // Restore initial state. this._state.set(this._initialState); if (this._paddedKey) { // Put padded key into buffer. this._buffer.set(this._paddedKey); this._bufferLength = exports.BLOCK_SIZE; } else { this._bufferLength = 0; } // Clear counters and flags. (0, wipe_1.wipe)(this._ctr); (0, wipe_1.wipe)(this._flag); this._finished = false; return this; }; BLAKE2b.prototype.validateConfig = function (config) { if (config.key && config.key.length > exports.KEY_LENGTH) { throw new Error("blake2b: wrong key length"); } if (config.salt && config.salt.length !== exports.SALT_LENGTH) { throw new Error("blake2b: wrong salt length"); } if (config.personalization && config.personalization.length !== exports.PERSONALIZATION_LENGTH) { throw new Error("blake2b: wrong personalization length"); } if (config.tree) { if (config.tree.fanout < 0 || config.tree.fanout > exports.MAX_FANOUT) { throw new Error("blake2b: wrong tree fanout"); } if (config.tree.maxDepth < 0 || config.tree.maxDepth > exports.MAX_MAX_DEPTH) { throw new Error("blake2b: wrong tree depth"); } if (config.tree.leafSize < 0 || config.tree.leafSize > exports.MAX_LEAF_SIZE) { throw new Error("blake2b: wrong leaf size"); } if (config.tree.innerDigestLength < 0 || config.tree.innerDigestLength > exports.DIGEST_LENGTH) { throw new Error("blake2b: wrong tree inner digest length"); } } }; BLAKE2b.prototype.update = function (data, dataLength) { if (dataLength === void 0) { dataLength = data.length; } if (this._finished) { throw new Error("blake2b: can't update because hash was finished."); } var left = exports.BLOCK_SIZE - this._bufferLength; var dataPos = 0; if (dataLength === 0) { return this; } // Finish buffer. if (dataLength > left) { for (var i = 0; i < left; i++) { this._buffer[this._bufferLength + i] = data[dataPos + i]; } this._processBlock(exports.BLOCK_SIZE); dataPos += left; dataLength -= left; this._bufferLength = 0; } // Process data blocks. while (dataLength > exports.BLOCK_SIZE) { for (var i = 0; i < exports.BLOCK_SIZE; i++) { this._buffer[i] = data[dataPos + i]; } this._processBlock(exports.BLOCK_SIZE); dataPos += exports.BLOCK_SIZE; dataLength -= exports.BLOCK_SIZE; this._bufferLength = 0; } // Copy leftovers to buffer. for (var i = 0; i < dataLength; i++) { this._buffer[this._bufferLength + i] = data[dataPos + i]; } this._bufferLength += dataLength; return this; }; BLAKE2b.prototype.finish = function (out) { if (!this._finished) { for (var i = this._bufferLength; i < exports.BLOCK_SIZE; i++) { this._buffer[i] = 0; } // Set last block flag. this._flag[0] = 0xffffffff; this._flag[1] = 0xffffffff; // Set last node flag if last node in tree. if (this._lastNode) { this._flag[2] = 0xffffffff; this._flag[3] = 0xffffffff; } this._processBlock(this._bufferLength); this._finished = true; } // Reuse buffer as temporary space for digest. var tmp = this._buffer.subarray(0, 64); for (var i = 0; i < 16; i++) { (0, binary_1.writeUint32LE)(this._state[i], tmp, i * 4); } out.set(tmp.subarray(0, out.length)); return this; }; BLAKE2b.prototype.digest = function () { var out = new Uint8Array(this.digestLength); this.finish(out); return out; }; BLAKE2b.prototype.clean = function () { (0, wipe_1.wipe)(this._vtmp); (0, wipe_1.wipe)(this._mtmp); (0, wipe_1.wipe)(this._state); (0, wipe_1.wipe)(this._buffer); (0, wipe_1.wipe)(this._initialState); if (this._paddedKey) { (0, wipe_1.wipe)(this._paddedKey); } this._bufferLength = 0; (0, wipe_1.wipe)(this._ctr); (0, wipe_1.wipe)(this._flag); this._lastNode = false; this._finished = false; }; BLAKE2b.prototype.saveState = function () { if (this._finished) { throw new Error("blake2b: cannot save finished state"); } return { state: new Uint32Array(this._state), buffer: new Uint8Array(this._buffer), bufferLength: this._bufferLength, ctr: new Uint32Array(this._ctr), flag: new Uint32Array(this._flag), lastNode: this._lastNode, paddedKey: this._paddedKey ? new Uint8Array(this._paddedKey) : undefined, initialState: new Uint32Array(this._initialState) }; }; BLAKE2b.prototype.restoreState = function (savedState) { this._state.set(savedState.state); this._buffer.set(savedState.buffer); this._bufferLength = savedState.bufferLength; this._ctr.set(savedState.ctr); this._flag.set(savedState.flag); this._lastNode = savedState.lastNode; if (this._paddedKey) { (0, wipe_1.wipe)(this._paddedKey); } this._paddedKey = savedState.paddedKey ? new Uint8Array(savedState.paddedKey) : undefined; this._initialState.set(savedState.initialState); return this; }; BLAKE2b.prototype.cleanSavedState = function (savedState) { (0, wipe_1.wipe)(savedState.state); (0, wipe_1.wipe)(savedState.buffer); (0, wipe_1.wipe)(savedState.initialState); if (savedState.paddedKey) { (0, wipe_1.wipe)(savedState.paddedKey); } savedState.bufferLength = 0; (0, wipe_1.wipe)(savedState.ctr); (0, wipe_1.wipe)(savedState.flag); savedState.lastNode = false; }; BLAKE2b.prototype._G = function (v, al, bl, cl, dl, ah, bh, ch, dh, ml0, mh0, ml1, mh1) { var vla = v[al], vha = v[ah], vlb = v[bl], vhb = v[bh], vlc = v[cl], vhc = v[ch], vld = v[dl], vhd = v[dh]; // 64-bit: va += vb var w = vla & 0xffff, x = vla >>> 16, y = vha & 0xffff, z = vha >>> 16; w += vlb & 0xffff; x += vlb >>> 16; y += vhb & 0xffff; z += vhb >>> 16; x += w >>> 16; y += x >>> 16; z += y >>> 16; vha = (y & 0xffff) | (z << 16); vla = (w & 0xffff) | (x << 16); // 64-bit: va += m[sigma[r][2 * i + 0]] w = vla & 0xffff; x = vla >>> 16; y = vha & 0xffff; z = vha >>> 16; w += ml0 & 0xffff; x += ml0 >>> 16; y += mh0 & 0xffff; z += mh0 >>> 16; x += w >>> 16; y += x >>> 16; z += y >>> 16; vha = (y & 0xffff) | (z << 16); vla = (w & 0xffff) | (x << 16); // 64-bit: vd ^= va vld ^= vla; vhd ^= vha; // 64-bit: rot(vd, 32) w = vhd; vhd = vld; vld = w; // 64-bit: vc += vd w = vlc & 0xffff; x = vlc >>> 16; y = vhc & 0xffff; z = vhc >>> 16; w += vld & 0xffff; x += vld >>> 16; y += vhd & 0xffff; z += vhd >>> 16; x += w >>> 16; y += x >>> 16; z += y >>> 16; vhc = (y & 0xffff) | (z << 16); vlc = (w & 0xffff) | (x << 16); // 64-bit: vb ^= vc vlb ^= vlc; vhb ^= vhc; // 64-bit: rot(vb, 24) w = vlb << 8 | vhb >>> 24; vlb = vhb << 8 | vlb >>> 24; vhb = w; // 64-bit: va += vb w = vla & 0xffff; x = vla >>> 16; y = vha & 0xffff; z = vha >>> 16; w += vlb & 0xffff; x += vlb >>> 16; y += vhb & 0xffff; z += vhb >>> 16; x += w >>> 16; y += x >>> 16; z += y >>> 16; vha = (y & 0xffff) | (z << 16); vla = (w & 0xffff) | (x << 16); // 64-bit: va += m[sigma[r][2 * i + 1] w = vla & 0xffff; x = vla >>> 16; y = vha & 0xffff; z = vha >>> 16; w += ml1 & 0xffff; x += ml1 >>> 16; y += mh1 & 0xffff; z += mh1 >>> 16; x += w >>> 16; y += x >>> 16; z += y >>> 16; vha = (y & 0xffff) | (z << 16); vla = (w & 0xffff) | (x << 16); // 64-bit: vd ^= va vld ^= vla; vhd ^= vha; // 64-bit: rot(vd, 16) w = vld << 16 | vhd >>> 16; vld = vhd << 16 | vld >>> 16; vhd = w; // 64-bit: vc += vd w = vlc & 0xffff; x = vlc >>> 16; y = vhc & 0xffff; z = vhc >>> 16; w += vld & 0xffff; x += vld >>> 16; y += vhd & 0xffff; z += vhd >>> 16; x += w >>> 16; y += x >>> 16; z += y >>> 16; vhc = (y & 0xffff) | (z << 16); vlc = (w & 0xffff) | (x << 16); // 64-bit: vb ^= vc vlb ^= vlc; vhb ^= vhc; // 64-bit: rot(vb, 63) w = vhb << 1 | vlb >>> 31; vlb = vlb << 1 | vhb >>> 31; vhb = w; v[al] = vla; v[ah] = vha; v[bl] = vlb; v[bh] = vhb; v[cl] = vlc; v[ch] = vhc; v[dl] = vld; v[dh] = vhd; }; BLAKE2b.prototype._incrementCounter = function (n) { for (var i = 0; i < 3; i++) { var a = this._ctr[i] + n; this._ctr[i] = a >>> 0; if (this._ctr[i] === a) { return; } n = 1; } }; BLAKE2b.prototype._processBlock = function (length) { this._incrementCounter(length); var v = this._vtmp; v.set(this._state); v.set(IV, 16); v[12 * 2 + 0] ^= this._ctr[0]; v[12 * 2 + 1] ^= this._ctr[1]; v[13 * 2 + 0] ^= this._ctr[2]; v[13 * 2 + 1] ^= this._ctr[3]; v[14 * 2 + 0] ^= this._flag[0]; v[14 * 2 + 1] ^= this._flag[1]; v[15 * 2 + 0] ^= this._flag[2]; v[15 * 2 + 1] ^= this._flag[3]; var m = this._mtmp; for (var i = 0; i < 32; i++) { m[i] = (0, binary_1.readUint32LE)(this._buffer, i * 4); } for (var r = 0; r < 12; r++) { this._G(v, 0, 8, 16, 24, 1, 9, 17, 25, m[SIGMA[r][0]], m[SIGMA[r][0] + 1], m[SIGMA[r][1]], m[SIGMA[r][1] + 1]); this._G(v, 2, 10, 18, 26, 3, 11, 19, 27, m[SIGMA[r][2]], m[SIGMA[r][2] + 1], m[SIGMA[r][3]], m[SIGMA[r][3] + 1]); this._G(v, 4, 12, 20, 28, 5, 13, 21, 29, m[SIGMA[r][4]], m[SIGMA[r][4] + 1], m[SIGMA[r][5]], m[SIGMA[r][5] + 1]); this._G(v, 6, 14, 22, 30, 7, 15, 23, 31, m[SIGMA[r][6]], m[SIGMA[r][6] + 1], m[SIGMA[r][7]], m[SIGMA[r][7] + 1]); this._G(v, 0, 10, 20, 30, 1, 11, 21, 31, m[SIGMA[r][8]], m[SIGMA[r][8] + 1], m[SIGMA[r][9]], m[SIGMA[r][9] + 1]); this._G(v, 2, 12, 22, 24, 3, 13, 23, 25, m[SIGMA[r][10]], m[SIGMA[r][10] + 1], m[SIGMA[r][11]], m[SIGMA[r][11] + 1]); this._G(v, 4, 14, 16, 26, 5, 15, 17, 27, m[SIGMA[r][12]], m[SIGMA[r][12] + 1], m[SIGMA[r][13]], m[SIGMA[r][13] + 1]); this._G(v, 6, 8, 18, 28, 7, 9, 19, 29, m[SIGMA[r][14]], m[SIGMA[r][14] + 1], m[SIGMA[r][15]], m[SIGMA[r][15] + 1]); } for (var i = 0; i < 16; i++) { this._state[i] ^= v[i] ^ v[i + 16]; } }; return BLAKE2b; }()); exports.BLAKE2b = BLAKE2b; function hash(data, digestLength, config) { if (digestLength === void 0) { digestLength = exports.DIGEST_LENGTH; } var h = new BLAKE2b(digestLength, config); h.update(data); var digest = h.digest(); h.clean(); return digest; } exports.hash = hash; //# sourceMappingURL=blake2b.js.map