RosettaCodeData/Task/MD4/Wren/md4.wren
2024-03-06 22:25:12 -08:00

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)
}