UNPKG

@stablelib/sha3

Version:
521 lines 15.4 kB
// Copyright (C) 2016 Dmitry Chestnykh // MIT License. See LICENSE file for details. import { readUint32LE, writeUint32LE } from "@stablelib/binary"; import { wipe } from "@stablelib/wipe"; export class Keccak { capacity; _sh = new Int32Array(25); // temporary space for permutation (high bits) _sl = new Int32Array(25); // temporary space for permutation (low bits) _state = new Uint8Array(200); // hash state _pos = 0; // position in state to XOR bytes into _finished = false; // whether the hash was finalized blockSize; // block size, which is also a sponge "rate" constructor(capacity = 32) { this.capacity = capacity; if (capacity <= 0 || capacity > 128) { throw new Error("SHA3: incorrect capacity"); } this.blockSize = 200 - capacity; } reset() { wipe(this._sh); wipe(this._sl); wipe(this._state); this._pos = 0; this._finished = false; return this; } clean = this.reset; update(data) { if (this._finished) { throw new Error("SHA3: can't update because hash was finished"); } // XOR data into the "rate"-size part of state // (the rest is "capacity", which is not touched from outside). for (let i = 0; i < data.length; i++) { this._state[this._pos++] ^= data[i]; // If the "rate" part is full, process the whole state // with Keccak permutation and reset position. if (this._pos >= this.blockSize) { keccakf(this._sh, this._sl, this._state); this._pos = 0; } } return this; } _padAndPermute(paddingByte) { // Apply padding. this._state[this._pos] ^= paddingByte; this._state[this.blockSize - 1] ^= 0x80; // Permute state. keccakf(this._sh, this._sl, this._state); // Set finished flag to true. this._finished = true; this._pos = 0; } _squeeze(dst) { if (!this._finished) { throw new Error("SHA3: squeezing before padAndPermute"); } // Squeeze. for (let i = 0; i < dst.length; i++) { if (this._pos === this.blockSize) { // Permute. keccakf(this._sh, this._sl, this._state); this._pos = 0; } dst[i] = this._state[this._pos++]; } } } export class SHA3 extends Keccak { digestLength; constructor(digestLength = 32) { super(digestLength * 2); this.digestLength = digestLength; } finish(dst) { if (!this._finished) { this._padAndPermute(0x06); } else { // XXX: only works for up to blockSize digests, // which is the case in our implementation. this._pos = 0; } this._squeeze(dst); return this; } digest() { let out = new Uint8Array(this.digestLength); this.finish(out); return out; } saveState() { if (this._finished) { throw new Error("SHA3: cannot save finished state"); } return new Uint8Array(this._state.subarray(0, this._pos)); } restoreState(savedState) { this._state.set(savedState); this._pos = savedState.length; this._finished = false; return this; } cleanSavedState(savedState) { wipe(savedState); } } export class SHA3224 extends SHA3 { constructor() { super(224 / 8); } } export class SHA3256 extends SHA3 { constructor() { super(256 / 8); } } export class SHA3384 extends SHA3 { constructor() { super(384 / 8); } } export class SHA3512 extends SHA3 { constructor() { super(512 / 8); } } export function hash(digestLength, data) { const h = new SHA3(digestLength); h.update(data); const digest = h.digest(); h.clean(); return digest; } export const hash224 = (data) => hash(224 / 8, data); export const hash256 = (data) => hash(256 / 8, data); export const hash384 = (data) => hash(384 / 8, data); export const hash512 = (data) => hash(512 / 8, data); export class SHAKE extends Keccak { bitSize; constructor(bitSize) { super(bitSize / 8 * 2); this.bitSize = bitSize; } stream(dst) { if (!this._finished) { this._padAndPermute(0x1f); } this._squeeze(dst); } } export class SHAKE128 extends SHAKE { constructor() { super(128); } } export class SHAKE256 extends SHAKE { constructor() { super(256); } } const RNDC_HI = new Int32Array([ 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x00000000, 0x80000000, 0x80000000, 0x80000000, 0x00000000, 0x80000000 ]); const RNDC_LO = new Int32Array([ 0x00000001, 0x00008082, 0x0000808a, 0x80008000, 0x0000808b, 0x80000001, 0x80008081, 0x00008009, 0x0000008a, 0x00000088, 0x80008009, 0x8000000a, 0x8000808b, 0x0000008b, 0x00008089, 0x00008003, 0x00008002, 0x00000080, 0x0000800a, 0x8000000a, 0x80008081, 0x00008080, 0x80000001, 0x80008008 ]); function keccakf(sh, sl, buf) { let bch0, bch1, bch2, bch3, bch4; let bcl0, bcl1, bcl2, bcl3, bcl4; let th, tl; for (let i = 0; i < 25; i++) { sl[i] = readUint32LE(buf, i * 8); sh[i] = readUint32LE(buf, i * 8 + 4); } for (let r = 0; r < 24; r++) { // Theta bch0 = sh[0] ^ sh[5] ^ sh[10] ^ sh[15] ^ sh[20]; bch1 = sh[1] ^ sh[6] ^ sh[11] ^ sh[16] ^ sh[21]; bch2 = sh[2] ^ sh[7] ^ sh[12] ^ sh[17] ^ sh[22]; bch3 = sh[3] ^ sh[8] ^ sh[13] ^ sh[18] ^ sh[23]; bch4 = sh[4] ^ sh[9] ^ sh[14] ^ sh[19] ^ sh[24]; bcl0 = sl[0] ^ sl[5] ^ sl[10] ^ sl[15] ^ sl[20]; bcl1 = sl[1] ^ sl[6] ^ sl[11] ^ sl[16] ^ sl[21]; bcl2 = sl[2] ^ sl[7] ^ sl[12] ^ sl[17] ^ sl[22]; bcl3 = sl[3] ^ sl[8] ^ sl[13] ^ sl[18] ^ sl[23]; bcl4 = sl[4] ^ sl[9] ^ sl[14] ^ sl[19] ^ sl[24]; th = bch4 ^ ((bch1 << 1) | (bcl1 >>> (32 - 1))); tl = bcl4 ^ ((bcl1 << 1) | (bch1 >>> (32 - 1))); sh[0] ^= th; sh[5] ^= th; sh[10] ^= th; sh[15] ^= th; sh[20] ^= th; sl[0] ^= tl; sl[5] ^= tl; sl[10] ^= tl; sl[15] ^= tl; sl[20] ^= tl; th = bch0 ^ ((bch2 << 1) | (bcl2 >>> (32 - 1))); tl = bcl0 ^ ((bcl2 << 1) | (bch2 >>> (32 - 1))); sh[1] ^= th; sh[6] ^= th; sh[11] ^= th; sh[16] ^= th; sh[21] ^= th; sl[1] ^= tl; sl[6] ^= tl; sl[11] ^= tl; sl[16] ^= tl; sl[21] ^= tl; th = bch1 ^ ((bch3 << 1) | (bcl3 >>> (32 - 1))); tl = bcl1 ^ ((bcl3 << 1) | (bch3 >>> (32 - 1))); sh[2] ^= th; sh[7] ^= th; sh[12] ^= th; sh[17] ^= th; sh[22] ^= th; sl[2] ^= tl; sl[7] ^= tl; sl[12] ^= tl; sl[17] ^= tl; sl[22] ^= tl; th = bch2 ^ ((bch4 << 1) | (bcl4 >>> (32 - 1))); tl = bcl2 ^ ((bcl4 << 1) | (bch4 >>> (32 - 1))); sh[3] ^= th; sl[3] ^= tl; sh[8] ^= th; sl[8] ^= tl; sh[13] ^= th; sl[13] ^= tl; sh[18] ^= th; sl[18] ^= tl; sh[23] ^= th; sl[23] ^= tl; th = bch3 ^ ((bch0 << 1) | (bcl0 >>> (32 - 1))); tl = bcl3 ^ ((bcl0 << 1) | (bch0 >>> (32 - 1))); sh[4] ^= th; sh[9] ^= th; sh[14] ^= th; sh[19] ^= th; sh[24] ^= th; sl[4] ^= tl; sl[9] ^= tl; sl[14] ^= tl; sl[19] ^= tl; sl[24] ^= tl; // Rho Pi th = sh[1]; tl = sl[1]; bch0 = sh[10]; bcl0 = sl[10]; sh[10] = (th << 1) | (tl >>> (32 - 1)); sl[10] = (tl << 1) | (th >>> (32 - 1)); th = bch0; tl = bcl0; bch0 = sh[7]; bcl0 = sl[7]; sh[7] = (th << 3) | (tl >>> (32 - 3)); sl[7] = (tl << 3) | (th >>> (32 - 3)); th = bch0; tl = bcl0; bch0 = sh[11]; bcl0 = sl[11]; sh[11] = (th << 6) | (tl >>> (32 - 6)); sl[11] = (tl << 6) | (th >>> (32 - 6)); th = bch0; tl = bcl0; bch0 = sh[17]; bcl0 = sl[17]; sh[17] = (th << 10) | (tl >>> (32 - 10)); sl[17] = (tl << 10) | (th >>> (32 - 10)); th = bch0; tl = bcl0; bch0 = sh[18]; bcl0 = sl[18]; sh[18] = (th << 15) | (tl >>> (32 - 15)); sl[18] = (tl << 15) | (th >>> (32 - 15)); th = bch0; tl = bcl0; bch0 = sh[3]; bcl0 = sl[3]; sh[3] = (th << 21) | (tl >>> (32 - 21)); sl[3] = (tl << 21) | (th >>> (32 - 21)); th = bch0; tl = bcl0; bch0 = sh[5]; bcl0 = sl[5]; sh[5] = (th << 28) | (tl >>> (32 - 28)); sl[5] = (tl << 28) | (th >>> (32 - 28)); th = bch0; tl = bcl0; bch0 = sh[16]; bcl0 = sl[16]; sh[16] = (tl << 4) | (th >>> (32 - 4)); sl[16] = (th << 4) | (tl >>> (32 - 4)); th = bch0; tl = bcl0; bch0 = sh[8]; bcl0 = sl[8]; sh[8] = (tl << 13) | (th >>> (32 - 13)); sl[8] = (th << 13) | (tl >>> (32 - 13)); th = bch0; tl = bcl0; bch0 = sh[21]; bcl0 = sl[21]; sh[21] = (tl << 23) | (th >>> (32 - 23)); sl[21] = (th << 23) | (tl >>> (32 - 23)); th = bch0; tl = bcl0; bch0 = sh[24]; bcl0 = sl[24]; sh[24] = (th << 2) | (tl >>> (32 - 2)); sl[24] = (tl << 2) | (th >>> (32 - 2)); th = bch0; tl = bcl0; bch0 = sh[4]; bcl0 = sl[4]; sh[4] = (th << 14) | (tl >>> (32 - 14)); sl[4] = (tl << 14) | (th >>> (32 - 14)); th = bch0; tl = bcl0; bch0 = sh[15]; bcl0 = sl[15]; sh[15] = (th << 27) | (tl >>> (32 - 27)); sl[15] = (tl << 27) | (th >>> (32 - 27)); th = bch0; tl = bcl0; bch0 = sh[23]; bcl0 = sl[23]; sh[23] = (tl << 9) | (th >>> (32 - 9)); sl[23] = (th << 9) | (tl >>> (32 - 9)); th = bch0; tl = bcl0; bch0 = sh[19]; bcl0 = sl[19]; sh[19] = (tl << 24) | (th >>> (32 - 24)); sl[19] = (th << 24) | (tl >>> (32 - 24)); th = bch0; tl = bcl0; bch0 = sh[13]; bcl0 = sl[13]; sh[13] = (th << 8) | (tl >>> (32 - 8)); sl[13] = (tl << 8) | (th >>> (32 - 8)); th = bch0; tl = bcl0; bch0 = sh[12]; bcl0 = sl[12]; sh[12] = (th << 25) | (tl >>> (32 - 25)); sl[12] = (tl << 25) | (th >>> (32 - 25)); th = bch0; tl = bcl0; bch0 = sh[2]; bcl0 = sl[2]; sh[2] = (tl << 11) | (th >>> (32 - 11)); sl[2] = (th << 11) | (tl >>> (32 - 11)); th = bch0; tl = bcl0; bch0 = sh[20]; bcl0 = sl[20]; sh[20] = (tl << 30) | (th >>> (32 - 30)); sl[20] = (th << 30) | (tl >>> (32 - 30)); th = bch0; tl = bcl0; bch0 = sh[14]; bcl0 = sl[14]; sh[14] = (th << 18) | (tl >>> (32 - 18)); sl[14] = (tl << 18) | (th >>> (32 - 18)); th = bch0; tl = bcl0; bch0 = sh[22]; bcl0 = sl[22]; sh[22] = (tl << 7) | (th >>> (32 - 7)); sl[22] = (th << 7) | (tl >>> (32 - 7)); th = bch0; tl = bcl0; bch0 = sh[9]; bcl0 = sl[9]; sh[9] = (tl << 29) | (th >>> (32 - 29)); sl[9] = (th << 29) | (tl >>> (32 - 29)); th = bch0; tl = bcl0; bch0 = sh[6]; bcl0 = sl[6]; sh[6] = (th << 20) | (tl >>> (32 - 20)); sl[6] = (tl << 20) | (th >>> (32 - 20)); th = bch0; tl = bcl0; bch0 = sh[1]; bcl0 = sl[1]; sh[1] = (tl << 12) | (th >>> (32 - 12)); sl[1] = (th << 12) | (tl >>> (32 - 12)); th = bch0; tl = bcl0; // Chi bch0 = sh[0]; bch1 = sh[1]; bch2 = sh[2]; bch3 = sh[3]; bch4 = sh[4]; sh[0] ^= (~bch1) & bch2; sh[1] ^= (~bch2) & bch3; sh[2] ^= (~bch3) & bch4; sh[3] ^= (~bch4) & bch0; sh[4] ^= (~bch0) & bch1; bcl0 = sl[0]; bcl1 = sl[1]; bcl2 = sl[2]; bcl3 = sl[3]; bcl4 = sl[4]; sl[0] ^= (~bcl1) & bcl2; sl[1] ^= (~bcl2) & bcl3; sl[2] ^= (~bcl3) & bcl4; sl[3] ^= (~bcl4) & bcl0; sl[4] ^= (~bcl0) & bcl1; bch0 = sh[5]; bch1 = sh[6]; bch2 = sh[7]; bch3 = sh[8]; bch4 = sh[9]; sh[5] ^= (~bch1) & bch2; sh[6] ^= (~bch2) & bch3; sh[7] ^= (~bch3) & bch4; sh[8] ^= (~bch4) & bch0; sh[9] ^= (~bch0) & bch1; bcl0 = sl[5]; bcl1 = sl[6]; bcl2 = sl[7]; bcl3 = sl[8]; bcl4 = sl[9]; sl[5] ^= (~bcl1) & bcl2; sl[6] ^= (~bcl2) & bcl3; sl[7] ^= (~bcl3) & bcl4; sl[8] ^= (~bcl4) & bcl0; sl[9] ^= (~bcl0) & bcl1; bch0 = sh[10]; bch1 = sh[11]; bch2 = sh[12]; bch3 = sh[13]; bch4 = sh[14]; sh[10] ^= (~bch1) & bch2; sh[11] ^= (~bch2) & bch3; sh[12] ^= (~bch3) & bch4; sh[13] ^= (~bch4) & bch0; sh[14] ^= (~bch0) & bch1; bcl0 = sl[10]; bcl1 = sl[11]; bcl2 = sl[12]; bcl3 = sl[13]; bcl4 = sl[14]; sl[10] ^= (~bcl1) & bcl2; sl[11] ^= (~bcl2) & bcl3; sl[12] ^= (~bcl3) & bcl4; sl[13] ^= (~bcl4) & bcl0; sl[14] ^= (~bcl0) & bcl1; bch0 = sh[15]; bch1 = sh[16]; bch2 = sh[17]; bch3 = sh[18]; bch4 = sh[19]; sh[15] ^= (~bch1) & bch2; sh[16] ^= (~bch2) & bch3; sh[17] ^= (~bch3) & bch4; sh[18] ^= (~bch4) & bch0; sh[19] ^= (~bch0) & bch1; bcl0 = sl[15]; bcl1 = sl[16]; bcl2 = sl[17]; bcl3 = sl[18]; bcl4 = sl[19]; sl[15] ^= (~bcl1) & bcl2; sl[16] ^= (~bcl2) & bcl3; sl[17] ^= (~bcl3) & bcl4; sl[18] ^= (~bcl4) & bcl0; sl[19] ^= (~bcl0) & bcl1; bch0 = sh[20]; bch1 = sh[21]; bch2 = sh[22]; bch3 = sh[23]; bch4 = sh[24]; sh[20] ^= (~bch1) & bch2; sh[21] ^= (~bch2) & bch3; sh[22] ^= (~bch3) & bch4; sh[23] ^= (~bch4) & bch0; sh[24] ^= (~bch0) & bch1; bcl0 = sl[20]; bcl1 = sl[21]; bcl2 = sl[22]; bcl3 = sl[23]; bcl4 = sl[24]; sl[20] ^= (~bcl1) & bcl2; sl[21] ^= (~bcl2) & bcl3; sl[22] ^= (~bcl3) & bcl4; sl[23] ^= (~bcl4) & bcl0; sl[24] ^= (~bcl0) & bcl1; // Iota sh[0] ^= RNDC_HI[r]; sl[0] ^= RNDC_LO[r]; } for (let i = 0; i < 25; i++) { writeUint32LE(sl[i], buf, i * 8); writeUint32LE(sh[i], buf, i * 8 + 4); } } //# sourceMappingURL=sha3.js.map