Skip to content

Commit a16160f

Browse files
committed
Use noble-hashes for md5
The existing md5 module brought in the util module, which messed up the chunking structure in the lightweight build; inlining those functions is an option, but the noble-hashes code is also more modern and readable.
1 parent abe750c commit a16160f

File tree

4 files changed

+83
-206
lines changed

4 files changed

+83
-206
lines changed

src/crypto/hash/index.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,7 @@ function nobleHash(nobleHashName, webCryptoHashName) {
5454
};
5555
}
5656

57-
function webHashMD5() {
58-
return (data) => import('./md5').then(({ default: computeMD5 }) => computeMD5(data));
59-
}
60-
61-
const md5 = nodeHash('md5') || webHashMD5();
57+
const md5 = nodeHash('md5') || nobleHash('md5');
6258
const sha1 = nodeHash('sha1') || nobleHash('sha1', 'SHA-1');
6359
const sha224 = nodeHash('sha224') || nobleHash('sha224');
6460
const sha256 = nodeHash('sha256') || nobleHash('sha256', 'SHA-256');

src/crypto/hash/md5.js

Lines changed: 0 additions & 201 deletions
This file was deleted.

src/crypto/hash/md5.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copied from https://github.com/paulmillr/noble-hashes/blob/main/test/misc/md5.ts
2+
3+
import { HashMD } from '@noble/hashes/_md';
4+
import { rotl, wrapConstructor } from '@noble/hashes/utils';
5+
6+
// Per-round constants
7+
const K = Array.from({ length: 64 }, (_, i) => Math.floor(2 ** 32 * Math.abs(Math.sin(i + 1))));
8+
// Choice: a ? b : c
9+
const Chi = (a: number, b: number, c: number) => (a & b) ^ (~a & c);
10+
// Initial state (same as sha1, but 4 u32 instead of 5)
11+
const IV = /* @__PURE__ */ new Uint32Array([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]);
12+
// Temporary buffer, not used to store anything between runs
13+
// Named this way for SHA1 compat
14+
const MD5_W = /* @__PURE__ */ new Uint32Array(16);
15+
class MD5 extends HashMD<MD5> {
16+
private A = IV[0] | 0;
17+
private B = IV[1] | 0;
18+
private C = IV[2] | 0;
19+
private D = IV[3] | 0;
20+
constructor() {
21+
super(64, 16, 8, true);
22+
}
23+
protected get(): [number, number, number, number] {
24+
const { A, B, C, D } = this;
25+
return [A, B, C, D];
26+
}
27+
protected set(A: number, B: number, C: number, D: number) {
28+
this.A = A | 0;
29+
this.B = B | 0;
30+
this.C = C | 0;
31+
this.D = D | 0;
32+
}
33+
protected process(view: DataView, offset: number): void {
34+
for (let i = 0; i < 16; i++, offset += 4) MD5_W[i] = view.getUint32(offset, true);
35+
// Compression function main loop, 64 rounds
36+
let { A, B, C, D } = this;
37+
for (let i = 0; i < 64; i++) {
38+
// eslint-disable-next-line one-var, one-var-declaration-per-line
39+
let F, g, s;
40+
if (i < 16) {
41+
// eslint-disable-next-line new-cap
42+
F = Chi(B, C, D);
43+
g = i;
44+
s = [7, 12, 17, 22];
45+
} else if (i < 32) {
46+
// eslint-disable-next-line new-cap
47+
F = Chi(D, B, C);
48+
g = (5 * i + 1) % 16;
49+
s = [5, 9, 14, 20];
50+
} else if (i < 48) {
51+
F = B ^ C ^ D;
52+
g = (3 * i + 5) % 16;
53+
s = [4, 11, 16, 23];
54+
} else {
55+
F = C ^ (B | ~D);
56+
g = (7 * i) % 16;
57+
s = [6, 10, 15, 21];
58+
}
59+
F = F + A + K[i] + MD5_W[g];
60+
A = D;
61+
D = C;
62+
C = B;
63+
B = B + rotl(F, s[i % 4]);
64+
}
65+
// Add the compressed chunk to the current hash value
66+
A = (A + this.A) | 0;
67+
B = (B + this.B) | 0;
68+
C = (C + this.C) | 0;
69+
D = (D + this.D) | 0;
70+
this.set(A, B, C, D);
71+
}
72+
protected roundClean() {
73+
MD5_W.fill(0);
74+
}
75+
destroy() {
76+
this.set(0, 0, 0, 0);
77+
this.buffer.fill(0);
78+
}
79+
}
80+
export const md5 = /* @__PURE__ */ wrapConstructor(() => new MD5());

src/crypto/hash/noble_hashes.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import { sha224, sha256 } from '@noble/hashes/sha256';
99
import { sha384, sha512 } from '@noble/hashes/sha512';
1010
import { sha3_256, sha3_512 } from '@noble/hashes/sha3';
1111
import { ripemd160 } from '@noble/hashes/ripemd160';
12+
import { md5 } from './md5';
1213

1314
export const nobleHashes = new Map(Object.entries({
15+
md5,
1416
sha1,
1517
sha224,
1618
sha256,

0 commit comments

Comments
 (0)