Last active
June 2, 2019 22:41
-
-
Save dchest/33ec9321a847d25341ca227ea664881a to your computer and use it in GitHub Desktop.
Gimli permutation in JavaScript. EXPERIMENTAL VERSION
This file contains hidden or 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
/** Gimli permutation - https://gimli.cr.yp.to */ | |
function gimli(s) { | |
var r, x, y, z, | |
a = s[ 0] | s[ 1] << 8 | s[ 2] << 16 | s[ 3] << 24, | |
b = s[ 4] | s[ 5] << 8 | s[ 6] << 16 | s[ 7] << 24, | |
c = s[ 8] | s[ 9] << 8 | s[10] << 16 | s[11] << 24, | |
d = s[12] | s[13] << 8 | s[14] << 16 | s[15] << 24, | |
e = s[16] | s[17] << 8 | s[18] << 16 | s[19] << 24, | |
f = s[20] | s[21] << 8 | s[22] << 16 | s[23] << 24, | |
g = s[24] | s[25] << 8 | s[26] << 16 | s[27] << 24, | |
h = s[28] | s[29] << 8 | s[30] << 16 | s[31] << 24, | |
i = s[32] | s[33] << 8 | s[34] << 16 | s[35] << 24, | |
j = s[36] | s[37] << 8 | s[38] << 16 | s[39] << 24, | |
k = s[40] | s[41] << 8 | s[42] << 16 | s[43] << 24, | |
l = s[44] | s[45] << 8 | s[46] << 16 | s[47] << 24; | |
for (r = 24; r > 0; --r) { | |
x = a << 24 | a >>> 8; | |
y = e << 9 | e >>> 23; | |
z = i; | |
i = (y & z) << 2 ^ x ^ z << 1; | |
e = (x | z) << 1 ^ y ^ x; | |
a = (x & y) << 3 ^ z ^ y; | |
x = b << 24 | b >>> 8; | |
y = f << 9 | f >>> 23; | |
z = j; | |
j = (y & z) << 2 ^ x ^ z << 1; | |
f = (x | z) << 1 ^ y ^ x; | |
b = (x & y) << 3 ^ z ^ y; | |
x = c << 24 | c >>> 8; | |
y = g << 9 | g >>> 23; | |
z = k; | |
k = (y & z) << 2 ^ x ^ z << 1; | |
g = (x | z) << 1 ^ y ^ x; | |
c = (x & y) << 3 ^ z ^ y; | |
x = d << 24 | d >>> 8; | |
y = h << 9 | h >>> 23; | |
z = l; | |
l = (y & z) << 2 ^ x ^ z << 1; | |
h = (x | z) << 1 ^ y ^ x; | |
d = (x & y) << 3 ^ z ^ y; | |
if ((r & 3) === 0) { | |
x = a; a = b; b = x; | |
x = c; c = d; d = x; | |
a ^= 0x9e377900 ^ r; | |
} | |
else if ((r & 3) === 2) { | |
x = a; a = c; c = x; | |
x = b; b = d; d = x; | |
} | |
} | |
s[ 0] = a; s[ 1] = a >>> 8; s[ 2] = a >>> 16; s[ 3] = a >>> 24; | |
s[ 4] = b; s[ 5] = b >>> 8; s[ 6] = b >>> 16; s[ 7] = b >>> 24; | |
s[ 8] = c; s[ 9] = c >>> 8; s[10] = c >>> 16; s[11] = c >>> 24; | |
s[12] = d; s[13] = d >>> 8; s[14] = d >>> 16; s[15] = d >>> 24; | |
s[16] = e; s[17] = e >>> 8; s[18] = e >>> 16; s[19] = e >>> 24; | |
s[20] = f; s[21] = f >>> 8; s[22] = f >>> 16; s[23] = f >>> 24; | |
s[24] = g; s[25] = g >>> 8; s[26] = g >>> 16; s[27] = g >>> 24; | |
s[28] = h; s[29] = h >>> 8; s[30] = h >>> 16; s[31] = h >>> 24; | |
s[32] = i; s[33] = i >>> 8; s[34] = i >>> 16; s[35] = i >>> 24; | |
s[36] = j; s[37] = j >>> 8; s[38] = j >>> 16; s[39] = j >>> 24; | |
s[40] = k; s[41] = k >>> 8; s[42] = k >>> 16; s[43] = k >>> 24; | |
s[44] = l; s[45] = l >>> 8; s[46] = l >>> 16; s[47] = l >>> 24; | |
} | |
/* Test and benchmarks */ | |
function test() { | |
var state = new Uint8Array(48); | |
for (var i = 0; i < 50 * 64 * 1024; i++) gimli(state); | |
var r = Buffer.from(state).toString('hex') | |
console.log(r); | |
if (r !== 'f362dcc0f6c36bb7e626a86ac15b7c25b392eb6df277979f40b91b6dc6846079fb7427955d6479a5abe65d477abdee9c') | |
throw new Error('Test failed'); | |
} | |
function bench() { | |
var begin = Date.now(); | |
var times = 50 * 64 * 1024; | |
var state = new Uint8Array(48); | |
for (var i = 0; i < times; i++) gimli(state); | |
var diff = Date.now() - begin; | |
console.log(diff + 'ms per ' + times + ' ops') | |
console.log('rate: 128', 50 * 1000 / diff + ' MiB/s'); | |
console.log('rate:full', 50 * 1000 * 3 / diff + ' MiB/s'); | |
} | |
bench(); | |
test(); | |
/** | |
2.6 GHz Intel Core i5, Node v8.1.3 | |
935ms per 3276800 ops | |
rate: 128 53.475935828877006 MiB/s | |
rate:full 160.42780748663102 MiB/s | |
f362dcc0f6c36bb7e626a86ac15b7c25b392eb6df277979f40b91b6dc6846079fb7427955d6479a5abe65d477abdee9c | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See https://github.com/dchest/gimli-js for release