UNPKG

18.5 kBJavaScriptView Raw
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"use strict";
41
42var _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
44var _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
46function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
47
48var 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
400module.exports = {
401 RIPEMD160: RIPEMD160
402};