|
| 1 | +fn md4(msg: [u8]) -> {a: u32, b: u32, c: u32, d: u32} { |
| 2 | + let orig_len = vec::len(msg) * 8u; |
| 3 | + // pad message |
| 4 | + let msg = msg + [0x80u8]; |
| 5 | + let bitlen = orig_len + 8u; |
| 6 | + while (bitlen + 64u) % 512u > 0u { |
| 7 | + msg += [0u8]; |
| 8 | + bitlen += 8u; |
| 9 | + } |
| 10 | + // append length |
| 11 | + let i = 0u; |
| 12 | + while i < 8u { |
| 13 | + msg += [(orig_len >> (i * 8u)) as u8]; |
| 14 | + i += 1u; |
| 15 | + } |
| 16 | + |
| 17 | + let a = 0x67452301u32; |
| 18 | + let b = 0xefcdab89u32; |
| 19 | + let c = 0x98badcfeu32; |
| 20 | + let d = 0x10325476u32; |
| 21 | + |
| 22 | + fn rot(r: int, x: u32) -> u32 { |
| 23 | + let r = r as u32; |
| 24 | + (x << r) | (x >> (32u32 - r)) |
| 25 | + } |
| 26 | + |
| 27 | + let i = 0u, e = vec::len(msg); |
| 28 | + let x = vec::init_elt_mut(0u32, 16u); |
| 29 | + while i < e { |
| 30 | + let aa = a, bb = b, cc = c, dd = d; |
| 31 | + |
| 32 | + let j = 0u, base = i; |
| 33 | + while j < 16u { |
| 34 | + x[j] = (msg[base] as u32) + (msg[base + 1u] as u32 << 8u32) + |
| 35 | + (msg[base + 2u] as u32 << 16u32) + |
| 36 | + (msg[base + 3u] as u32 << 24u32); |
| 37 | + j += 1u; base += 4u; |
| 38 | + } |
| 39 | + |
| 40 | + let j = 0u; |
| 41 | + while j < 16u { |
| 42 | + a = rot(3, a + ((b & c) | (!b & d)) + x[j]); |
| 43 | + j += 1u; |
| 44 | + d = rot(7, d + ((a & b) | (!a & c)) + x[j]); |
| 45 | + j += 1u; |
| 46 | + c = rot(11, c + ((d & a) | (!d & b)) + x[j]); |
| 47 | + j += 1u; |
| 48 | + b = rot(19, b + ((c & d) | (!c & a)) + x[j]); |
| 49 | + j += 1u; |
| 50 | + } |
| 51 | + |
| 52 | + let j = 0u, q = 0x5a827999u32; |
| 53 | + while j < 4u { |
| 54 | + a = rot(3, a + ((b & c) | ((b & d) | (c & d))) + x[j] + q); |
| 55 | + d = rot(5, d + ((a & b) | ((a & c) | (b & c))) + x[j + 4u] + q); |
| 56 | + c = rot(9, c + ((d & a) | ((d & b) | (a & b))) + x[j + 8u] + q); |
| 57 | + b = rot(13, b + ((c & d) | ((c & a) | (d & a))) + x[j + 12u] + q); |
| 58 | + j += 1u; |
| 59 | + } |
| 60 | + |
| 61 | + let j = 0u, q = 0x6ed9eba1u32; |
| 62 | + while j < 8u { |
| 63 | + let jj = j > 2u ? j - 3u : j; |
| 64 | + a = rot(3, a + (b ^ c ^ d) + x[jj] + q); |
| 65 | + d = rot(9, d + (a ^ b ^ c) + x[jj + 8u] + q); |
| 66 | + c = rot(11, c + (d ^ a ^ b) + x[jj + 4u] + q); |
| 67 | + b = rot(15, b + (c ^ d ^ a) + x[jj + 12u] + q); |
| 68 | + j += 2u; |
| 69 | + } |
| 70 | + |
| 71 | + a += aa; b += bb; c += cc; d += dd; |
| 72 | + i += 64u; |
| 73 | + } |
| 74 | + ret {a: a, b: b, c: c, d: d}; |
| 75 | +} |
| 76 | + |
| 77 | +fn md4_str(msg: [u8]) -> str { |
| 78 | + let {a, b, c, d} = md4(msg); |
| 79 | + fn app(a: u32, b: u32, c: u32, d: u32, f: block(u32)) { |
| 80 | + f(a); f(b); f(c); f(d); |
| 81 | + } |
| 82 | + let result = ""; |
| 83 | + app(a, b, c, d) {|u| |
| 84 | + let i = 0u32; |
| 85 | + while i < 4u32 { |
| 86 | + let byte = (u >> (i * 8u32)) as u8; |
| 87 | + if byte <= 16u8 { result += "0"; } |
| 88 | + result += uint::to_str(byte as uint, 16u); |
| 89 | + i += 1u32; |
| 90 | + } |
| 91 | + } |
| 92 | + result |
| 93 | +} |
| 94 | + |
| 95 | +fn md4_text(msg: str) -> str { md4_str(str::bytes(msg)) } |
| 96 | + |
| 97 | +#[test] |
| 98 | +fn test_md4() { |
| 99 | + assert md4_text("") == "31d6cfe0d16ae931b73c59d7e0c089c0"; |
| 100 | + assert md4_text("a") == "bde52cb31de33e46245e05fbdbd6fb24"; |
| 101 | + assert md4_text("abc") == "a448017aaf21d8525fc10ae87aa6729d"; |
| 102 | + assert md4_text("message digest") == "d9130a8164549fe818874806e1c7014b"; |
| 103 | + assert md4_text("abcdefghijklmnopqrstuvwxyz") == |
| 104 | + "d79e1c308aa5bbcdeea8ed63df412da9"; |
| 105 | + assert md4_text("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123\ |
| 106 | + 456789") == "043f8582f241db351ce627e153e7f0e4"; |
| 107 | + assert md4_text("12345678901234567890123456789012345678901234567890123456\ |
| 108 | + 789012345678901234567890") == |
| 109 | + "e33b4ddc9c38f2199c3e7b164fcc0536"; |
| 110 | +} |
0 commit comments