crypto-es
Version:
A cryptography algorithms library compatible with ES6 and TypeScript
194 lines (192 loc) • 6.07 kB
JavaScript
const require_core = require('./core.cjs');
const require_x64_core = require('./x64-core.cjs');
//#region src/sha3.ts
const RHO_OFFSETS = [];
const PI_INDEXES = [];
const ROUND_CONSTANTS = [];
let _x = 1;
let _y = 0;
for (let t = 0; t < 24; t += 1) {
RHO_OFFSETS[_x + 5 * _y] = (t + 1) * (t + 2) / 2 % 64;
const newX = _y % 5;
const newY = (2 * _x + 3 * _y) % 5;
_x = newX;
_y = newY;
}
for (let x = 0; x < 5; x += 1) for (let y = 0; y < 5; y += 1) PI_INDEXES[x + 5 * y] = y + (2 * x + 3 * y) % 5 * 5;
let LFSR = 1;
for (let i = 0; i < 24; i += 1) {
let roundConstantMsw = 0;
let roundConstantLsw = 0;
for (let j = 0; j < 7; j += 1) {
if (LFSR & 1) {
const bitPosition = (1 << j) - 1;
if (bitPosition < 32) roundConstantLsw ^= 1 << bitPosition;
else roundConstantMsw ^= 1 << bitPosition - 32;
}
if (LFSR & 128) LFSR = LFSR << 1 ^ 113;
else LFSR <<= 1;
}
ROUND_CONSTANTS[i] = require_x64_core.X64Word.create(roundConstantMsw, roundConstantLsw);
}
const T = [];
for (let i = 0; i < 25; i += 1) T[i] = require_x64_core.X64Word.create();
/**
* SHA-3 hash algorithm.
*/
var SHA3Algo = class extends require_core.Hasher32 {
_state = [];
/**
* Initializes a newly created hasher.
*
* @param cfg - Configuration options.
* @property {number} outputLength - The desired number of bits in the output hash.
* Only values permitted are: 224, 256, 384, 512.
* Default: 512
*/
constructor(cfg) {
super(Object.assign({ outputLength: 512 }, cfg));
}
_doReset() {
this._state = [];
for (let i = 0; i < 25; i += 1) this._state[i] = new require_x64_core.X64Word();
this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32;
}
_doProcessBlock(M, offset) {
if (this._state.length === 0) this._doReset();
const state = this._state;
const nBlockSizeLanes = this.blockSize / 2;
for (let i = 0; i < nBlockSizeLanes; i += 1) {
let M2i = M[offset + 2 * i];
let M2i1 = M[offset + 2 * i + 1];
M2i = (M2i << 8 | M2i >>> 24) & 16711935 | (M2i << 24 | M2i >>> 8) & 4278255360;
M2i1 = (M2i1 << 8 | M2i1 >>> 24) & 16711935 | (M2i1 << 24 | M2i1 >>> 8) & 4278255360;
const lane = state[i];
lane.high ^= M2i1;
lane.low ^= M2i;
}
for (let round = 0; round < 24; round += 1) {
for (let x = 0; x < 5; x += 1) {
let tMsw = 0;
let tLsw = 0;
for (let y = 0; y < 5; y += 1) {
const lane$1 = state[x + 5 * y];
tMsw ^= lane$1.high;
tLsw ^= lane$1.low;
}
const Tx = T[x];
Tx.high = tMsw;
Tx.low = tLsw;
}
for (let x = 0; x < 5; x += 1) {
const Tx4 = T[(x + 4) % 5];
const Tx1 = T[(x + 1) % 5];
const Tx1Msw = Tx1.high;
const Tx1Lsw = Tx1.low;
const tMsw = Tx4.high ^ (Tx1Msw << 1 | Tx1Lsw >>> 31);
const tLsw = Tx4.low ^ (Tx1Lsw << 1 | Tx1Msw >>> 31);
for (let y = 0; y < 5; y += 1) {
const lane$1 = state[x + 5 * y];
lane$1.high ^= tMsw;
lane$1.low ^= tLsw;
}
}
for (let laneIndex = 1; laneIndex < 25; laneIndex += 1) {
let tMsw;
let tLsw;
const lane$1 = state[laneIndex];
const laneMsw = lane$1.high;
const laneLsw = lane$1.low;
const rhoOffset = RHO_OFFSETS[laneIndex];
if (rhoOffset < 32) {
tMsw = laneMsw << rhoOffset | laneLsw >>> 32 - rhoOffset;
tLsw = laneLsw << rhoOffset | laneMsw >>> 32 - rhoOffset;
} else {
tMsw = laneLsw << rhoOffset - 32 | laneMsw >>> 64 - rhoOffset;
tLsw = laneMsw << rhoOffset - 32 | laneLsw >>> 64 - rhoOffset;
}
const TPiLane = T[PI_INDEXES[laneIndex]];
TPiLane.high = tMsw;
TPiLane.low = tLsw;
}
const T0 = T[0];
const state0 = state[0];
T0.high = state0.high;
T0.low = state0.low;
for (let x = 0; x < 5; x += 1) for (let y = 0; y < 5; y += 1) {
const laneIndex = x + 5 * y;
const lane$1 = state[laneIndex];
const TLane = T[laneIndex];
const Tx1Lane = T[(x + 1) % 5 + 5 * y];
const Tx2Lane = T[(x + 2) % 5 + 5 * y];
lane$1.high = TLane.high ^ ~Tx1Lane.high & Tx2Lane.high;
lane$1.low = TLane.low ^ ~Tx1Lane.low & Tx2Lane.low;
}
const lane = state[0];
const roundConstant = ROUND_CONSTANTS[round];
lane.high ^= roundConstant.high;
lane.low ^= roundConstant.low;
}
}
_doFinalize() {
const data = this._data;
const dataWords = data.words;
const nBitsLeft = data.sigBytes * 8;
const blockSizeBits = this.blockSize * 32;
dataWords[nBitsLeft >>> 5] |= 1 << 24 - nBitsLeft % 32;
dataWords[(Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits >>> 5) - 1] |= 128;
data.sigBytes = dataWords.length * 4;
this._process();
const state = this._state;
const outputLengthBytes = this.cfg.outputLength / 8;
const outputLengthLanes = outputLengthBytes / 8;
const hashWords = [];
for (let i = 0; i < outputLengthLanes; i += 1) {
const lane = state[i];
let laneMsw = lane.high;
let laneLsw = lane.low;
laneMsw = (laneMsw << 8 | laneMsw >>> 24) & 16711935 | (laneMsw << 24 | laneMsw >>> 8) & 4278255360;
laneLsw = (laneLsw << 8 | laneLsw >>> 24) & 16711935 | (laneLsw << 24 | laneLsw >>> 8) & 4278255360;
hashWords.push(laneLsw);
hashWords.push(laneMsw);
}
return new require_core.WordArray(hashWords, outputLengthBytes);
}
clone() {
const clone = super.clone.call(this);
clone._state = [];
for (let i = 0; i < this._state.length; i += 1) clone._state[i] = this._state[i].clone();
return clone;
}
};
/**
* Shortcut function to the hasher's object interface.
*
* @param message - The message to hash.
* @returns The hash.
*
* @example
* ```js
* const hash = CryptoJS.SHA3('message');
* const hash = CryptoJS.SHA3(wordArray);
* ```
*/
const SHA3 = require_core.Hasher._createHelper(SHA3Algo);
/**
* Shortcut function to the HMAC's object interface.
*
* @param message - The message to hash.
* @param key - The secret key.
* @returns The HMAC.
*
* @example
* ```js
* const hmac = CryptoJS.HmacSHA3(message, key);
* ```
*/
const HmacSHA3 = require_core.Hasher._createHmacHelper(SHA3Algo);
//#endregion
exports.HmacSHA3 = HmacSHA3;
exports.SHA3 = SHA3;
exports.SHA3Algo = SHA3Algo;
//# sourceMappingURL=sha3.cjs.map