-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
AbigailDeng
authored and
AbigailDeng
committed
Mar 17, 2023
1 parent
5978c6e
commit af44292
Showing
10 changed files
with
415 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* eslint-disable no-param-reassign */ | ||
const { Transform } = require('readable-stream'); | ||
|
||
module.exports = KeccakState => class Keccak extends Transform { | ||
constructor(rate, capacity, delimitedSuffix, hashBitLength, options) { | ||
super(options); | ||
|
||
this._rate = rate; | ||
this._capacity = capacity; | ||
this._delimitedSuffix = delimitedSuffix; | ||
this._hashBitLength = hashBitLength; | ||
this._options = options; | ||
|
||
this._state = new KeccakState(); | ||
this._state.initialize(rate, capacity); | ||
this._finalized = false; | ||
} | ||
|
||
update(data, encoding) { | ||
if (!Buffer.isBuffer(data) && typeof data !== 'string') { | ||
throw new TypeError('Data must be a string or a buffer'); | ||
} | ||
if (this._finalized) throw new Error('Digest already called'); | ||
if (!Buffer.isBuffer(data)) data = Buffer.from(data, encoding); | ||
|
||
this._state.absorb(data); | ||
|
||
return this; | ||
} | ||
|
||
digest(encoding) { | ||
if (this._finalized) throw new Error('Digest already called'); | ||
this._finalized = true; | ||
|
||
if (this._delimitedSuffix) { this._state.absorbLastFewBits(this._delimitedSuffix); } | ||
let digest = this._state.squeeze(this._hashBitLength / 8); | ||
if (encoding !== undefined) digest = digest.toString(encoding); | ||
|
||
this._resetState(); | ||
|
||
return digest; | ||
} | ||
|
||
// remove result from memory | ||
_resetState() { | ||
this._state.initialize(this._rate, this._capacity); | ||
return this; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
const createKeccak = require('./api'); | ||
const KeccakState = require('./keccak'); | ||
|
||
const keccak = bits => str => { | ||
let msg; | ||
if (str.slice(0, 2) === '0x') { | ||
msg = []; | ||
for (let i = 2, l = str.length; i < l; i += 2) { msg.push(parseInt(str.slice(i, i + 2), 16)); } | ||
msg = Buffer.from(msg); | ||
} else { | ||
msg = str; | ||
} | ||
let instance; | ||
const Keccak = createKeccak(KeccakState); | ||
if (bits === 256) { | ||
instance = new Keccak(1088, 512, null, 256); | ||
} else { | ||
instance = new Keccak(576, 1024, null, 512); | ||
} | ||
return `0x${instance.update(msg).digest('hex')}`; | ||
}; | ||
|
||
export const keccak256 = keccak(256); | ||
export const keccak512 = keccak(512); | ||
export const keccak256s = keccak(256); | ||
export const keccak512s = keccak(512); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
/* eslint-disable no-param-reassign */ | ||
const P1600_ROUND_CONSTANTS = [ | ||
1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, | ||
2147483649, 0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, | ||
2147516425, 0, 2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, | ||
2147483648, 32771, 2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, | ||
2147483658, 2147483648, 2147516545, 2147483648, 32896, 2147483648, 2147483649, | ||
0, 2147516424, 2147483648, | ||
]; | ||
|
||
const keccakState = { | ||
p1600(s) { | ||
for (let round = 0; round < 24; ++round) { | ||
// theta | ||
const lo0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40]; | ||
const hi0 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41]; | ||
const lo1 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42]; | ||
const hi1 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43]; | ||
const lo2 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44]; | ||
const hi2 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45]; | ||
const lo3 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46]; | ||
const hi3 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47]; | ||
const lo4 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48]; | ||
const hi4 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49]; | ||
|
||
let lo = lo4 ^ ((lo1 << 1) | (hi1 >>> 31)); | ||
let hi = hi4 ^ ((hi1 << 1) | (lo1 >>> 31)); | ||
const t1slo0 = s[0] ^ lo; | ||
const t1shi0 = s[1] ^ hi; | ||
const t1slo5 = s[10] ^ lo; | ||
const t1shi5 = s[11] ^ hi; | ||
const t1slo10 = s[20] ^ lo; | ||
const t1shi10 = s[21] ^ hi; | ||
const t1slo15 = s[30] ^ lo; | ||
const t1shi15 = s[31] ^ hi; | ||
const t1slo20 = s[40] ^ lo; | ||
const t1shi20 = s[41] ^ hi; | ||
lo = lo0 ^ ((lo2 << 1) | (hi2 >>> 31)); | ||
hi = hi0 ^ ((hi2 << 1) | (lo2 >>> 31)); | ||
const t1slo1 = s[2] ^ lo; | ||
const t1shi1 = s[3] ^ hi; | ||
const t1slo6 = s[12] ^ lo; | ||
const t1shi6 = s[13] ^ hi; | ||
const t1slo11 = s[22] ^ lo; | ||
const t1shi11 = s[23] ^ hi; | ||
const t1slo16 = s[32] ^ lo; | ||
const t1shi16 = s[33] ^ hi; | ||
const t1slo21 = s[42] ^ lo; | ||
const t1shi21 = s[43] ^ hi; | ||
lo = lo1 ^ ((lo3 << 1) | (hi3 >>> 31)); | ||
hi = hi1 ^ ((hi3 << 1) | (lo3 >>> 31)); | ||
const t1slo2 = s[4] ^ lo; | ||
const t1shi2 = s[5] ^ hi; | ||
const t1slo7 = s[14] ^ lo; | ||
const t1shi7 = s[15] ^ hi; | ||
const t1slo12 = s[24] ^ lo; | ||
const t1shi12 = s[25] ^ hi; | ||
const t1slo17 = s[34] ^ lo; | ||
const t1shi17 = s[35] ^ hi; | ||
const t1slo22 = s[44] ^ lo; | ||
const t1shi22 = s[45] ^ hi; | ||
lo = lo2 ^ ((lo4 << 1) | (hi4 >>> 31)); | ||
hi = hi2 ^ ((hi4 << 1) | (lo4 >>> 31)); | ||
const t1slo3 = s[6] ^ lo; | ||
const t1shi3 = s[7] ^ hi; | ||
const t1slo8 = s[16] ^ lo; | ||
const t1shi8 = s[17] ^ hi; | ||
const t1slo13 = s[26] ^ lo; | ||
const t1shi13 = s[27] ^ hi; | ||
const t1slo18 = s[36] ^ lo; | ||
const t1shi18 = s[37] ^ hi; | ||
const t1slo23 = s[46] ^ lo; | ||
const t1shi23 = s[47] ^ hi; | ||
lo = lo3 ^ ((lo0 << 1) | (hi0 >>> 31)); | ||
hi = hi3 ^ ((hi0 << 1) | (lo0 >>> 31)); | ||
const t1slo4 = s[8] ^ lo; | ||
const t1shi4 = s[9] ^ hi; | ||
const t1slo9 = s[18] ^ lo; | ||
const t1shi9 = s[19] ^ hi; | ||
const t1slo14 = s[28] ^ lo; | ||
const t1shi14 = s[29] ^ hi; | ||
const t1slo19 = s[38] ^ lo; | ||
const t1shi19 = s[39] ^ hi; | ||
const t1slo24 = s[48] ^ lo; | ||
const t1shi24 = s[49] ^ hi; | ||
|
||
// rho & pi | ||
const t2slo0 = t1slo0; | ||
const t2shi0 = t1shi0; | ||
const t2slo16 = (t1shi5 << 4) | (t1slo5 >>> 28); | ||
const t2shi16 = (t1slo5 << 4) | (t1shi5 >>> 28); | ||
const t2slo7 = (t1slo10 << 3) | (t1shi10 >>> 29); | ||
const t2shi7 = (t1shi10 << 3) | (t1slo10 >>> 29); | ||
const t2slo23 = (t1shi15 << 9) | (t1slo15 >>> 23); | ||
const t2shi23 = (t1slo15 << 9) | (t1shi15 >>> 23); | ||
const t2slo14 = (t1slo20 << 18) | (t1shi20 >>> 14); | ||
const t2shi14 = (t1shi20 << 18) | (t1slo20 >>> 14); | ||
const t2slo10 = (t1slo1 << 1) | (t1shi1 >>> 31); | ||
const t2shi10 = (t1shi1 << 1) | (t1slo1 >>> 31); | ||
const t2slo1 = (t1shi6 << 12) | (t1slo6 >>> 20); | ||
const t2shi1 = (t1slo6 << 12) | (t1shi6 >>> 20); | ||
const t2slo17 = (t1slo11 << 10) | (t1shi11 >>> 22); | ||
const t2shi17 = (t1shi11 << 10) | (t1slo11 >>> 22); | ||
const t2slo8 = (t1shi16 << 13) | (t1slo16 >>> 19); | ||
const t2shi8 = (t1slo16 << 13) | (t1shi16 >>> 19); | ||
const t2slo24 = (t1slo21 << 2) | (t1shi21 >>> 30); | ||
const t2shi24 = (t1shi21 << 2) | (t1slo21 >>> 30); | ||
const t2slo20 = (t1shi2 << 30) | (t1slo2 >>> 2); | ||
const t2shi20 = (t1slo2 << 30) | (t1shi2 >>> 2); | ||
const t2slo11 = (t1slo7 << 6) | (t1shi7 >>> 26); | ||
const t2shi11 = (t1shi7 << 6) | (t1slo7 >>> 26); | ||
const t2slo2 = (t1shi12 << 11) | (t1slo12 >>> 21); | ||
const t2shi2 = (t1slo12 << 11) | (t1shi12 >>> 21); | ||
const t2slo18 = (t1slo17 << 15) | (t1shi17 >>> 17); | ||
const t2shi18 = (t1shi17 << 15) | (t1slo17 >>> 17); | ||
const t2slo9 = (t1shi22 << 29) | (t1slo22 >>> 3); | ||
const t2shi9 = (t1slo22 << 29) | (t1shi22 >>> 3); | ||
const t2slo5 = (t1slo3 << 28) | (t1shi3 >>> 4); | ||
const t2shi5 = (t1shi3 << 28) | (t1slo3 >>> 4); | ||
const t2slo21 = (t1shi8 << 23) | (t1slo8 >>> 9); | ||
const t2shi21 = (t1slo8 << 23) | (t1shi8 >>> 9); | ||
const t2slo12 = (t1slo13 << 25) | (t1shi13 >>> 7); | ||
const t2shi12 = (t1shi13 << 25) | (t1slo13 >>> 7); | ||
const t2slo3 = (t1slo18 << 21) | (t1shi18 >>> 11); | ||
const t2shi3 = (t1shi18 << 21) | (t1slo18 >>> 11); | ||
const t2slo19 = (t1shi23 << 24) | (t1slo23 >>> 8); | ||
const t2shi19 = (t1slo23 << 24) | (t1shi23 >>> 8); | ||
const t2slo15 = (t1slo4 << 27) | (t1shi4 >>> 5); | ||
const t2shi15 = (t1shi4 << 27) | (t1slo4 >>> 5); | ||
const t2slo6 = (t1slo9 << 20) | (t1shi9 >>> 12); | ||
const t2shi6 = (t1shi9 << 20) | (t1slo9 >>> 12); | ||
const t2slo22 = (t1shi14 << 7) | (t1slo14 >>> 25); | ||
const t2shi22 = (t1slo14 << 7) | (t1shi14 >>> 25); | ||
const t2slo13 = (t1slo19 << 8) | (t1shi19 >>> 24); | ||
const t2shi13 = (t1shi19 << 8) | (t1slo19 >>> 24); | ||
const t2slo4 = (t1slo24 << 14) | (t1shi24 >>> 18); | ||
const t2shi4 = (t1shi24 << 14) | (t1slo24 >>> 18); | ||
|
||
// chi | ||
s[0] = t2slo0 ^ (~t2slo1 & t2slo2); | ||
s[1] = t2shi0 ^ (~t2shi1 & t2shi2); | ||
s[10] = t2slo5 ^ (~t2slo6 & t2slo7); | ||
s[11] = t2shi5 ^ (~t2shi6 & t2shi7); | ||
s[20] = t2slo10 ^ (~t2slo11 & t2slo12); | ||
s[21] = t2shi10 ^ (~t2shi11 & t2shi12); | ||
s[30] = t2slo15 ^ (~t2slo16 & t2slo17); | ||
s[31] = t2shi15 ^ (~t2shi16 & t2shi17); | ||
s[40] = t2slo20 ^ (~t2slo21 & t2slo22); | ||
s[41] = t2shi20 ^ (~t2shi21 & t2shi22); | ||
s[2] = t2slo1 ^ (~t2slo2 & t2slo3); | ||
s[3] = t2shi1 ^ (~t2shi2 & t2shi3); | ||
s[12] = t2slo6 ^ (~t2slo7 & t2slo8); | ||
s[13] = t2shi6 ^ (~t2shi7 & t2shi8); | ||
s[22] = t2slo11 ^ (~t2slo12 & t2slo13); | ||
s[23] = t2shi11 ^ (~t2shi12 & t2shi13); | ||
s[32] = t2slo16 ^ (~t2slo17 & t2slo18); | ||
s[33] = t2shi16 ^ (~t2shi17 & t2shi18); | ||
s[42] = t2slo21 ^ (~t2slo22 & t2slo23); | ||
s[43] = t2shi21 ^ (~t2shi22 & t2shi23); | ||
s[4] = t2slo2 ^ (~t2slo3 & t2slo4); | ||
s[5] = t2shi2 ^ (~t2shi3 & t2shi4); | ||
s[14] = t2slo7 ^ (~t2slo8 & t2slo9); | ||
s[15] = t2shi7 ^ (~t2shi8 & t2shi9); | ||
s[24] = t2slo12 ^ (~t2slo13 & t2slo14); | ||
s[25] = t2shi12 ^ (~t2shi13 & t2shi14); | ||
s[34] = t2slo17 ^ (~t2slo18 & t2slo19); | ||
s[35] = t2shi17 ^ (~t2shi18 & t2shi19); | ||
s[44] = t2slo22 ^ (~t2slo23 & t2slo24); | ||
s[45] = t2shi22 ^ (~t2shi23 & t2shi24); | ||
s[6] = t2slo3 ^ (~t2slo4 & t2slo0); | ||
s[7] = t2shi3 ^ (~t2shi4 & t2shi0); | ||
s[16] = t2slo8 ^ (~t2slo9 & t2slo5); | ||
s[17] = t2shi8 ^ (~t2shi9 & t2shi5); | ||
s[26] = t2slo13 ^ (~t2slo14 & t2slo10); | ||
s[27] = t2shi13 ^ (~t2shi14 & t2shi10); | ||
s[36] = t2slo18 ^ (~t2slo19 & t2slo15); | ||
s[37] = t2shi18 ^ (~t2shi19 & t2shi15); | ||
s[46] = t2slo23 ^ (~t2slo24 & t2slo20); | ||
s[47] = t2shi23 ^ (~t2shi24 & t2shi20); | ||
s[8] = t2slo4 ^ (~t2slo0 & t2slo1); | ||
s[9] = t2shi4 ^ (~t2shi0 & t2shi1); | ||
s[18] = t2slo9 ^ (~t2slo5 & t2slo6); | ||
s[19] = t2shi9 ^ (~t2shi5 & t2shi6); | ||
s[28] = t2slo14 ^ (~t2slo10 & t2slo11); | ||
s[29] = t2shi14 ^ (~t2shi10 & t2shi11); | ||
s[38] = t2slo19 ^ (~t2slo15 & t2slo16); | ||
s[39] = t2shi19 ^ (~t2shi15 & t2shi16); | ||
s[48] = t2slo24 ^ (~t2slo20 & t2slo21); | ||
s[49] = t2shi24 ^ (~t2shi20 & t2shi21); | ||
|
||
// iota | ||
s[0] ^= P1600_ROUND_CONSTANTS[round * 2]; | ||
s[1] ^= P1600_ROUND_CONSTANTS[round * 2 + 1]; | ||
} | ||
}, | ||
}; | ||
|
||
function Keccak() { | ||
// much faster than `new Array(50)` | ||
this.state = [ | ||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
]; | ||
|
||
this.blockSize = null; | ||
this.count = 0; | ||
this.squeezing = false; | ||
} | ||
|
||
Keccak.prototype.initialize = function (rate) { | ||
for (let i = 0; i < 50; ++i) this.state[i] = 0; | ||
this.blockSize = rate / 8; | ||
this.count = 0; | ||
this.squeezing = false; | ||
}; | ||
|
||
Keccak.prototype.absorb = function (data) { | ||
for (let i = 0; i < data.length; ++i) { | ||
this.state[~~(this.count / 4)] ^= data[i] << (8 * (this.count % 4)); | ||
this.count += 1; | ||
if (this.count === this.blockSize) { | ||
keccakState.p1600(this.state); | ||
this.count = 0; | ||
} | ||
} | ||
}; | ||
|
||
Keccak.prototype.absorbLastFewBits = function (bits) { | ||
this.state[~~(this.count / 4)] ^= bits << (8 * (this.count % 4)); | ||
if ((bits & 0x80) !== 0 && this.count === this.blockSize - 1) { | ||
keccakState.p1600(this.state); | ||
} | ||
this.state[~~((this.blockSize - 1) / 4)] | ||
^= 0x80 << (8 * ((this.blockSize - 1) % 4)); | ||
keccakState.p1600(this.state); | ||
this.count = 0; | ||
this.squeezing = true; | ||
}; | ||
|
||
Keccak.prototype.squeeze = function (length) { | ||
if (!this.squeezing) this.absorbLastFewBits(0x01); | ||
|
||
const output = Buffer.alloc(length); | ||
for (let i = 0; i < length; ++i) { | ||
output[i] = (this.state[~~(this.count / 4)] >>> (8 * (this.count % 4))) & 0xff; | ||
this.count += 1; | ||
if (this.count === this.blockSize) { | ||
keccakState.p1600(this.state); | ||
this.count = 0; | ||
} | ||
} | ||
|
||
return output; | ||
}; | ||
|
||
module.exports = Keccak; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.