c11-hash-js
Version:
c11 javascript hashing algorithm in pure javascript
492 lines (467 loc) • 15.8 kB
JavaScript
/////////////////////////////////////
/////////////// Jh /////////////////
//// Written by Quantum Explorer ////
////////// Dash Foundation //////////
/// Released under the MIT License //
/////////////////////////////////////
var op = require('./op');
var he = require('./helper');
var Jh_BlockSize = 64;
var Jh_StateSize = 32;
var JH_HX = 8;
var JH_HY = 4;
var IV512 = he.bytes2Int32Buffer(he.b64Decode("b9FLlj4Aqhdjai4FehXVQ4oiXo0Ml+8L6TQSWfKzw2GJHaDBU2+AHiqpBWvqK22AWI7M2yB1uqapDzp2uvg79wFp5gVB40ppRrWKji5v5loQR6fQwYQ8JDtucbEtWsGZz1f27J2x+FanBoh8VxaxVuPC/N/mhRf7VFpGeMyM3Us="));
var C = he.bytes2Int32Buffer(he.b64Decode("ot7Vcmf4Fd8KFYR7VxUjt5DWq4H2h1pNxU+fTkAr0cPgOpjqnPpFXJnSxQOambJmtJYCZopTu/IaFFa1MaLbiFxaowPbDhmaCrI/QBBEwYeAGQUcHZWehK3rM2/czedekhO6EEFrvwIVZXjc0Ce79zmBLApQeKo30r8aP9ORAEENWi1CkH7M9pyfYt3Ol8CSC6dcGKxEK8fWZd/RI/zGYwNsbpcauOCefkUFIajsbES7A/Hu+mGOXbKXlv2XgYOUN4WOSi8wA9stjWcqlWqf+4Fz/opsabj4RnLHihRCf8CPFfTFxF7HvadvRHWAuxGPt3XeUryI5K4eALiC9KOmmDOP9I4VY6OpJFZfqon5t9Ug7fG2/eBafFrpyjY2LEIGQzUpzj2Y/k50+TpTp0uac1kf9dCGgU5vga2dDp9a2K9nBgWnamI07r4oC4snF7luJgd0Rz8QgMZvfqDge0h+xqUKVQ3ApPhKn+fjkZ7xjpeBcnaG1I1gUEFann5isOXz7B+f/HogVEAAGuTjhMn0zvWU10/YlfqdEX4uVaVUwyQoct9bKG7+veJ/9XiyxKUP73yJBS7TSe6Fk35Ef1ko6zdpX3BKMSSz8SiGXmXk1h0EdxvH5yC5UehD/nSKh9Qjo+gpffKUdpIJesvdwdkwm/swGx3gG9xbT0kk2r+CnPIxuuek/79wtAVEMg1IvPjeMvyuOznTu1PBw59FoIsp4P0FyeUPCa73EjRwlDTxkEIBt3Gile1E4zaOO+lKmC9PYx1AiBX2bKBLRMFH/69Sh/FKu34wxgrixbZwRuaMbsxWpNWkAMpPvUuEndquGD7IRc5Xc63RZDBozqboZyVcFPKM2qMW4Q7LWAbpM5qZlJogsmAfe4Rvwn+sztEYhdGgoVtZMtMZ3Y3AHJpQRrSlqmdjPZ+6awTkqxnK9n7uVgvqebEfdCEoqTX3venuUTY7WqxXHXbTUHX+wkY6AXB9o6/BNfdC2KSYIOzteHlna54VY4NBqNs66k07w/qDLIMyHztAp/NHJxw08EBZmnYtt2xOPuf9TyHSOY39uO9ZV9xJDJuN2utJK0nXolsNcPNo0K47fYRVjXrw6aX1ZY745PSiuKBTOxA2ngeoDFrsPnWSlGiRT4joVlVcsFtMvLr4mTu743uUh/PW9Np1XRxrciisrmRtszTcUKU0bHHbKLjy4mH4KlGNEDNk2+P8dd1Z8bysHKI/zkM80btnsEPoAspbCjN1oSmITRk0f1xTFrTDlDuSHk15Dtd1dHk/r+6299So6iE5Gr4JfvRcUScjTFMkoybSPDK6ShejRK3Vpm2mPh21CMnyr5g9WYNWPGuRoXz4TE1ghnLMPuJG9sduCLMzmC9edryxpWbWKyrmxO/otvQGNtTBvhWC7nRjIe+8DU7B/WnJU/TEWn2nJlhYBhYUwX4W+uAGPa+Qfj+dYyjj8snSDNKbADDOql8wDNS3FlEqdJgy4PLYMOsNmvjO43uexUuSefG1buZR/9NohgRXTSObMWeW5vOm5swFdQoX2YF2sc5sMhOEUhc8YqIF+LPLK/RHFUd4glRG/0hqkyMHWN84ZWVeTol8/PKOUIb8RC5wMYbKC9CiCUDwTkd4MDnuoGWDOPfRN+le9706LOQmspchb/gTAdHtRKPn3p/vFd+gi9mSJXb294U8vkLcEnzsp9h+sCer2n2NU96oPqqTziWq2GkCvf1D9lr5CHMa2u9fwKUZShczZk2XaiH9TDGYtDVwFUHbuw8e6ptUze2hY9CackCXUb+ddfbib0eR"));
// var IV512 = [
// (0x6fd14b96), (0x3e00aa17), (0x636a2e05), (0x7a15d543),
// (0x8a225e8d), (0x0c97ef0b), (0xe9341259), (0xf2b3c361),
// (0x891da0c1), (0x536f801e), (0x2aa9056b), (0xea2b6d80),
// (0x588eccdb), (0x2075baa6), (0xa90f3a76), (0xbaf83bf7),
// (0x0169e605), (0x41e34a69), (0x46b58a8e), (0x2e6fe65a),
// (0x1047a7d0), (0xc1843c24), (0x3b6e71b1), (0x2d5ac199),
// (0xcf57f6ec), (0x9db1f856), (0xa706887c), (0x5716b156),
// (0xe3c2fcdf), (0xe68517fb), (0x545a4678), (0xcc8cdd4b)
// ];
//C would need to be 32 bit swapped if using these values
// var C = [
// (0x72d5dea2), (0xdf15f867), (0x7b84150a),
// (0xb7231557), (0x81abd690), (0x4d5a87f6),
// (0x4e9f4fc5), (0xc3d12b40), (0xea983ae0),
// (0x5c45fa9c), (0x03c5d299), (0x66b2999a),
// (0x660296b4), (0xf2bb538a), (0xb556141a),
// (0x88dba231), (0x03a35a5c), (0x9a190edb),
// (0x403fb20a), (0x87c14410), (0x1c051980),
// (0x849e951d), (0x6f33ebad), (0x5ee7cddc),
// (0x10ba1392), (0x02bf6b41), (0xdc786515),
// (0xf7bb27d0), (0x0a2c8139), (0x37aa7850),
// (0x3f1abfd2), (0x410091d3), (0x422d5a0d),
// (0xf6cc7e90), (0xdd629f9c), (0x92c097ce),
// (0x185ca70b), (0xc72b44ac), (0xd1df65d6),
// (0x63c6fc23), (0x976e6c03), (0x9ee0b81a),
// (0x2105457e), (0x446ceca8), (0xeef103bb),
// (0x5d8e61fa), (0xfd9697b2), (0x94838197),
// (0x4a8e8537), (0xdb03302f), (0x2a678d2d),
// (0xfb9f6a95), (0x8afe7381), (0xf8b8696c),
// (0x8ac77246), (0xc07f4214), (0xc5f4158f),
// (0xbdc75ec4), (0x75446fa7), (0x8f11bb80),
// (0x52de75b7), (0xaee488bc), (0x82b8001e),
// (0x98a6a3f4), (0x8ef48f33), (0xa9a36315),
// (0xaa5f5624), (0xd5b7f989), (0xb6f1ed20),
// (0x7c5ae0fd), (0x36cae95a), (0x06422c36),
// (0xce293543), (0x4efe983d), (0x533af974),
// (0x739a4ba7), (0xd0f51f59), (0x6f4e8186),
// (0x0e9dad81), (0xafd85a9f), (0xa7050667),
// (0xee34626a), (0x8b0b28be), (0x6eb91727),
// (0x47740726), (0xc680103f), (0xe0a07e6f),
// (0xc67e487b), (0x0d550aa5), (0x4af8a4c0),
// (0x91e3e79f), (0x978ef19e), (0x86767281),
// (0x50608dd4), (0x7e9e5a41), (0xf3e5b062),
// (0xfc9f1fec), (0x4054207a), (0xe3e41a00),
// (0xcef4c984), (0x4fd794f5), (0x9dfa95d8),
// (0x552e7e11), (0x24c354a5), (0x5bdf7228),
// (0xbdfe6e28), (0x78f57fe2), (0x0fa5c4b2),
// (0x05897cef), (0xee49d32e), (0x447e9385),
// (0xeb28597f), (0x705f6937), (0xb324314a),
// (0x5e8628f1), (0x1dd6e465), (0xc71b7704),
// (0x51b920e7), (0x74fe43e8), (0x23d4878a),
// (0x7d29e8a3), (0x927694f2), (0xddcb7a09),
// (0x9b30d9c1), (0x1d1b30fb), (0x5bdc1be0),
// (0xda24494f), (0xf29c82bf), (0xa4e7ba31),
// (0xb470bfff), (0x0d324405), (0xdef8bc48),
// (0x3baefc32), (0x53bbd339), (0x459fc3c1),
// (0xe0298ba0), (0xe5c905fd), (0xf7ae090f),
// (0x94703412), (0x4290f134), (0xa271b701),
// (0xe344ed95), (0xe93b8e36), (0x4f2f984a),
// (0x88401d63), (0xa06cf615), (0x47c1444b),
// (0x8752afff), (0x7ebb4af1), (0xe20ac630),
// (0x4670b6c5), (0xcc6e8ce6), (0xa4d5a456),
// (0xbd4fca00), (0xda9d844b), (0xc83e18ae),
// (0x7357ce45), (0x3064d1ad), (0xe8a6ce68),
// (0x145c2567), (0xa3da8cf2), (0xcb0ee116),
// (0x33e90658), (0x9a94999a), (0x1f60b220),
// (0xc26f847b), (0xd1ceac7f), (0xa0d18518),
// (0x32595ba1), (0x8ddd19d3), (0x509a1cc0),
// (0xaaa5b446), (0x9f3d6367), (0xe4046bba),
// (0xf6ca19ab), (0x0b56ee7e), (0x1fb179ea),
// (0xa9282174), (0xe9bdf735), (0x3b3651ee),
// (0x1d57ac5a), (0x7550d376), (0x3a46c2fe),
// (0xa37d7001), (0xf735c1af), (0x98a4d842),
// (0x78edec20), (0x9e6b6779), (0x41836315),
// (0xea3adba8), (0xfac33b4d), (0x32832c83),
// (0xa7403b1f), (0x1c2747f3), (0x5940f034),
// (0xb72d769a), (0xe73e4e6c), (0xd2214ffd),
// (0xb8fd8d39), (0xdc5759ef), (0x8d9b0c49),
// (0x2b49ebda), (0x5ba2d749), (0x68f3700d),
// (0x7d3baed0), (0x7a8d5584), (0xf5a5e9f0),
// (0xe4f88e65), (0xa0b8a2f4), (0x36103b53),
// (0x0ca8079e), (0x753eec5a), (0x91689492),
// (0x56e8884f), (0x5bb05c55), (0xf8babc4c),
// (0xe3bb3b99), (0xf387947b), (0x75daf4d6),
// (0x726b1c5d), (0x64aeac28), (0xdc34b36d),
// (0x6c34a550), (0xb828db71), (0xf861e2f2),
// (0x108d512a), (0xe3db6433), (0x59dd75fc),
// (0x1cacbcf1), (0x43ce3fa2), (0x67bbd13c),
// (0x02e843b0), (0x330a5bca), (0x8829a175),
// (0x7f34194d), (0xb416535c), (0x923b94c3),
// (0x0e794d1e), (0x797475d7), (0xb6eeaf3f),
// (0xeaa8d4f7), (0xbe1a3921), (0x5cf47e09),
// (0x4c232751), (0x26a32453), (0xba323cd2),
// (0x44a3174a), (0x6da6d5ad), (0xb51d3ea6),
// (0xaff2c908), (0x83593d98), (0x916b3c56),
// (0x4cf87ca1), (0x7286604d), (0x46e23ecc),
// (0x086ec7f6), (0x2f9833b3), (0xb1bc765e),
// (0x2bd666a5), (0xefc4e62a), (0x06f4b6e8),
// (0xbec1d436), (0x74ee8215), (0xbcef2163),
// (0xfdc14e0d), (0xf453c969), (0xa77d5ac4),
// (0x06585826), (0x7ec11416), (0x06e0fa16),
// (0x7e90af3d), (0x28639d3f), (0xd2c9f2e3),
// (0x009bd20c), (0x5faace30), (0xb7d40c30),
// (0x742a5116), (0xf2e03298), (0x0deb30d8),
// (0xe3cef89a), (0x4bc59e7b), (0xb5f17992),
// (0xff51e66e), (0x048668d3), (0x9b234d57),
// (0xe6966731), (0xcce6a6f3), (0x170a7505),
// (0xb17681d9), (0x13326cce), (0x3c175284),
// (0xf805a262), (0xf42bcbb3), (0x78471547),
// (0xff465482), (0x23936a48), (0x38df5807),
// (0x4e5e6565), (0xf2fc7c89), (0xfc86508e),
// (0x31702e44), (0xd00bca86), (0xf04009a2),
// (0x3078474e), (0x65a0ee39), (0xd1f73883),
// (0xf75ee937), (0xe42c3abd), (0x2197b226),
// (0x0113f86f), (0xa344edd1), (0xef9fdee7),
// (0x8ba0df15), (0x762592d9), (0x3c85f7f6),
// (0x12dc42be), (0xd8a7ec7c), (0xab27b07e),
// (0x538d7dda), (0xaa3ea8de), (0xaa25ce93),
// (0xbd0269d8), (0x5af643fd), (0x1a7308f9),
// (0xc05fefda), (0x174a19a5), (0x974d6633),
// (0x4cfd216a), (0x35b49831), (0xdb411570),
// (0xea1e0fbb), (0xedcd549b), (0x9ad063a1),
// (0x51974072), (0xf6759dbf), (0x91476fe2)
// ];
var Sb = function(x, c) {
x[3] = ~x[3];
x[0] ^= (c) & ~x[2];
var tmp = (c) ^ (x[0] & x[1]);
x[0] ^= x[2] & x[3];
x[3] ^= ~x[1] & x[2];
x[1] ^= x[0] & x[2];
x[2] ^= x[0] & ~x[3];
x[0] ^= x[1] | x[3];
x[3] ^= x[1] & x[2];
x[1] ^= tmp & x[0];
x[2] ^= tmp;
return x;
}
var Lb = function(x) {
x[4] ^= x[1];
x[5] ^= x[2];
x[6] ^= x[3] ^ x[0];
x[7] ^= x[0];
x[0] ^= x[5];
x[1] ^= x[6];
x[2] ^= x[7] ^ x[4];
x[3] ^= x[4];
return x;
}
var Ceven = function(n, r) {
return C[((r) << 3) + 3 - n];
}
var Codd = function(n, r) {
return C[((r) << 3) + 7 - n];
}
var S = function(x0, x1, x2, x3, cb, r) {
var x = Sb([x0[3], x1[3], x2[3], x3[3]], cb(3, r));
x0[3] = x[0];
x1[3] = x[1];
x2[3] = x[2];
x3[3] = x[3];
x = Sb([x0[2], x1[2], x2[2], x3[2]], cb(2, r));
x0[2] = x[0];
x1[2] = x[1];
x2[2] = x[2];
x3[2] = x[3];
x = Sb([x0[1], x1[1], x2[1], x3[1]], cb(1, r));
x0[1] = x[0];
x1[1] = x[1];
x2[1] = x[2];
x3[1] = x[3];
x = Sb([x0[0], x1[0], x2[0], x3[0]], cb(0, r));
x0[0] = x[0];
x1[0] = x[1];
x2[0] = x[2];
x3[0] = x[3];
}
var L = function(x0, x1, x2, x3, x4, x5, x6, x7) {
var x = Lb([x0[3], x1[3], x2[3], x3[3], x4[3], x5[3], x6[3], x7[3]]);
x0[3] = x[0];
x1[3] = x[1];
x2[3] = x[2];
x3[3] = x[3];
x4[3] = x[4];
x5[3] = x[5];
x6[3] = x[6];
x7[3] = x[7];
x = Lb([x0[2], x1[2], x2[2], x3[2], x4[2], x5[2], x6[2], x7[2]]);
x0[2] = x[0];
x1[2] = x[1];
x2[2] = x[2];
x3[2] = x[3];
x4[2] = x[4];
x5[2] = x[5];
x6[2] = x[6];
x7[2] = x[7];
x = Lb([x0[1], x1[1], x2[1], x3[1], x4[1], x5[1], x6[1], x7[1]]);
x0[1] = x[0];
x1[1] = x[1];
x2[1] = x[2];
x3[1] = x[3];
x4[1] = x[4];
x5[1] = x[5];
x6[1] = x[6];
x7[1] = x[7];
x = Lb([x0[0], x1[0], x2[0], x3[0], x4[0], x5[0], x6[0], x7[0]]);
x0[0] = x[0];
x1[0] = x[1];
x2[0] = x[2];
x3[0] = x[3];
x4[0] = x[4];
x5[0] = x[5];
x6[0] = x[6];
x7[0] = x[7];
}
var Wz = function(x, c, n) {
var t = (x[3] & (c)) << (n);
x[3] = ((x[3] >> (n)) & (c)) | t;
t = (x[2] & (c)) << (n);
x[2] = ((x[2] >> (n)) & (c)) | t;
t = (x[1] & (c)) << (n);
x[1] = ((x[1] >> (n)) & (c)) | t;
t = (x[0] & (c)) << (n);
x[0] = ((x[0] >> (n)) & (c)) | t;
}
var W = function(ro, x) {
switch (ro) {
case 0:
return Wz(x, (0x55555555), 1);
case 1:
return Wz(x, (0x33333333), 2);
case 2:
return Wz(x, (0x0F0F0F0F), 4);
case 3:
return Wz(x, (0x00FF00FF), 8);
case 4:
return Wz(x, (0x0000FFFF), 16);
case 5:
{
var t = x[3];
x[3] = x[2];
x[2] = t;
t = x[1];
x[1] = x[0];
x[0] = t;
return;
}
case 6:
{
var t = x[3];
x[3] = x[1];
x[1] = t;
t = x[2];
x[2] = x[0];
x[0] = t;
return;
}
}
}
var SL = function(h, r, ro) {
S(h[0], h[2], h[4], h[6], Ceven, r);
S(h[1], h[3], h[5], h[7], Codd, r);
L(h[0], h[2], h[4], h[6], h[1], h[3], h[5], h[7]);
W(ro, h[1]);
W(ro, h[3]);
W(ro, h[5]);
W(ro, h[7]);
}
var READ_STATE = function(h, state) {
h[0][3] = state[0];
h[0][2] = state[1];
h[0][1] = state[2];
h[0][0] = state[3];
h[1][3] = state[4];
h[1][2] = state[5];
h[1][1] = state[6];
h[1][0] = state[7];
h[2][3] = state[8];
h[2][2] = state[9];
h[2][1] = state[10];
h[2][0] = state[11];
h[3][3] = state[12];
h[3][2] = state[13];
h[3][1] = state[14];
h[3][0] = state[15];
h[4][3] = state[16];
h[4][2] = state[17];
h[4][1] = state[18];
h[4][0] = state[19];
h[5][3] = state[20];
h[5][2] = state[21];
h[5][1] = state[22];
h[5][0] = state[23];
h[6][3] = state[24];
h[6][2] = state[25];
h[6][1] = state[26];
h[6][0] = state[27];
h[7][3] = state[28];
h[7][2] = state[29];
h[7][1] = state[30];
h[7][0] = state[31];
}
var WRITE_STATE = function(h, state) {
state[0] = h[0][3];
state[1] = h[0][2];
state[2] = h[0][1];
state[3] = h[0][0];
state[4] = h[1][3];
state[5] = h[1][2];
state[6] = h[1][1];
state[7] = h[1][0];
state[8] = h[2][3];
state[9] = h[2][2];
state[10] = h[2][1];
state[11] = h[2][0];
state[12] = h[3][3];
state[13] = h[3][2];
state[14] = h[3][1];
state[15] = h[3][0];
state[16] = h[4][3];
state[17] = h[4][2];
state[18] = h[4][1];
state[19] = h[4][0];
state[20] = h[5][3];
state[21] = h[5][2];
state[22] = h[5][1];
state[23] = h[5][0];
state[24] = h[6][3];
state[25] = h[6][2];
state[26] = h[6][1];
state[27] = h[6][0];
state[28] = h[7][3];
state[29] = h[7][2];
state[30] = h[7][1];
state[31] = h[7][0];
}
var E8 = function(h) {
for (var r = 0; r < 42; r += 7) {
SL(h, r + 0, 0);
SL(h, r + 1, 1);
SL(h, r + 2, 2);
SL(h, r + 3, 3);
SL(h, r + 4, 4);
SL(h, r + 5, 5);
SL(h, r + 6, 6);
}
}
var bufferXORInsertBackwards = function(buffer, data, x, y, bufferOffsetX, bufferOffsetY) {
if (!bufferOffsetX) bufferOffsetX = 0;
if (!bufferOffsetY) bufferOffsetY = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
var m = i + bufferOffsetX;
var n = bufferOffsetY + y - 1 - j;
var xOr = buffer[m][n] ^ data[i * 4 + j];
buffer[m][n] = xOr;
}
}
}
var jh = function(ctx, data, len) {
var buf, ptr;
//create a local copy of states
buf = ctx.buffer;
ptr = ctx.ptr;
if (!len) len = data.length;
if (len < ctx.buffer.length - ptr) {
op.bufferInsert(buf, ptr, data, data.length);
ptr += data.length;
ctx.ptr = ptr;
return;
}
var V = new Array(JH_HX);
for (var i = 0; i < JH_HX; i++) {
V[i] = new Array(JH_HY);
}
READ_STATE(V, ctx.state);
while (len > 0) {
var clen = ctx.buffer.length - ptr;
if (clen > len) clen = len;
op.bufferInsert(buf, ptr, data, clen);
ptr += clen;
data = data.slice(clen);
len -= clen;
if (ptr === ctx.buffer.length) {
var int32Buf = op.swap32Array(he.bytes2Int32Buffer(buf));
bufferXORInsertBackwards(V, int32Buf, 4, 4);
E8(V);
bufferXORInsertBackwards(V, int32Buf, 4, 4, 4, 0);
if ((ctx.blockCountLow = op.t32(ctx.blockCountLow + 1)) == 0)
ctx.blockCountHigh++;
ptr = 0;
}
}
WRITE_STATE(V, ctx.state);
ctx.ptr = ptr;
}
var jhClose = function(ctx) {
var z;
var buf = new Array(128);
var numz, u;
var l = new Array(4);
buf[0] = 0x80;
if (ctx.ptr == 0) {
numz = 47;
}
else {
numz = 111 - ctx.ptr;
}
op.bufferSet(buf, 1, 0, numz);
l[0] = op.t32(ctx.blockCountLow << 9) + (ctx.ptr << 3);
l[1] = op.t32(ctx.blockCountLow >> 23) + op.t32(ctx.blockCountHigh << 9);
l[2] = op.t32(ctx.blockCountHigh >> 23);
l[3] = 0;
var lBytes = he.int32Buffer2Bytes(op.swap32Array(l));
op.bufferInsertBackwards(buf, 1 + numz, lBytes, 16);
jh(ctx, buf, numz + 17);
var out = new Array(16);
for (u = 0; u < 16; u++)
out[u] = op.swap32(ctx.state[u + 16]);
return out;
}
module.exports = function(input, format, output) {
var msg;
if (format === 1) {
msg = input;
}
else if (format === 2) {
msg = he.int32Buffer2Bytes(input);
}
else {
msg = he.string2bytes(input);
}
var ctx = {};
ctx.state = op.swap32Array(IV512);
ctx.ptr = 0;
ctx.buffer = new Array(Jh_BlockSize);
ctx.blockCountHigh = 0;
ctx.blockCountLow = 0;
jh(ctx, msg);
var r = jhClose(ctx);
var out;
if (output === 2) {
out = r;
}
else if (output === 1) {
out = he.int32Buffer2Bytes(r)
}
else {
out = he.int32ArrayToHexString(r)
}
return out;
}