/ concept-collection / mri-scanner
concept-collection / mri-scanner
mri-scanner / src / seq / md5.ts
74 lines · 2.1 KBBlameHistoryRaw
1// Pure-JS MD5 (RFC 1321), used to verify .seq [SIGNATURE] sections
2// synchronously (WebCrypto has no MD5). Input is treated as a byte string.
4export function md5Hex(input: string): string {
5 const bytes: number[] = []
6 for (let i = 0; i < input.length; i++) bytes.push(input.charCodeAt(i) & 0xff)
8 const origLenBits = bytes.length * 8
9 bytes.push(0x80)
10 while (bytes.length % 64 !== 56) bytes.push(0)
11 let len = origLenBits
12 for (let i = 0; i < 8; i++) {
13 bytes.push(len & 0xff)
14 len = Math.floor(len / 256)
15 }
17 const S = [
18 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9,
19 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15,
20 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
21 ]
22 const K = Array.from({ length: 64 }, (_, i) => Math.floor(Math.abs(Math.sin(i + 1)) * 4294967296) >>> 0)
24 let a0 = 0x67452301
25 let b0 = 0xefcdab89
26 let c0 = 0x98badcfe
27 let d0 = 0x10325476
29 const rotl = (x: number, c: number) => ((x << c) | (x >>> (32 - c))) >>> 0
31 for (let chunk = 0; chunk < bytes.length; chunk += 64) {
32 const M = Array.from({ length: 16 }, (_, j) => {
33 const o = chunk + j * 4
34 return (bytes[o] | (bytes[o + 1] << 8) | (bytes[o + 2] << 16) | (bytes[o + 3] << 24)) >>> 0
35 })
36 let A = a0
37 let B = b0
38 let C = c0
39 let D = d0
40 for (let i = 0; i < 64; i++) {
41 let F: number
42 let g: number
43 if (i < 16) {
44 F = (B & C) | (~B & D)
45 g = i
46 } else if (i < 32) {
47 F = (D & B) | (~D & C)
48 g = (5 * i + 1) % 16
49 } else if (i < 48) {
50 F = B ^ C ^ D
51 g = (3 * i + 5) % 16
52 } else {
53 F = C ^ (B | ~D)
54 g = (7 * i) % 16
55 }
56 F = (F + A + K[i] + M[g]) >>> 0
57 A = D
58 D = C
59 C = B
60 B = (B + rotl(F, S[i])) >>> 0
61 }
62 a0 = (a0 + A) >>> 0
63 b0 = (b0 + B) >>> 0
64 c0 = (c0 + C) >>> 0
65 d0 = (d0 + D) >>> 0
66 }
68 const le = (w: number) => {
69 let s = ''
70 for (let i = 0; i < 4; i++) s += ((w >>> (i * 8)) & 0xff).toString(16).padStart(2, '0')
71 return s
72 }
73 return le(a0) + le(b0) + le(c0) + le(d0)