RosettaCodeData/Task/RIPEMD-160/Phix/ripemd-160-2.phix
2018-08-17 15:15:24 +01:00

108 lines
4.6 KiB
Text

--
-- builtins\ripemd160.e
-- ====================
--
function rol(atom v, integer n)
-- Programming note: this use of #ilASM{} is more for expediency than efficiency
#ilASM{ mov eax,[v]
call :%pLoadMint
mov ecx,[n]
rol eax,cl
lea edi,[v]
call :%pStoreMint }
return v
end function
constant K = {#00000000,#5A827999,#6ED9EBA1,#8F1BBCDC,#A953FD4E},
KK = {#50A28BE6,#5C4DD124,#6D703EF3,#7A6D76E9,#00000000},
r = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 },
rr = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 },
s = {11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 },
ss = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 }
global function ripemd160(string message, bool asString=true, atom pMem=NULL)
--
-- Calculate the ripe-md-160 checksum.
--
-- if asString is true (the default), returns a string representation of the
-- checksum (and pMem is ignored)
-- if asString is false, returns pMem (for want of anything better), which
-- must be a non-NULL pointer to at least 20 bytes of memory.
--
atom h0 = #67452301,
h1 = #EFCDAB89,
h2 = #98BADCFE,
h3 = #10325476,
h4 = #C3D2E1F0,
mraw, t, tt
integer l = length(message),
padding = 64 - mod(l+1,64)
if padding<8 then padding += 64 end if
message &= #80 & repeat('\0',padding-8)
& int_to_bytes(l*8,8)
#ilASM{ mov eax,[message]
lea edi,[mraw]
shl eax,2 -- ref -> raw address
call :%pStoreMint }
for i=0 to length(message)-64 by 64 do
atom {a, b, c, d, e} = {h0, h1, h2, h3, h4}
atom {aa, bb, cc, dd, ee} = {h0, h1, h2, h3, h4}
for j = 1 to 80 do
integer k = floor((j-1)/16)
switch k
case 0:
t = xor_bits(xor_bits(b, c), d)
tt = xor_bits(bb,or_bits(cc,not_bits(dd)))
case 1:
t = or_bits(and_bits(b,c),and_bits(not_bits(b),d))
tt = or_bits(and_bits(bb,dd),and_bits(cc,not_bits(dd)))
case 2:
t = xor_bits(or_bits(b,not_bits(c)),d)
tt = xor_bits(or_bits(bb,not_bits(cc)),dd)
case 3:
t = or_bits(and_bits(b,d),and_bits(c,not_bits(d)))
tt = or_bits(and_bits(bb,cc),and_bits(not_bits(bb),dd))
case 4:
t = xor_bits(b,or_bits(c,not_bits(d)))
tt = xor_bits(xor_bits(bb, cc), dd)
end switch
t = rol( a + t + peek4u(mraw+i+ r[j]*4) + K[k+1], s[j]) + e
tt = rol(aa + tt + peek4u(mraw+i+rr[j]*4) + KK[k+1], ss[j]) + ee
{a, e, d, c, b } = {e, d, rol(c, 10), b, t }
{aa,ee,dd,cc,bb} = {ee,dd,rol(cc, 10),bb,tt}
end for
{h0, h1, h2, h3, h4} = {h1+c+dd, h2+d+ee, h3+e+aa, h4+a+bb, h0+b+cc}
end for
if not asString then
if pMem=NULL then ?9/0 end if
poke4(pMem,{h0,h1,h2,h3,h4})
return pMem
end if
atom mem = allocate(20,true)
poke4(mem,{h0,h1,h2,h3,h4})
string res = ""
for i=1 to 20 do
res &= sprintf("%02X",peek(mem+i-1))
end for
return res
end function