///|
let md5_s : Array[Int] = [
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, 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, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
]
///|
let md5_k : Array[UInt] = [
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613,
0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193,
0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d,
0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122,
0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244,
0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb,
0xeb86d391,
]
///|
fn md5_u32(x : UInt) -> UInt {
UInt::land(x, 0xffff_ffff)
}
///|
fn rotl32(x : UInt, n : Int) -> UInt {
md5_u32(UInt::lor(x << n, x >> (32 - n)))
}
///|
fn le_u32(bytes : @pdfio.MutableBytes, offset : Int) -> UInt {
let b0 = @pdfio.bget(bytes, offset).reinterpret_as_uint()
let b1 = @pdfio.bget(bytes, offset + 1).reinterpret_as_uint()
let b2 = @pdfio.bget(bytes, offset + 2).reinterpret_as_uint()
let b3 = @pdfio.bget(bytes, offset + 3).reinterpret_as_uint()
UInt::lor(UInt::lor(b0, b1 << 8), UInt::lor(b2 << 16, b3 << 24))
}
///|
fn add_u32(a : UInt, b : UInt) -> UInt {
md5_u32(UInt::add(a, b))
}
///|
fn md5_pad(data : @pdfio.MutableBytes) -> @pdfio.MutableBytes {
let len = @pdfio.bytes_size(data)
let bit_len = UInt64::mul(UInt64::extend_uint(len.reinterpret_as_uint()), 8)
let pad_len = (56 - (len + 1) % 64 + 64) % 64
let total = len + 1 + pad_len + 8
let out = @pdfio.mkbytes(total)
let mut i = 0
while i < len {
@pdfio.bset(out, i, @pdfio.bget(data, i))
i = i + 1
}
@pdfio.bset(out, len, 0x80)
let mut j = 0
while j < 8 {
let shift = j * 8
let v = (bit_len >> shift).to_int()
@pdfio.bset(out, total - 8 + j, Int::land(v, 0xff))
j = j + 1
}
out
}
///|
/// MD5 digest of bytes, returning 16 raw bytes.
pub fn PdfCryptPrimitives::md5(
_self : PdfCryptPrimitives,
data : @pdfio.MutableBytes,
) -> @pdfio.MutableBytes {
let padded = md5_pad(data)
let mut a0 : UInt = 0x67452301
let mut b0 : UInt = 0xefcdab89
let mut c0 : UInt = 0x98badcfe
let mut d0 : UInt = 0x10325476
let mut offset = 0
while offset < @pdfio.bytes_size(padded) {
let m : Array[UInt] = Array::make(16, 0)
let mut i = 0
while i < 16 {
m[i] = le_u32(padded, offset + i * 4)
i = i + 1
}
let mut a = a0
let mut b = b0
let mut c = c0
let mut d = d0
let mut idx = 0
while idx < 64 {
let mut f : UInt = 0
let mut g : Int = 0
if idx < 16 {
f = UInt::lor(UInt::land(b, c), UInt::land(UInt::lnot(b), d))
g = idx
} else if idx < 32 {
f = UInt::lor(UInt::land(d, b), UInt::land(UInt::lnot(d), c))
g = (5 * idx + 1) % 16
} else if idx < 48 {
f = UInt::lxor(UInt::lxor(b, c), d)
g = (3 * idx + 5) % 16
} else {
f = UInt::lxor(c, UInt::lor(b, UInt::lnot(d)))
g = 7 * idx % 16
}
let temp = d
let sum = add_u32(add_u32(add_u32(a, f), md5_k[idx]), m[g])
d = c
c = b
b = add_u32(b, rotl32(sum, md5_s[idx]))
a = temp
idx = idx + 1
}
a0 = add_u32(a0, a)
b0 = add_u32(b0, b)
c0 = add_u32(c0, c)
d0 = add_u32(d0, d)
offset = offset + 64
}
let out = @pdfio.mkbytes(16)
let words = [a0, b0, c0, d0]
let mut w = 0
while w < 4 {
let word = words[w]
let mut i = 0
while i < 4 {
let byte_val = (word >> (i * 8)).reinterpret_as_int()
@pdfio.bset(out, w * 4 + i, Int::land(byte_val, 0xff))
i = i + 1
}
w = w + 1
}
out
}