Skip to content

Instantly share code, notes, and snippets.

@dchest
Last active June 2, 2019 22:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dchest/33ec9321a847d25341ca227ea664881a to your computer and use it in GitHub Desktop.
Save dchest/33ec9321a847d25341ca227ea664881a to your computer and use it in GitHub Desktop.
Gimli permutation in JavaScript. EXPERIMENTAL VERSION
/** 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
*/
@dchest
Copy link
Author

dchest commented Jun 2, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment