You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
326 lines
10 KiB
326 lines
10 KiB
;(function (root, factory, undef) { |
|
if (typeof exports === "object") { |
|
// CommonJS |
|
module.exports = exports = factory(require("./core"), require("./x64-core")); |
|
} |
|
else if (typeof define === "function" && define.amd) { |
|
// AMD |
|
define(["./core", "./x64-core"], factory); |
|
} |
|
else { |
|
// Global (browser) |
|
factory(root.CryptoJS); |
|
} |
|
}(this, function (CryptoJS) { |
|
|
|
(function (Math) { |
|
// Shortcuts |
|
var C = CryptoJS; |
|
var C_lib = C.lib; |
|
var WordArray = C_lib.WordArray; |
|
var Hasher = C_lib.Hasher; |
|
var C_x64 = C.x64; |
|
var X64Word = C_x64.Word; |
|
var C_algo = C.algo; |
|
|
|
// Constants tables |
|
var RHO_OFFSETS = []; |
|
var PI_INDEXES = []; |
|
var ROUND_CONSTANTS = []; |
|
|
|
// Compute Constants |
|
(function () { |
|
// Compute rho offset constants |
|
var x = 1, y = 0; |
|
for (var t = 0; t < 24; t++) { |
|
RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64; |
|
|
|
var newX = y % 5; |
|
var newY = (2 * x + 3 * y) % 5; |
|
x = newX; |
|
y = newY; |
|
} |
|
|
|
// Compute pi index constants |
|
for (var x = 0; x < 5; x++) { |
|
for (var y = 0; y < 5; y++) { |
|
PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; |
|
} |
|
} |
|
|
|
// Compute round constants |
|
var LFSR = 0x01; |
|
for (var i = 0; i < 24; i++) { |
|
var roundConstantMsw = 0; |
|
var roundConstantLsw = 0; |
|
|
|
for (var j = 0; j < 7; j++) { |
|
if (LFSR & 0x01) { |
|
var bitPosition = (1 << j) - 1; |
|
if (bitPosition < 32) { |
|
roundConstantLsw ^= 1 << bitPosition; |
|
} else /* if (bitPosition >= 32) */ { |
|
roundConstantMsw ^= 1 << (bitPosition - 32); |
|
} |
|
} |
|
|
|
// Compute next LFSR |
|
if (LFSR & 0x80) { |
|
// Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 |
|
LFSR = (LFSR << 1) ^ 0x71; |
|
} else { |
|
LFSR <<= 1; |
|
} |
|
} |
|
|
|
ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); |
|
} |
|
}()); |
|
|
|
// Reusable objects for temporary values |
|
var T = []; |
|
(function () { |
|
for (var i = 0; i < 25; i++) { |
|
T[i] = X64Word.create(); |
|
} |
|
}()); |
|
|
|
/** |
|
* SHA-3 hash algorithm. |
|
*/ |
|
var SHA3 = C_algo.SHA3 = Hasher.extend({ |
|
/** |
|
* Configuration options. |
|
* |
|
* @property {number} outputLength |
|
* The desired number of bits in the output hash. |
|
* Only values permitted are: 224, 256, 384, 512. |
|
* Default: 512 |
|
*/ |
|
cfg: Hasher.cfg.extend({ |
|
outputLength: 512 |
|
}), |
|
|
|
_doReset: function () { |
|
var state = this._state = [] |
|
for (var i = 0; i < 25; i++) { |
|
state[i] = new X64Word.init(); |
|
} |
|
|
|
this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; |
|
}, |
|
|
|
_doProcessBlock: function (M, offset) { |
|
// Shortcuts |
|
var state = this._state; |
|
var nBlockSizeLanes = this.blockSize / 2; |
|
|
|
// Absorb |
|
for (var i = 0; i < nBlockSizeLanes; i++) { |
|
// Shortcuts |
|
var M2i = M[offset + 2 * i]; |
|
var M2i1 = M[offset + 2 * i + 1]; |
|
|
|
// Swap endian |
|
M2i = ( |
|
(((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) | |
|
(((M2i << 24) | (M2i >>> 8)) & 0xff00ff00) |
|
); |
|
M2i1 = ( |
|
(((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) | |
|
(((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00) |
|
); |
|
|
|
// Absorb message into state |
|
var lane = state[i]; |
|
lane.high ^= M2i1; |
|
lane.low ^= M2i; |
|
} |
|
|
|
// Rounds |
|
for (var round = 0; round < 24; round++) { |
|
// Theta |
|
for (var x = 0; x < 5; x++) { |
|
// Mix column lanes |
|
var tMsw = 0, tLsw = 0; |
|
for (var y = 0; y < 5; y++) { |
|
var lane = state[x + 5 * y]; |
|
tMsw ^= lane.high; |
|
tLsw ^= lane.low; |
|
} |
|
|
|
// Temporary values |
|
var Tx = T[x]; |
|
Tx.high = tMsw; |
|
Tx.low = tLsw; |
|
} |
|
for (var x = 0; x < 5; x++) { |
|
// Shortcuts |
|
var Tx4 = T[(x + 4) % 5]; |
|
var Tx1 = T[(x + 1) % 5]; |
|
var Tx1Msw = Tx1.high; |
|
var Tx1Lsw = Tx1.low; |
|
|
|
// Mix surrounding columns |
|
var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); |
|
var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); |
|
for (var y = 0; y < 5; y++) { |
|
var lane = state[x + 5 * y]; |
|
lane.high ^= tMsw; |
|
lane.low ^= tLsw; |
|
} |
|
} |
|
|
|
// Rho Pi |
|
for (var laneIndex = 1; laneIndex < 25; laneIndex++) { |
|
var tMsw; |
|
var tLsw; |
|
|
|
// Shortcuts |
|
var lane = state[laneIndex]; |
|
var laneMsw = lane.high; |
|
var laneLsw = lane.low; |
|
var rhoOffset = RHO_OFFSETS[laneIndex]; |
|
|
|
// Rotate lanes |
|
if (rhoOffset < 32) { |
|
tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); |
|
tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); |
|
} else /* if (rhoOffset >= 32) */ { |
|
tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); |
|
tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); |
|
} |
|
|
|
// Transpose lanes |
|
var TPiLane = T[PI_INDEXES[laneIndex]]; |
|
TPiLane.high = tMsw; |
|
TPiLane.low = tLsw; |
|
} |
|
|
|
// Rho pi at x = y = 0 |
|
var T0 = T[0]; |
|
var state0 = state[0]; |
|
T0.high = state0.high; |
|
T0.low = state0.low; |
|
|
|
// Chi |
|
for (var x = 0; x < 5; x++) { |
|
for (var y = 0; y < 5; y++) { |
|
// Shortcuts |
|
var laneIndex = x + 5 * y; |
|
var lane = state[laneIndex]; |
|
var TLane = T[laneIndex]; |
|
var Tx1Lane = T[((x + 1) % 5) + 5 * y]; |
|
var Tx2Lane = T[((x + 2) % 5) + 5 * y]; |
|
|
|
// Mix rows |
|
lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); |
|
lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); |
|
} |
|
} |
|
|
|
// Iota |
|
var lane = state[0]; |
|
var roundConstant = ROUND_CONSTANTS[round]; |
|
lane.high ^= roundConstant.high; |
|
lane.low ^= roundConstant.low; |
|
} |
|
}, |
|
|
|
_doFinalize: function () { |
|
// Shortcuts |
|
var data = this._data; |
|
var dataWords = data.words; |
|
var nBitsTotal = this._nDataBytes * 8; |
|
var nBitsLeft = data.sigBytes * 8; |
|
var blockSizeBits = this.blockSize * 32; |
|
|
|
// Add padding |
|
dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32); |
|
dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; |
|
data.sigBytes = dataWords.length * 4; |
|
|
|
// Hash final blocks |
|
this._process(); |
|
|
|
// Shortcuts |
|
var state = this._state; |
|
var outputLengthBytes = this.cfg.outputLength / 8; |
|
var outputLengthLanes = outputLengthBytes / 8; |
|
|
|
// Squeeze |
|
var hashWords = []; |
|
for (var i = 0; i < outputLengthLanes; i++) { |
|
// Shortcuts |
|
var lane = state[i]; |
|
var laneMsw = lane.high; |
|
var laneLsw = lane.low; |
|
|
|
// Swap endian |
|
laneMsw = ( |
|
(((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) | |
|
(((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00) |
|
); |
|
laneLsw = ( |
|
(((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) | |
|
(((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00) |
|
); |
|
|
|
// Squeeze state to retrieve hash |
|
hashWords.push(laneLsw); |
|
hashWords.push(laneMsw); |
|
} |
|
|
|
// Return final computed hash |
|
return new WordArray.init(hashWords, outputLengthBytes); |
|
}, |
|
|
|
clone: function () { |
|
var clone = Hasher.clone.call(this); |
|
|
|
var state = clone._state = this._state.slice(0); |
|
for (var i = 0; i < 25; i++) { |
|
state[i] = state[i].clone(); |
|
} |
|
|
|
return clone; |
|
} |
|
}); |
|
|
|
/** |
|
* Shortcut function to the hasher's object interface. |
|
* |
|
* @param {WordArray|string} message The message to hash. |
|
* |
|
* @return {WordArray} The hash. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var hash = CryptoJS.SHA3('message'); |
|
* var hash = CryptoJS.SHA3(wordArray); |
|
*/ |
|
C.SHA3 = Hasher._createHelper(SHA3); |
|
|
|
/** |
|
* Shortcut function to the HMAC's object interface. |
|
* |
|
* @param {WordArray|string} message The message to hash. |
|
* @param {WordArray|string} key The secret key. |
|
* |
|
* @return {WordArray} The HMAC. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var hmac = CryptoJS.HmacSHA3(message, key); |
|
*/ |
|
C.HmacSHA3 = Hasher._createHmacHelper(SHA3); |
|
}(Math)); |
|
|
|
|
|
return CryptoJS.SHA3; |
|
|
|
})); |