108 lines
4.6 KiB
Text
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
|