1 | // https://gist.githubusercontent.com/wlzla000/bac83df6d3c51916c4dd0bc947e46947/raw/7ee3462b095ab22580ddaf191f44a590da6fe33b/RIPEMD-160.js
|
2 |
|
3 | /*
|
4 | RIPEMD-160.js
|
5 |
|
6 | developed
|
7 | by K. (https://github.com/wlzla000)
|
8 | on December 27-29, 2017,
|
9 |
|
10 | licensed under
|
11 |
|
12 |
|
13 | the MIT license
|
14 |
|
15 | Copyright (c) 2017 K.
|
16 |
|
17 | Permission is hereby granted, free of charge, to any person
|
18 | obtaining a copy of this software and associated documentation
|
19 | files (the "Software"), to deal in the Software without
|
20 | restriction, including without limitation the rights to use,
|
21 | copy, modify, merge, publish, distribute, sublicense, and/or
|
22 | sell copies of the Software, and to permit persons to whom the
|
23 | Software is furnished to do so, subject to the following
|
24 | conditions:
|
25 |
|
26 | The above copyright notice and this permission notice shall be
|
27 | included in all copies or substantial portions of the Software.
|
28 |
|
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
31 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
32 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
33 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
34 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
35 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
36 | OTHER DEALINGS IN THE SOFTWARE.
|
37 | */
|
38 | /* eslint-disable */
|
39 |
|
40 | ;
|
41 |
|
42 | var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
43 |
|
44 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
45 |
|
46 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
47 |
|
48 | var RIPEMD160 = function () {
|
49 | function RIPEMD160() {
|
50 | // https://webcache.googleusercontent.com/search?q=cache:CnLOgolTHYEJ:https://www.cosic.esat.kuleuven.be/publications/article-317.pdf
|
51 | // http://shodhganga.inflibnet.ac.in/bitstream/10603/22978/13/13_appendix.pdf
|
52 |
|
53 | _classCallCheck(this, RIPEMD160);
|
54 | }
|
55 |
|
56 | _createClass(RIPEMD160, null, [{
|
57 | key: "get_n_pad_bytes",
|
58 | value: function get_n_pad_bytes(message_size /* in bytes, 1 byte is 8 bits. */) {
|
59 | // Obtain the number of bytes needed to pad the message.
|
60 | // It does not contain the size of the message size information.
|
61 | /*
|
62 | https://webcache.googleusercontent.com/search?q=cache:CnLOgolTHYEJ:https://www.cosic.esat.kuleuven.be/publications/article-317.pdf
|
63 | The Cryptographic Hash Function RIPEMD-160
|
64 | written by
|
65 | Bart Preneel,
|
66 | Hans Dobbertin,
|
67 | Antoon Bosselaers
|
68 | in
|
69 | 1997.
|
70 | --------------------------------------------------
|
71 | §5 Description of RIPEMD-160
|
72 | ......
|
73 | In order to guarantee that the total input size is a
|
74 | multiple of 512 bits, the input is padded in the same
|
75 | way as for all the members of the MD4-family: one
|
76 | appends a single 1 followed by a string of 0s (the
|
77 | number of 0s lies between 0 and 511); the last 64 bits
|
78 | of the extended input contain the binary representation
|
79 | of the input size in bits, least significant byte first.
|
80 | */
|
81 | /*
|
82 | https://tools.ietf.org/rfc/rfc1186.txt
|
83 | RFC 1186: MD4 Message Digest Algorithm.
|
84 | written by
|
85 | Ronald Linn Rivest
|
86 | in
|
87 | October 1990.
|
88 | --------------------------------------------------
|
89 | §3 MD4 Algorithm Description
|
90 | ......
|
91 | Step 1. Append padding bits
|
92 | The message is "padded" (extended) so that its length
|
93 | (in bits) is congruent to 448, modulo 512. That is, the
|
94 | message is extended so that it is just 64 bits shy of
|
95 | being a multiple of 512 bits long. Padding is always
|
96 | performed, even if the length of the message is already
|
97 | congruent to 448, modulo 512 (in which case 512 bits of
|
98 | padding are added).
|
99 | Padding is performed as follows: a single "1" bit is
|
100 | appended to the message, and then enough zero bits are
|
101 | appended so that the length in bits of the padded
|
102 | message becomes congruent to 448, modulo 512.
|
103 | Step 2. Append length
|
104 | A 64-bit representation of b (the length of the message
|
105 | before the padding bits were added) is appended to the
|
106 | result of the previous step. In the unlikely event that
|
107 | b is greater than 2^64, then only the low-order 64 bits
|
108 | of b are used. (These bits are appended as two 32-bit
|
109 | words and appended low-order word first in accordance
|
110 | with the previous conventions.)
|
111 | At this point the resulting message (after padding with
|
112 | bits and with b) has a length that is an exact multiple
|
113 | of 512 bits. Equivalently, this message has a length
|
114 | that is an exact multiple of 16 (32-bit) words. Let
|
115 | M[0 ... N-1] denote the words of the resulting message,
|
116 | where N is a multiple of 16.
|
117 | */
|
118 | // https://crypto.stackexchange.com/a/32407/54568
|
119 | /*
|
120 | Example case # 1
|
121 | [0 bit: message.]
|
122 | [1 bit: 1.]
|
123 | [447 bits: 0.]
|
124 | [64 bits: message size information.]
|
125 | Example case # 2
|
126 | [512-bits: message]
|
127 | [1 bit: 1.]
|
128 | [447 bits: 0.]
|
129 | [64 bits: message size information.]
|
130 | Example case # 3
|
131 | [(512 - 64 = 448) bits: message.]
|
132 | [1 bit: 1.]
|
133 | [511 bits: 0.]
|
134 | [64 bits: message size information.]
|
135 | Example case # 4
|
136 | [(512 - 65 = 447) bits: message.]
|
137 | [1 bit: 1.]
|
138 | [0 bit: 0.]
|
139 | [64 bits: message size information.]
|
140 | */
|
141 | // The number of padding zero bits:
|
142 | // 511 - [{(message size in bits) + 64} (mod 512)]
|
143 | return 64 - (message_size + 8 & 63 /* 63 */);
|
144 | }
|
145 | }, {
|
146 | key: "pad",
|
147 | value: function pad(message /* An ArrayBuffer. */) {
|
148 | var message_size = message.byteLength;
|
149 | var n_pad = RIPEMD160.get_n_pad_bytes(message_size);
|
150 |
|
151 | // `Number.MAX_SAFE_INTEGER` is ((2 ** 53) - 1) and
|
152 | // bitwise operation in Javascript is done on 32-bits operands.
|
153 | var divmod = function divmod(dividend, divisor) {
|
154 | return [Math.floor(dividend / divisor), dividend % divisor];
|
155 | };
|
156 | /*
|
157 | To shift
|
158 | 00000000 000????? ???????? ???????? ???????? ???????? ???????? ????????
|
159 | t o
|
160 | 00000000 ???????? ???????? ???????? ???????? ???????? ???????? ?????000
|
161 | --------------------------------------------------------------------------------
|
162 | Method #1
|
163 | 00000000 000????? ???????? ???????? ???????? ???????? ???????? ????????
|
164 | [00000000 000AAAAA AAAAAAAA AAAAAAAA] (<A> captured)
|
165 | [00000000 AAAAAAAA AAAAAAAA AAAAA000] (<A> shifted)
|
166 | (<B> captured) [BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB]
|
167 | (<B> shifted) [BBB][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
|
168 | [00000000 AAAAAAAA AAAAAAAA AAAAABBB] (<A> & <B_2> merged)
|
169 | [00000000 AAAAAAAA AAAAAAAA AAAAABBB][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
|
170 | 00000000 ???????? ???????? ???????? ???????? ???????? ???????? ?????000
|
171 | const uint32_max_plus_1 = 0x100000000; // (2 ** 32)
|
172 | const [
|
173 | msg_byte_size_most, // Value range [0, (2 ** 21) - 1].
|
174 | msg_byte_size_least // Value range [0, (2 ** 32) - 1].
|
175 | ] = divmod(message_size, uint32_max_plus_1);
|
176 | const [
|
177 | carry, // Value range [0, 7].
|
178 | msg_bit_size_least // Value range [0, (2 ** 32) - 8].
|
179 | ] = divmod(message_byte_size_least * 8, uint32_max_plus_1);
|
180 | const message_bit_size_most = message_byte_size_most * 8
|
181 | + carry; // Value range [0, (2 ** 24) - 1].
|
182 | --------------------------------------------------------------------------------
|
183 | Method #2
|
184 | 00000000 000????? ???????? ???????? ???????? ???????? ???????? ????????
|
185 | [00000 000AAAAA AAAAAAAA AAAAAAAA AAA] (<A> captured)
|
186 | (<B> captured) [000BBBBB BBBBBBBB BBBBBBBB BBBBBBBB]
|
187 | (<B> shifted) [BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
|
188 | [00000000 AAAAAAAA AAAAAAAA AAAAAAAA][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
|
189 | 00000000 ???????? ???????? ???????? ???????? ???????? ???????? ?????000
|
190 | */
|
191 |
|
192 | var _divmod$map = divmod(message_size, 536870912 /* (2 ** 29) */).map(function (x, index) {
|
193 | return index ? x * 8 : x;
|
194 | }),
|
195 | _divmod$map2 = _slicedToArray(_divmod$map, 2),
|
196 | msg_bit_size_most = _divmod$map2[0],
|
197 | msg_bit_size_least = _divmod$map2[1];
|
198 |
|
199 | // `ArrayBuffer.transfer()` is not supported.
|
200 |
|
201 |
|
202 | var padded = new Uint8Array(message_size + n_pad + 8);
|
203 | padded.set(new Uint8Array(message), 0);
|
204 | var data_view = new DataView(padded.buffer);
|
205 | data_view.setUint8(message_size, 128);
|
206 | data_view.setUint32(message_size + n_pad, msg_bit_size_least, true // Little-endian
|
207 | );
|
208 | data_view.setUint32(message_size + n_pad + 4, msg_bit_size_most, true // Little-endian
|
209 | );
|
210 |
|
211 | return padded.buffer;
|
212 | }
|
213 | }, {
|
214 | key: "f",
|
215 | value: function f(j, x, y, z) {
|
216 | if (0 <= j && j <= 15) {
|
217 | // Exclusive-OR
|
218 | return x ^ y ^ z;
|
219 | }
|
220 | if (16 <= j && j <= 31) {
|
221 | // Multiplexing (muxing)
|
222 | return x & y | ~x & z;
|
223 | }
|
224 | if (32 <= j && j <= 47) {
|
225 | return (x | ~y) ^ z;
|
226 | }
|
227 | if (48 <= j && j <= 63) {
|
228 | // Multiplexing (muxing)
|
229 | return x & z | y & ~z;
|
230 | }
|
231 | if (64 <= j && j <= 79) {
|
232 | return x ^ (y | ~z);
|
233 | }
|
234 | }
|
235 | }, {
|
236 | key: "K",
|
237 | value: function K(j) {
|
238 | if (0 <= j && j <= 15) {
|
239 | return 0x00000000;
|
240 | }
|
241 | if (16 <= j && j <= 31) {
|
242 | // Math.floor((2 ** 30) * Math.SQRT2)
|
243 | return 0x5A827999;
|
244 | }
|
245 | if (32 <= j && j <= 47) {
|
246 | // Math.floor((2 ** 30) * Math.sqrt(3))
|
247 | return 0x6ED9EBA1;
|
248 | }
|
249 | if (48 <= j && j <= 63) {
|
250 | // Math.floor((2 ** 30) * Math.sqrt(5))
|
251 | return 0x8F1BBCDC;
|
252 | }
|
253 | if (64 <= j && j <= 79) {
|
254 | // Math.floor((2 ** 30) * Math.sqrt(7))
|
255 | return 0xA953FD4E;
|
256 | }
|
257 | }
|
258 | }, {
|
259 | key: "KP",
|
260 | value: function KP(j) // K'
|
261 | {
|
262 | if (0 <= j && j <= 15) {
|
263 | // Math.floor((2 ** 30) * Math.cbrt(2))
|
264 | return 0x50A28BE6;
|
265 | }
|
266 | if (16 <= j && j <= 31) {
|
267 | // Math.floor((2 ** 30) * Math.cbrt(3))
|
268 | return 0x5C4DD124;
|
269 | }
|
270 | if (32 <= j && j <= 47) {
|
271 | // Math.floor((2 ** 30) * Math.cbrt(5))
|
272 | return 0x6D703EF3;
|
273 | }
|
274 | if (48 <= j && j <= 63) {
|
275 | // Math.floor((2 ** 30) * Math.cbrt(7))
|
276 | return 0x7A6D76E9;
|
277 | }
|
278 | if (64 <= j && j <= 79) {
|
279 | return 0x00000000;
|
280 | }
|
281 | }
|
282 | }, {
|
283 | key: "add_modulo32",
|
284 | value: function add_modulo32() /* ...... */{
|
285 | // 1. Modulo addition (addition modulo) is associative.
|
286 | // https://proofwiki.org/wiki/Modulo_Addition_is_Associative
|
287 | // 2. Bitwise operation in Javascript
|
288 | // is done on 32-bits operands
|
289 | // and results in a 32-bits value.
|
290 | return Array.from(arguments).reduce(function (a, b) {
|
291 | return a + b;
|
292 | }, 0) | 0;
|
293 | }
|
294 | }, {
|
295 | key: "rol32",
|
296 | value: function rol32(value, count) {
|
297 | // Cyclic left shift (rotate) on 32-bits value.
|
298 | return value << count | value >>> 32 - count;
|
299 | }
|
300 | }, {
|
301 | key: "hash",
|
302 | value: function hash(message /* An ArrayBuffer. */) {
|
303 | ////////// Padding //////////
|
304 |
|
305 | // The padded message.
|
306 | var padded = RIPEMD160.pad(message);
|
307 |
|
308 | ////////// Compression //////////
|
309 |
|
310 | // Message word selectors.
|
311 | var r = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13];
|
312 | var rP = [// r'
|
313 | 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11];
|
314 |
|
315 | // Amounts for 'rotate left' operation.
|
316 | var s = [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6];
|
317 | var sP = [// s'
|
318 | 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11];
|
319 |
|
320 | // The size, in bytes, of a word.
|
321 | var word_size = 4;
|
322 |
|
323 | // The size, in bytes, of a 16-words block.
|
324 | var block_size = 64;
|
325 |
|
326 | // The number of the 16-words blocks.
|
327 | var t = padded.byteLength / block_size;
|
328 |
|
329 | // The message after padding consists of t 16-word blocks that
|
330 | // are denoted with X_i[j], with 0≤i≤(t − 1) and 0≤j≤15.
|
331 | var X = new Array(t).fill(undefined).map(function (_, i) {
|
332 | return function (j) {
|
333 | return new DataView(padded, i * block_size, block_size).getUint32(j * word_size, true // Little-endian
|
334 | );
|
335 | };
|
336 | });
|
337 |
|
338 | // The result of RIPEMD-160 is contained in five 32-bit words,
|
339 | // which form the internal state of the algorithm. The final
|
340 | // content of these five 32-bit words is converted to a 160-bit
|
341 | // string, again using the little-endian convention.
|
342 | var h = [0x67452301, // h_0
|
343 | 0xEFCDAB89, // h_1
|
344 | 0x98BADCFE, // h_2
|
345 | 0x10325476, // h_3
|
346 | 0xC3D2E1F0 // h_4
|
347 | ];
|
348 |
|
349 | for (var i = 0; i < t; ++i) {
|
350 | var A = h[0],
|
351 | B = h[1],
|
352 | C = h[2],
|
353 | D = h[3],
|
354 | E = h[4];
|
355 | var AP = A,
|
356 | BP = B,
|
357 | CP = C,
|
358 | DP = D,
|
359 | EP = E;
|
360 | for (var j = 0; j < 80; ++j) {
|
361 | // Left rounds
|
362 | var _T = RIPEMD160.add_modulo32(RIPEMD160.rol32(RIPEMD160.add_modulo32(A, RIPEMD160.f(j, B, C, D), X[i](r[j]), RIPEMD160.K(j)), s[j]), E);
|
363 | A = E;
|
364 | E = D;
|
365 | D = RIPEMD160.rol32(C, 10);
|
366 | C = B;
|
367 | B = _T;
|
368 |
|
369 | // Right rounds
|
370 | _T = RIPEMD160.add_modulo32(RIPEMD160.rol32(RIPEMD160.add_modulo32(AP, RIPEMD160.f(79 - j, BP, CP, DP), X[i](rP[j]), RIPEMD160.KP(j)), sP[j]), EP);
|
371 | AP = EP;
|
372 | EP = DP;
|
373 | DP = RIPEMD160.rol32(CP, 10);
|
374 | CP = BP;
|
375 | BP = _T;
|
376 | }
|
377 | var T = RIPEMD160.add_modulo32(h[1], C, DP);
|
378 | h[1] = RIPEMD160.add_modulo32(h[2], D, EP);
|
379 | h[2] = RIPEMD160.add_modulo32(h[3], E, AP);
|
380 | h[3] = RIPEMD160.add_modulo32(h[4], A, BP);
|
381 | h[4] = RIPEMD160.add_modulo32(h[0], B, CP);
|
382 | h[0] = T;
|
383 | }
|
384 |
|
385 | // The final output string then consists of the concatenatation
|
386 | // of h_0, h_1, h_2, h_3, and h_4 after converting each h_i to a
|
387 | // 4-byte string using the little-endian convention.
|
388 | var result = new ArrayBuffer(20);
|
389 | var data_view = new DataView(result);
|
390 | h.forEach(function (h_i, i) {
|
391 | return data_view.setUint32(i * 4, h_i, true);
|
392 | });
|
393 | return result;
|
394 | }
|
395 | }]);
|
396 |
|
397 | return RIPEMD160;
|
398 | }();
|
399 |
|
400 | module.exports = {
|
401 | RIPEMD160: RIPEMD160
|
402 | };
|