93 lines
3.1 KiB
Text
93 lines
3.1 KiB
Text
import "./fmt" for Fmt
|
|
|
|
var toBytes = Fn.new { |val|
|
|
var bytes = List.filled(4, 0)
|
|
bytes[0] = val & 255
|
|
bytes[1] = (val >> 8) & 255
|
|
bytes[2] = (val >> 16) & 255
|
|
bytes[3] = (val >> 24) & 255
|
|
return bytes
|
|
}
|
|
|
|
var toInt = Fn.new { |bytes| bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24 }
|
|
|
|
var md4 = Fn.new { |initMsg|
|
|
var f = Fn.new { |x, y, z| (x & y) | (~x & z) }
|
|
var g = Fn.new { |x, y, z| (x & y) | (x & z) | (y & z) }
|
|
var h = Fn.new { |x, y, z| x ^ y ^ z }
|
|
var r = Fn.new { |v, s| (v << s) | (v >> (32 - s)) }
|
|
|
|
var a = 0x67452301
|
|
var b = 0xefcdab89
|
|
var c = 0x98badcfe
|
|
var d = 0x10325476
|
|
var initBytes = initMsg.bytes
|
|
var initLen = initBytes.count
|
|
var newLen = initLen + 1
|
|
while (newLen % 64 != 56) newLen = newLen + 1
|
|
var msg = List.filled(newLen + 8, 0)
|
|
for (i in 0...initLen) msg[i] = initBytes[i]
|
|
msg[initLen] = 0x80 // remaining bytes already 0
|
|
var lenBits = toBytes.call(initLen * 8)
|
|
for (i in newLen...newLen+4) msg[i] = lenBits[i-newLen]
|
|
var extraBits = toBytes.call(initLen >> 29)
|
|
for (i in newLen+4...newLen+8) msg[i] = extraBits[i-newLen-4]
|
|
var offset = 0
|
|
var x = List.filled(16, 0)
|
|
while (offset < newLen) {
|
|
for (i in 0...16) x[i] = toInt.call(msg[offset+i*4...offset + i*4 + 4])
|
|
var a2 = a
|
|
var b2 = b
|
|
var c2 = c
|
|
var d2 = d
|
|
for (i in [0, 4, 8, 12]) {
|
|
a = r.call(a + f.call(b, c, d) + x[i+0], 3)
|
|
d = r.call(d + f.call(a, b, c) + x[i+1], 7)
|
|
c = r.call(c + f.call(d, a, b) + x[i+2], 11)
|
|
b = r.call(b + f.call(c, d, a) + x[i+3], 19)
|
|
}
|
|
for (i in 0..3) {
|
|
a = r.call(a + g.call(b, c, d) + x[i+0] + 0x5a827999, 3)
|
|
d = r.call(d + g.call(a, b, c) + x[i+4] + 0x5a827999, 5)
|
|
c = r.call(c + g.call(d, a, b) + x[i+8] + 0x5a827999, 9)
|
|
b = r.call(b + g.call(c, d, a) + x[i+12] + 0x5a827999, 13)
|
|
}
|
|
for (i in [0, 2, 1, 3]) {
|
|
a = r.call(a + h.call(b, c, d) + x[i+0] + 0x6ed9eba1, 3)
|
|
d = r.call(d + h.call(a, b, c) + x[i+8] + 0x6ed9eba1, 9)
|
|
c = r.call(c + h.call(d, a, b) + x[i+4] + 0x6ed9eba1, 11)
|
|
b = r.call(b + h.call(c, d, a) + x[i+12] + 0x6ed9eba1, 15)
|
|
}
|
|
a = a + a2
|
|
b = b + b2
|
|
c = c + c2
|
|
d = d + d2
|
|
offset = offset + 64
|
|
}
|
|
var digest = List.filled(16, 0)
|
|
var dBytes = toBytes.call(a)
|
|
for (i in 0...4) digest[i] = dBytes[i]
|
|
dBytes = toBytes.call(b)
|
|
for (i in 0...4) digest[i+4] = dBytes[i]
|
|
dBytes = toBytes.call(c)
|
|
for (i in 0...4) digest[i+8] = dBytes[i]
|
|
dBytes = toBytes.call(d)
|
|
for (i in 0...4) digest[i+12] = dBytes[i]
|
|
return digest
|
|
}
|
|
|
|
var strings = [
|
|
"",
|
|
"a",
|
|
"abc",
|
|
"message digest",
|
|
"abcdefghijklmnopqrstuvwxyz",
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
|
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
|
"Rosetta Code"
|
|
]
|
|
|
|
for (s in strings) {
|
|
var digest = md4.call(s)
|
|
Fmt.print("$s <== '$0s'", Fmt.v("xz", 2, digest, 0, "", ""), s)
|
|
}
|