Skip to content

Commit 7ff59de

Browse files
🚧 progress: Import existing code.
1 parent 4c224e3 commit 7ff59de

File tree

7 files changed

+9642
-8
lines changed

7 files changed

+9642
-8
lines changed

package.json

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,22 @@
6868
"test:module": "IMPORT_MAP_PATH=test/import-maps/dist/index.module.json npm run test-cmd",
6969
"test:src": "IMPORT_MAP_PATH=test/import-maps/src/index.json npm run test-cmd"
7070
},
71-
"dependencies": {},
71+
"dependencies": {
72+
"@arithmetic-type/uint32": "^2.0.0"
73+
},
7274
"devDependencies": {
75+
"@array-like/alloc": "0.0.1",
7376
"@babel/core": "7.19.0",
7477
"@babel/plugin-transform-destructuring": "7.18.13",
7578
"@babel/plugin-transform-for-of": "7.18.8",
7679
"@babel/preset-env": "7.19.0",
80+
"@codec-bytes/ascii": "3.0.0",
7781
"@commitlint/cli": "17.1.2",
7882
"@js-library/commitlint-config": "0.0.4",
7983
"@node-loader/babel": "2.0.1",
8084
"@node-loader/core": "2.0.0",
8185
"@node-loader/import-maps": "1.1.0",
86+
"@set-theory/cartesian-product": "2.0.2",
8287
"ava": "4.3.3",
8388
"babel-plugin-transform-remove-console": "6.9.4",
8489
"babel-plugin-unassert": "3.2.0",
@@ -225,6 +230,15 @@
225230
"doc/**"
226231
],
227232
"env": "browser"
233+
},
234+
{
235+
"files": [
236+
"src/**"
237+
],
238+
"rules": {
239+
"no-bitwise": "off",
240+
"unicorn/prefer-math-trunc": "off"
241+
}
228242
}
229243
]
230244
}

src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
const answer = 42;
2-
export default answer;
1+
export * from './md5.js';
2+
export * from './md5fast.js';

src/md5.js

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
import {get32, add32, rotl32, lil32} from '@arithmetic-type/uint32';
2+
3+
function cycle(h, k, r, w) {
4+
// Initialize hash value for this chunk:
5+
let a = h[0];
6+
let b = h[1];
7+
let c = h[2];
8+
let d = h[3];
9+
10+
// Main loop
11+
for (let i = 0; i < 64; ++i) {
12+
let f;
13+
let g;
14+
15+
if (i < 16) {
16+
f = (b & c) | (~b & d);
17+
g = i;
18+
} else if (i < 32) {
19+
f = (d & b) | (~d & c);
20+
g = (5 * i + 1) % 16;
21+
} else if (i < 48) {
22+
f = b ^ c ^ d;
23+
g = (3 * i + 5) % 16;
24+
} else {
25+
f = c ^ (b | ~d);
26+
g = (7 * i) % 16;
27+
}
28+
29+
const t = d;
30+
d = c;
31+
c = b;
32+
b = add32(b, rotl32(add32(add32(a, f), add32(k[i], w[g])), r[i]));
33+
a = t;
34+
}
35+
36+
// Add this chunk's hash to result so far:
37+
h[0] = add32(h[0], a);
38+
h[1] = add32(h[1], b);
39+
h[2] = add32(h[2], c);
40+
h[3] = add32(h[3], d);
41+
}
42+
43+
function call(h, k, r, data, o) {
44+
// Break chunk into sixteen 32-bit little-endian words w[i], 0 ≤ i ≤ 15
45+
46+
const w = [
47+
lil32(data, o + 0),
48+
lil32(data, o + 4),
49+
lil32(data, o + 8),
50+
lil32(data, o + 12),
51+
lil32(data, o + 16),
52+
lil32(data, o + 20),
53+
lil32(data, o + 24),
54+
lil32(data, o + 28),
55+
lil32(data, o + 32),
56+
lil32(data, o + 36),
57+
lil32(data, o + 40),
58+
lil32(data, o + 44),
59+
lil32(data, o + 48),
60+
lil32(data, o + 52),
61+
lil32(data, o + 56),
62+
lil32(data, o + 60),
63+
];
64+
65+
cycle(h, k, r, w);
66+
}
67+
68+
/**
69+
* MD5
70+
*/
71+
export function md5(bytes, n, digest) {
72+
const k = [
73+
get32(0xd7_6a_a4_78),
74+
get32(0xe8_c7_b7_56),
75+
get32(0x24_20_70_db),
76+
get32(0xc1_bd_ce_ee),
77+
get32(0xf5_7c_0f_af),
78+
get32(0x47_87_c6_2a),
79+
get32(0xa8_30_46_13),
80+
get32(0xfd_46_95_01),
81+
get32(0x69_80_98_d8),
82+
get32(0x8b_44_f7_af),
83+
get32(0xff_ff_5b_b1),
84+
get32(0x89_5c_d7_be),
85+
get32(0x6b_90_11_22),
86+
get32(0xfd_98_71_93),
87+
get32(0xa6_79_43_8e),
88+
get32(0x49_b4_08_21),
89+
get32(0xf6_1e_25_62),
90+
get32(0xc0_40_b3_40),
91+
get32(0x26_5e_5a_51),
92+
get32(0xe9_b6_c7_aa),
93+
get32(0xd6_2f_10_5d),
94+
get32(0x02_44_14_53),
95+
get32(0xd8_a1_e6_81),
96+
get32(0xe7_d3_fb_c8),
97+
get32(0x21_e1_cd_e6),
98+
get32(0xc3_37_07_d6),
99+
get32(0xf4_d5_0d_87),
100+
get32(0x45_5a_14_ed),
101+
get32(0xa9_e3_e9_05),
102+
get32(0xfc_ef_a3_f8),
103+
get32(0x67_6f_02_d9),
104+
get32(0x8d_2a_4c_8a),
105+
get32(0xff_fa_39_42),
106+
get32(0x87_71_f6_81),
107+
get32(0x6d_9d_61_22),
108+
get32(0xfd_e5_38_0c),
109+
get32(0xa4_be_ea_44),
110+
get32(0x4b_de_cf_a9),
111+
get32(0xf6_bb_4b_60),
112+
get32(0xbe_bf_bc_70),
113+
get32(0x28_9b_7e_c6),
114+
get32(0xea_a1_27_fa),
115+
get32(0xd4_ef_30_85),
116+
get32(0x04_88_1d_05),
117+
get32(0xd9_d4_d0_39),
118+
get32(0xe6_db_99_e5),
119+
get32(0x1f_a2_7c_f8),
120+
get32(0xc4_ac_56_65),
121+
get32(0xf4_29_22_44),
122+
get32(0x43_2a_ff_97),
123+
get32(0xab_94_23_a7),
124+
get32(0xfc_93_a0_39),
125+
get32(0x65_5b_59_c3),
126+
get32(0x8f_0c_cc_92),
127+
get32(0xff_ef_f4_7d),
128+
get32(0x85_84_5d_d1),
129+
get32(0x6f_a8_7e_4f),
130+
get32(0xfe_2c_e6_e0),
131+
get32(0xa3_01_43_14),
132+
get32(0x4e_08_11_a1),
133+
get32(0xf7_53_7e_82),
134+
get32(0xbd_3a_f2_35),
135+
get32(0x2a_d7_d2_bb),
136+
get32(0xeb_86_d3_91),
137+
];
138+
139+
const r = [
140+
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5,
141+
9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11,
142+
16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10,
143+
15, 21,
144+
];
145+
146+
// PREPARE
147+
148+
const q = (n / 8) | 0;
149+
const z = q * 8;
150+
const u = n - z;
151+
152+
// Append the bit '1' to the message
153+
const last = u > 0 ? bytes[q] & (~0 << (7 - u)) : 0x80;
154+
155+
// Initialize state
156+
const h = [
157+
get32(0x67_45_23_01),
158+
get32(0xef_cd_ab_89),
159+
get32(0x98_ba_dc_fe),
160+
get32(0x10_32_54_76),
161+
];
162+
163+
// Process the message in successive 512-bit chunks:
164+
// break message into 512-bit chunks
165+
166+
const m = (n / 512) | 0;
167+
const y = ((n - 512 * m) / 8) | 0;
168+
169+
// Offset in data
170+
let o = 0;
171+
172+
// For each chunk
173+
for (let j = 0; j < m; ++j, o += 64) {
174+
call(h, k, r, bytes, o);
175+
}
176+
177+
// Last bytes + padding + length
178+
let tail = [];
179+
180+
// Last bytes
181+
for (let j = 0; j < y; ++j) {
182+
tail.push(bytes[o + j]);
183+
}
184+
185+
// Special care taken for the very last byte which could
186+
// have been modified if n is not a multiple of 8
187+
tail.push(last);
188+
189+
// Append 0 ≤ k < 512 bits '0', so that the resulting
190+
// message length (in bits) is congruent to 448 (mod 512)
191+
let zeroes = ((448 - ((n + 1) % 512)) / 8) | 0;
192+
193+
if (zeroes < 0) {
194+
// We need an additional block as there is
195+
// not enough space left to append
196+
// the length of the data in bits
197+
198+
for (let j = 0; j < -zeroes; ++j) {
199+
tail.push(0);
200+
}
201+
202+
call(h, k, r, tail, 0);
203+
204+
zeroes = 448 / 8;
205+
tail = [];
206+
}
207+
208+
// Pad with zeroes
209+
for (let j = 0; j < zeroes; ++j) {
210+
tail.push(0);
211+
}
212+
213+
// Append length of message (before preparation), in bits,
214+
// as 64-bit little-endian integer
215+
216+
tail.push(
217+
(n >>> 0) & 0xff,
218+
(n >>> 8) & 0xff,
219+
(n >>> 16) & 0xff,
220+
(n >>> 24) & 0xff,
221+
0,
222+
0,
223+
0,
224+
0,
225+
);
226+
227+
call(h, k, r, tail, 0);
228+
229+
digest[0] = (h[0] >>> 0) & 0xff;
230+
digest[1] = (h[0] >>> 8) & 0xff;
231+
digest[2] = (h[0] >>> 16) & 0xff;
232+
digest[3] = (h[0] >>> 24) & 0xff;
233+
digest[4] = (h[1] >>> 0) & 0xff;
234+
digest[5] = (h[1] >>> 8) & 0xff;
235+
digest[6] = (h[1] >>> 16) & 0xff;
236+
digest[7] = (h[1] >>> 24) & 0xff;
237+
digest[8] = (h[2] >>> 0) & 0xff;
238+
digest[9] = (h[2] >>> 8) & 0xff;
239+
digest[10] = (h[2] >>> 16) & 0xff;
240+
digest[11] = (h[2] >>> 24) & 0xff;
241+
digest[12] = (h[3] >>> 0) & 0xff;
242+
digest[13] = (h[3] >>> 8) & 0xff;
243+
digest[14] = (h[3] >>> 16) & 0xff;
244+
digest[15] = (h[3] >>> 24) & 0xff;
245+
246+
return digest;
247+
}

0 commit comments

Comments
 (0)