Find the MD4 message digest of a string of octets.
Use the ASCII encoded string “Rosetta Code” (without quotes).
You may either call an MD4 library, or implement MD4 in your language.

MD4 is an obsolete hash function that computes a 128-bit message digest that sometimes appears in obsolete protocols.

RFC 1320 specifies the MD4 algorithm. RFC 6150 declares that MD4 is obsolete.

--
-- demo\rosetta\md4.exw
-- ====================
--
-- Non-optimised. If there is a genuine need for something faster, I can give #ilASM a bash.
-- MD4 is an obsolete hash function that computes a 128-bit message digest that sometimes appears in obsolete protocols.
-- Even the replacement, MD5 is now considered severly comprimised.
--
without js -- (allocate/poke/peek)
function r32(atom a)
    if a<0 then a+=#100000000 end if
    return remainder(a,#100000000)
end function

function rol(atom word, integer bits)
-- left rotate the bits of a 32-bit number by the specified number of bits
    word = r32(word)    -- trim to a 32-bit uint again
    return r32(word*power(2,bits))+floor(word/power(2,32-bits))
end function

function f(atom x,y,z)
    return or_bits(and_bits(x,y),and_bits(not_bits(x),z))
end function

function g(atom x,y,z)
    return or_all({r32(and_bits(x,y)),and_bits(x,z),and_bits(y,z)})
end function

function h(atom x,y,z)
    return xor_bits(r32(xor_bits(x,y)),z)
end function

function md4(sequence data)
    integer bytes_to_add = 64-remainder(length(data)+9,64)
    if bytes_to_add=64 then bytes_to_add = 0 end if
    data = data&#80&repeat(0,bytes_to_add)&
           int_to_bytes(length(data)*8,8)
 
    atom a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476
 
    atom m64 = allocate(64,true)
    integer i
    for x=1 to length(data)-1 by 64 do
        poke(m64,data[x..x+63])
        sequence z = peek4u({m64,16})
        atom a2 = a, b2 = b, c2 = c, d2 = d
        for i=0 to 12 by 4 do
            a = rol(a + f(b, c, d) + z[i+1],  3)
            d = rol(d + f(a, b, c) + z[i+2],  7)
            c = rol(c + f(d, a, b) + z[i+3], 11)
            b = rol(b + f(c, d, a) + z[i+4], 19)
        end for
        for i=1 to 4 do
            a = rol(a + g(b, c, d) + z[i+0]  + 0x5a827999,  3)
            d = rol(d + g(a, b, c) + z[i+4]  + 0x5a827999,  5)
            c = rol(c + g(d, a, b) + z[i+8]  + 0x5a827999,  9)
            b = rol(b + g(c, d, a) + z[i+12] + 0x5a827999, 13)
        end for
        for j=1 to 4 do
            i = {1, 3, 2, 4}[j]
            a = rol(a + h(b, c, d) + z[i+0]  + 0x6ed9eba1,  3)
            d = rol(d + h(a, b, c) + z[i+8]  + 0x6ed9eba1,  9)
            c = rol(c + h(d, a, b) + z[i+4]  + 0x6ed9eba1, 11)
            b = rol(b + h(c, d, a) + z[i+12] + 0x6ed9eba1, 15)
        end for
        a = r32(a+a2)
        b = r32(b+b2)
        c = r32(c+c2)
        d = r32(d+d2)
    end for
    poke4(m64,{a,b,c,d})
    return peek({m64,16})
end function 

function hexify(sequence s)
    for i=1 to length(s) do
        s[i] = sprintf("%02X",s[i])
    end for
    return join(s,"")
end function

?hexify(md4("Rosetta Code"))

{} = wait_key()
