ripemd128.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * A pure JavaScript implementation of RIPEMD128 using Uint8Array as input/output.
  3. * By Feng Dihai <fengdh@gmail.com>, 2015/07/09
  4. *
  5. * Based on coiscir/jsdigest (https://github.com/coiscir/jsdigest/blob/master/src/hash/ripemd128.js)
  6. *
  7. * ripemd128.js is free software released under terms of the MIT License.
  8. * You can get a copy on http://opensource.org/licenses/MIT.
  9. *
  10. *
  11. * RIPEMD-128 (c) 1996 Hans Dobbertin, Antoon Bosselaers, and Bart Preneel
  12. */
  13. var ripemd128;
  14. (function() {
  15. // implementation
  16. // convert array of number to Uint32Array
  17. function asUint32Array(arr) {
  18. return new Uint32Array(arr);
  19. }
  20. // concat 2 typed array
  21. function concat(a, b) {
  22. var c = new a.constructor(a.length + b.length);
  23. c.set(a);
  24. c.set(b, a.length);
  25. return c;
  26. }
  27. // swap high and low bits of a 32-bit int.
  28. function rotl( x, n ) {
  29. return ( x >>> ( 32 - n ) ) | ( x << n );
  30. }
  31. var DIGEST = 128,
  32. BLOCK = 64,
  33. S = [
  34. [ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 ], // round 1
  35. [ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 ], // round 2
  36. [ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 ], // round 3
  37. [ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 ], // round 4
  38. [ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 ], // parallel round 1
  39. [ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 ], // parallel round 2
  40. [ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 ], // parallel round 3
  41. [ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 ] // parallel round 4
  42. ].map(asUint32Array),
  43. X = [
  44. [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], // round 1
  45. [ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 ], // round 2
  46. [ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 ], // round 3
  47. [ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 ], // round 4
  48. [ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 ], // parallel round 1
  49. [ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 ], // parallel round 2
  50. [ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 ], // parallel round 3
  51. [ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 ] // parallel round 4
  52. ].map(asUint32Array),
  53. K = asUint32Array([
  54. 0x00000000, // FF
  55. 0x5a827999, // GG
  56. 0x6ed9eba1, // HH
  57. 0x8f1bbcdc, // II
  58. 0x50a28be6, // III
  59. 0x5c4dd124, // HHH
  60. 0x6d703ef3, // GGG
  61. 0x00000000 // FFF
  62. ]),
  63. F = [
  64. function ( x, y, z ) {
  65. return ( x ^ y ^ z );
  66. },
  67. function ( x, y, z ) {
  68. return ( x & y ) | ( ( ~x ) & z );
  69. },
  70. function ( x, y, z ) {
  71. return ( x | ( ~y ) ) ^ z;
  72. },
  73. function ( x, y, z ) {
  74. return ( x & z ) | ( y & ( ~z ) );
  75. }
  76. ];
  77. ripemd128 = function( data ) {
  78. var aa, bb, cc, dd, aaa, bbb, ccc, ddd, i, l, r, rr, t, tmp, x,
  79. hash = new Uint32Array([ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 ]),
  80. bytes = data.length;
  81. var padding = new Uint8Array(( ( bytes % 64 ) < 56 ? 56 : 120 ) - ( bytes % 64 ));
  82. padding[0] = [0x80];
  83. data = new Uint32Array(concat(data, padding).buffer);
  84. // ending with check bits (= little endian 64-bit int, 8 * data.length)
  85. bytes = bytes << 3;
  86. x = concat( data, [bytes, bytes >> 31 >> 1]);
  87. // update hash
  88. for ( i = 0, t = 0, l = x.length; i < l; i += 16, t = 0 ) {
  89. aa = aaa = hash[0];
  90. bb = bbb = hash[1];
  91. cc = ccc = hash[2];
  92. dd = ddd = hash[3];
  93. for ( ; t < 64; ++t ) {
  94. r = ~~( t / 16 );
  95. aa = rotl(aa + F[r]( bb, cc, dd ) + x[ i + X[r][ t % 16 ] ] + K[r], S[r][ t % 16 ]);
  96. tmp = dd;
  97. dd = cc;
  98. cc = bb;
  99. bb = aa;
  100. aa = tmp;
  101. }
  102. for ( ; t < 128; ++t ) {
  103. r = ~~( t / 16 );
  104. rr = ~~( ( 63 - ( t % 64 ) ) / 16 );
  105. aaa = rotl(aaa + F[rr]( bbb, ccc, ddd ) + x[ i + X[r][ t % 16 ] ] + K[r], S[r][ t % 16 ]);
  106. tmp = ddd;
  107. ddd = ccc;
  108. ccc = bbb;
  109. bbb = aaa;
  110. aaa = tmp;
  111. }
  112. ddd = hash[1] + cc + ddd;
  113. hash[1] = hash[2] + dd + aaa;
  114. hash[2] = hash[3] + aa + bbb;
  115. hash[3] = hash[0] + bb + ccc;
  116. hash[0] = ddd;
  117. }
  118. return new Uint8Array( hash.buffer );
  119. }
  120. }());