RIPEMD-160
Algorithm creator(s)
Hans Dobbertin, Antoon Bosselaers, Bart Preneel
PB author(s)
Greg Turgeon
Description
PBCC3/PBWIN7 implementation of the 160-bit RIPEMD cryptographic hash function. Intended to be used as a secure replacement for the 128-bit hash functions MD4, MD5, and RIPEMD.
Note
Source
https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/24092-ripemd-160-secure-hash-for-3-0-7-0?t=23455
See also
Source Code
Download source code file ripemd-160.bas (Right-click -> "Save as ...")
#IF 0
=====================================================================
RIPEMD-160 SECURE HASH
=====================================================================
The RMD160 secure hash algorithm creates a 160-bit hash of an input
string of any length. A hash is considered secure when it possesses
the following qualities: 1) Finding two input strings which hash to
the same value is considered not feasible. 2) Determining an input
string from its hash is considered not feasible.
From the RIPEMD-160 home page:
User agrees to give due credit to K.U.Leuven in scientific
publications or communications in relation with the use of the
RIPEMD-160 software as follows: RIPEMD-160 software written by
Antoon Bosselaers, available at http://www.esat.kuleuven.ac.be/~cosicart/ps/AB-9601/.
The PowerBASIC implementation appearing below is based on that of Brian
Gladman, which is available here: http://fp.gladman.plus.com/cryptography_technology/
This PB implementation is hereby placed in the public domain. Use it
as you wish. My hope is discourage reliance on home-grown encryption
schemes in favor of well-examined, strong, freely available
algorithms.
In this posting, test-bed code appears below the RMD160.BAS file
contents. All code requires PB compiler releases 3.0/7.0 or later.
All code compiles with either PBCC or PBWin. Implementation Notes
-- The algorithm operates on plaintext blocks of 64 bytes. Padding
of final blocks < 64 bytes must conform to a specific pattern and is
accomplished automatically by calling MDfinish(). The process of
hashing consists of the following essential steps:
ctx.pBuffer = strptr(target_data)
ctx.BufferLength = len(target_data)
bufflen = ctx.BufferLength
RMD160_Init ctx '<-- Initialize hashing of
do while bufflen > (%BLOCKSIZE-1) ' target_data
Compress ctx '<-- hash target_data
ctx.pBuffer = ctx.pBuffer + %BLOCKSIZE
bufflen = bufflen - %BLOCKSIZE
loop
MDfinish ctx '<-- hash last block of
' target_data
' (if any) + padding
-- Implementation here is handled through an #INCLUDE file. No global
data is employed.
-- Because of the methods of data handling required for most
encryption and hashing, PowerBASIC's LONGs should be used to assure
correct bit-level results (as well as additional speed).
Greg Turgeon 07/2002
=====================================================================
#ENDIF
%HASHLENGTH = 20 'bytes
%BLOCKSIZE = 64 'bytes
TYPE HASH_CONTEXT
pBuffer AS LONG PTR
BufferLength AS LONG
MD AS LONG PTR
MD_Buffer AS STRING * %HASHLENGTH '<-- Holds actual hash value
END TYPE
'--------------------
' Utility macros
'--------------------
'--------------------
MACRO zbs(x)=string$(x,0) 'also defined in RMD160.BAS
'--------------------
MACRO FUNCTION rotlc(xx,constant_shiftval)
retval = xx
! rol retval, constant_shiftval
END MACRO = retval
'--------------------
'RMD160 macros
'--------------------
'--------------------
MACRO Fmd(x,y,z)=((x XOR y XOR z))
'--------------------
MACRO Gmd(x,y,z)=((x AND y) OR (NOT(x) AND z))
'--------------------
MACRO Hmd(x,y,z)=((x OR NOT(y)) XOR z)
'--------------------
MACRO Imd(x,y,z)=((x AND z) OR (y AND NOT(z)))
'--------------------
MACRO Jmd(x,y,z)=(x XOR (y OR NOT(z)))
'--------------------
MACRO FFmd(a,b,c,d,e,x,s)
a=a+Fmd(b,c,d)+x
a=(rotlc(a,s))
a=a+e
c=rotlc(c,10)
END MACRO
'--------------------
MACRO GGmd(a,b,c,d,e,x,s)
a=a+Gmd(b,c,d)+(x)+&h5a827999
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
'--------------------
MACRO HHmd(a,b,c,d,e,x,s)
a=a+Hmd(b,c,d)+x+&h6ed9eba1
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
MACRO IImd(a,b,c,d,e,x,s)
a=a+Imd(b,c,d)+x+&h8f1bbcdc
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
'--------------------
MACRO JJmd(a,b,c,d,e,x,s)
a=a+Jmd(b,c,d)+x+&ha953fd4e
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
'--------------------
MACRO FFFmd(a,b,c,d,e,x,s)
a=a+Fmd(b,c,d)+x
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
'--------------------
MACRO GGGmd(a,b,c,d,e,x,s)
a=a+Gmd(b,c,d)+x+&h7a6d76e9
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
'--------------------
MACRO HHHmd(a,b,c,d,e,x,s)
a=a+Hmd(b,c,d)+(x)+&h6d703ef3
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
'--------------------
MACRO IIImd(a,b,c,d,e,x,s)
a=a+Imd(b,c,d)+x+&h5c4dd124
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
'--------------------
MACRO JJJmd(a,b,c,d,e,x,s)
a=a+Jmd(b,c,d)+x+&h50a28be6
a=rotlc(a,s)
a=a+e
c=rotlc(c,10)
END MACRO
DECLARE FUNCTION RMD160_Init(Ctx AS HASH_CONTEXT)
DECLARE FUNCTION Compress(Ctx AS HASH_CONTEXT)
DECLARE FUNCTION MDfinish(Ctx AS HASH_CONTEXT)
'====================
FUNCTION RMD160_Init(Ctx AS HASH_CONTEXT)
Ctx.MD_Buffer = zbs(%HASHLENGTH)
Ctx.MD = varptr(Ctx.MD_Buffer)
Ctx.@MD[0] = &h67452301
Ctx.@MD[1] = &hefcdab89
Ctx.@MD[2] = &h98badcfe
Ctx.@MD[3] = &h10325476
Ctx.@MD[4] = &hc3d2e1f0
END FUNCTION
'====================
FUNCTION Compress(Ctx AS HASH_CONTEXT)
LOCAL aa&, bb&, cc&, dd&, ee&, aaa&, bbb&, ccc&, ddd&, eee&, x AS LONG PTR, retval&
aa = Ctx.@MD[0] : bb = Ctx.@MD[1] : cc = Ctx.@MD[2]
dd = Ctx.@MD[3] : ee = Ctx.@MD[4]
aaa = Ctx.@MD[0] : bbb = Ctx.@MD[1] : ccc = Ctx.@MD[2]
ddd = Ctx.@MD[3] : eee = Ctx.@MD[4]
x = Ctx.pBuffer 'local copy
'-- round 1
FFmd(aa,bb,cc,dd,ee,@x[0],11)
FFmd(ee,aa,bb,cc,dd,@x[1],14)
FFmd(dd,ee,aa,bb,cc,@x[2],15)
FFmd(cc,dd,ee,aa,bb,@x[3],12)
FFmd(bb,cc,dd,ee,aa,@x[4],5)
FFmd(aa,bb,cc,dd,ee,@x[5],8)
FFmd(ee,aa,bb,cc,dd,@x[6],7)
FFmd(dd,ee,aa,bb,cc,@x[7],9)
FFmd(cc,dd,ee,aa,bb,@x[8],11)
FFmd(bb,cc,dd,ee,aa,@x[9],13)
FFmd(aa,bb,cc,dd,ee,@x[10],14)
FFmd(ee,aa,bb,cc,dd,@x[11],15)
FFmd(dd,ee,aa,bb,cc,@x[12],6)
FFmd(cc,dd,ee,aa,bb,@x[13],7)
FFmd(bb,cc,dd,ee,aa,@x[14],9)
FFmd(aa,bb,cc,dd,ee,@x[15],8)
'-- round 2
GGmd(ee,aa,bb,cc,dd,@x[7],7)
GGmd(dd,ee,aa,bb,cc,@x[4],6)
GGmd(cc,dd,ee,aa,bb,@x[13],8)
GGmd(bb,cc,dd,ee,aa,@x[1],13)
GGmd(aa,bb,cc,dd,ee,@x[10],11)
GGmd(ee,aa,bb,cc,dd,@x[6],9)
GGmd(dd,ee,aa,bb,cc,@x[15],7)
GGmd(cc,dd,ee,aa,bb,@x[3],15)
GGmd(bb,cc,dd,ee,aa,@x[12],7)
GGmd(aa,bb,cc,dd,ee,@x[0],12)
GGmd(ee,aa,bb,cc,dd,@x[9],15)
GGmd(dd,ee,aa,bb,cc,@x[5],9)
GGmd(cc,dd,ee,aa,bb,@x[2],11)
GGmd(bb,cc,dd,ee,aa,@x[14],7)
GGmd(aa,bb,cc,dd,ee,@x[11],13)
GGmd(ee,aa,bb,cc,dd,@x[8],12)
'-- round 3
HHmd(dd,ee,aa,bb,cc,@x[3],11)
HHmd(cc,dd,ee,aa,bb,@x[10],13)
HHmd(bb,cc,dd,ee,aa,@x[14],6)
HHmd(aa,bb,cc,dd,ee,@x[4],7)
HHmd(ee,aa,bb,cc,dd,@x[9],14)
HHmd(dd,ee,aa,bb,cc,@x[15],9)
HHmd(cc,dd,ee,aa,bb,@x[8],13)
HHmd(bb,cc,dd,ee,aa,@x[1],15)
HHmd(aa,bb,cc,dd,ee,@x[2],14)
HHmd(ee,aa,bb,cc,dd,@x[7],8)
HHmd(dd,ee,aa,bb,cc,@x[0],13)
HHmd(cc,dd,ee,aa,bb,@x[6],6)
HHmd(bb,cc,dd,ee,aa,@x[13],5)
HHmd(aa,bb,cc,dd,ee,@x[11],12)
HHmd(ee,aa,bb,cc,dd,@x[5],7)
HHmd(dd,ee,aa,bb,cc,@x[12],5)
'-- round 4
IImd(cc,dd,ee,aa,bb,@x[1],11)
IImd(bb,cc,dd,ee,aa,@x[9],12)
IImd(aa,bb,cc,dd,ee,@x[11],14)
IImd(ee,aa,bb,cc,dd,@x[10],15)
IImd(dd,ee,aa,bb,cc,@x[0],14)
IImd(cc,dd,ee,aa,bb,@x[8],15)
IImd(bb,cc,dd,ee,aa,@x[12],9)
IImd(aa,bb,cc,dd,ee,@x[4],8)
IImd(ee,aa,bb,cc,dd,@x[13],9)
IImd(dd,ee,aa,bb,cc,@x[3],14)
IImd(cc,dd,ee,aa,bb,@x[7],5)
IImd(bb,cc,dd,ee,aa,@x[15],6)
IImd(aa,bb,cc,dd,ee,@x[14],8)
IImd(ee,aa,bb,cc,dd,@x[5],6)
IImd(dd,ee,aa,bb,cc,@x[6],5)
IImd(cc,dd,ee,aa,bb,@x[2],12)
'-- round 5
JJmd(bb,cc,dd,ee,aa,@x[4],9)
JJmd(aa,bb,cc,dd,ee,@x[0],15)
JJmd(ee,aa,bb,cc,dd,@x[5],5)
JJmd(dd,ee,aa,bb,cc,@x[9],11)
JJmd(cc,dd,ee,aa,bb,@x[7],6)
JJmd(bb,cc,dd,ee,aa,@x[12],8)
JJmd(aa,bb,cc,dd,ee,@x[2],13)
JJmd(ee,aa,bb,cc,dd,@x[10],12)
JJmd(dd,ee,aa,bb,cc,@x[14],5)
JJmd(cc,dd,ee,aa,bb,@x[1],12)
JJmd(bb,cc,dd,ee,aa,@x[3],13)
JJmd(aa,bb,cc,dd,ee,@x[8],14)
JJmd(ee,aa,bb,cc,dd,@x[11],11)
JJmd(dd,ee,aa,bb,cc,@x[6],8)
JJmd(cc,dd,ee,aa,bb,@x[15],5)
JJmd(bb,cc,dd,ee,aa,@x[13],6)
'-- parallel round 1
JJJmd(aaa,bbb,ccc,ddd,eee,@x[5],8)
JJJmd(eee,aaa,bbb,ccc,ddd,@x[14],9)
JJJmd(ddd,eee,aaa,bbb,ccc,@x[7],9)
JJJmd(ccc,ddd,eee,aaa,bbb,@x[0],11)
JJJmd(bbb,ccc,ddd,eee,aaa,@x[9],13)
JJJmd(aaa,bbb,ccc,ddd,eee,@x[2],15)
JJJmd(eee,aaa,bbb,ccc,ddd,@x[11],15)
JJJmd(ddd,eee,aaa,bbb,ccc,@x[4],5)
JJJmd(ccc,ddd,eee,aaa,bbb,@x[13],7)
JJJmd(bbb,ccc,ddd,eee,aaa,@x[6],7)
JJJmd(aaa,bbb,ccc,ddd,eee,@x[15],8)
JJJmd(eee,aaa,bbb,ccc,ddd,@x[8],11)
JJJmd(ddd,eee,aaa,bbb,ccc,@x[1],14)
JJJmd(ccc,ddd,eee,aaa,bbb,@x[10],14)
JJJmd(bbb,ccc,ddd,eee,aaa,@x[3],12)
JJJmd(aaa,bbb,ccc,ddd,eee,@x[12],6)
'-- parallel round 2
IIImd(eee,aaa,bbb,ccc,ddd,@x[6],9)
IIImd(ddd,eee,aaa,bbb,ccc,@x[11],13)
IIImd(ccc,ddd,eee,aaa,bbb,@x[3],15)
IIImd(bbb,ccc,ddd,eee,aaa,@x[7],7)
IIImd(aaa,bbb,ccc,ddd,eee,@x[0],12)
IIImd(eee,aaa,bbb,ccc,ddd,@x[13],8)
IIImd(ddd,eee,aaa,bbb,ccc,@x[5],9)
IIImd(ccc,ddd,eee,aaa,bbb,@x[10],11)
IIImd(bbb,ccc,ddd,eee,aaa,@x[14],7)
IIImd(aaa,bbb,ccc,ddd,eee,@x[15],7)
IIImd(eee,aaa,bbb,ccc,ddd,@x[8],12)
IIImd(ddd,eee,aaa,bbb,ccc,@x[12],7)
IIImd(ccc,ddd,eee,aaa,bbb,@x[4],6)
IIImd(bbb,ccc,ddd,eee,aaa,@x[9],15)
IIImd(aaa,bbb,ccc,ddd,eee,@x[1],13)
IIImd(eee,aaa,bbb,ccc,ddd,@x[2],11)
'-- parallel round 3
HHHmd(ddd,eee,aaa,bbb,ccc,@x[15],9)
HHHmd(ccc,ddd,eee,aaa,bbb,@x[5],7)
HHHmd(bbb,ccc,ddd,eee,aaa,@x[1],15)
HHHmd(aaa,bbb,ccc,ddd,eee,@x[3],11)
HHHmd(eee,aaa,bbb,ccc,ddd,@x[7],8)
HHHmd(ddd,eee,aaa,bbb,ccc,@x[14],6)
HHHmd(ccc,ddd,eee,aaa,bbb,@x[6],6)
HHHmd(bbb,ccc,ddd,eee,aaa,@x[9],14)
HHHmd(aaa,bbb,ccc,ddd,eee,@x[11],12)
HHHmd(eee,aaa,bbb,ccc,ddd,@x[8],13)
HHHmd(ddd,eee,aaa,bbb,ccc,@x[12],5)
HHHmd(ccc,ddd,eee,aaa,bbb,@x[2],14)
HHHmd(bbb,ccc,ddd,eee,aaa,@x[10],13)
HHHmd(aaa,bbb,ccc,ddd,eee,@x[0],13)
HHHmd(eee,aaa,bbb,ccc,ddd,@x[4],7)
HHHmd(ddd,eee,aaa,bbb,ccc,@x[13],5)
'-- parallel round 4
GGGmd(ccc,ddd,eee,aaa,bbb,@x[8],15)
GGGmd(bbb,ccc,ddd,eee,aaa,@x[6],5)
GGGmd(aaa,bbb,ccc,ddd,eee,@x[4],8)
GGGmd(eee,aaa,bbb,ccc,ddd,@x[1],11)
GGGmd(ddd,eee,aaa,bbb,ccc,@x[3],14)
GGGmd(ccc,ddd,eee,aaa,bbb,@x[11],14)
GGGmd(bbb,ccc,ddd,eee,aaa,@x[15],6)
GGGmd(aaa,bbb,ccc,ddd,eee,@x[0],14)
GGGmd(eee,aaa,bbb,ccc,ddd,@x[5],6)
GGGmd(ddd,eee,aaa,bbb,ccc,@x[12],9)
GGGmd(ccc,ddd,eee,aaa,bbb,@x[2],12)
GGGmd(bbb,ccc,ddd,eee,aaa,@x[13],9)
GGGmd(aaa,bbb,ccc,ddd,eee,@x[9],12)
GGGmd(eee,aaa,bbb,ccc,ddd,@x[7],5)
GGGmd(ddd,eee,aaa,bbb,ccc,@x[10],15)
GGGmd(ccc,ddd,eee,aaa,bbb,@x[14],8)
'-- parallel round 5
FFFmd(bbb,ccc,ddd,eee,aaa,@x[12],8)
FFFmd(aaa,bbb,ccc,ddd,eee,@x[15],5)
FFFmd(eee,aaa,bbb,ccc,ddd,@x[10],12)
FFFmd(ddd,eee,aaa,bbb,ccc,@x[4],9)
FFFmd(ccc,ddd,eee,aaa,bbb,@x[1],12)
FFFmd(bbb,ccc,ddd,eee,aaa,@x[5],5)
FFFmd(aaa,bbb,ccc,ddd,eee,@x[8],14)
FFFmd(eee,aaa,bbb,ccc,ddd,@x[7],6)
FFFmd(ddd,eee,aaa,bbb,ccc,@x[6],8)
FFFmd(ccc,ddd,eee,aaa,bbb,@x[2],13)
FFFmd(bbb,ccc,ddd,eee,aaa,@x[13],6)
FFFmd(aaa,bbb,ccc,ddd,eee,@x[14],5)
FFFmd(eee,aaa,bbb,ccc,ddd,@x[0],15)
FFFmd(ddd,eee,aaa,bbb,ccc,@x[3],13)
FFFmd(ccc,ddd,eee,aaa,bbb,@x[9],11)
FFFmd(bbb,ccc,ddd,eee,aaa,@x[11],11)
'-- combine results
ddd = ddd + cc + Ctx.@MD[1]
Ctx.@MD[1] = Ctx.@MD[2] + dd + eee
Ctx.@MD[2] = Ctx.@MD[3] + ee + aaa
Ctx.@MD[3] = Ctx.@MD[4] + aa + bbb
Ctx.@MD[4] = Ctx.@MD[0] + bb + ccc
Ctx.@MD[0] = ddd
END FUNCTION
'=========================
FUNCTION MakePadding$(BYVAL TotalBytes&)
LOCAL padding$, buffbits&&, padbytes&
buffbits = TotalBytes * 8
padding = zbs(8)
poke$ strptr(padding), peek$(varptr(buffbits),8)
padbytes = %BLOCKSIZE - ((TotalBytes+9) AND (%BLOCKSIZE-1))
function = chr$(&h80) + zbs(padbytes) + padding
END FUNCTION
'====================
FUNCTION MDfinish(Ctx AS HASH_CONTEXT)
LOCAL x_buffer$, x AS BYTE PTR, retval&, padding$, bytesleft&
x_buffer$ = zbs(%BLOCKSIZE) : x = strptr(x_buffer$)
padding = MakePadding$(Ctx.BufferLength)
bytesleft = Ctx.BufferLength AND 63
poke$ x, peek$(Ctx.pBuffer, bytesleft)
poke$ x+bytesleft, padding
Ctx.pBuffer = x
Compress Ctx
END FUNCTION
'-- end RMD160.BAS
'=====================================================================
' RIPEMD-160 Test Bed code
' Compiles with either PBWIN 7.0+ or PBCC 3.0+
'=====================================================================
#COMPILE EXE
#REGISTER NONE
#DIM ALL
'============
DEFLNG A-Z
'--------------------
'-- Utility macros
'--------------------
#IF %def(%pb_win32)
MACRO eol=$CR
MACRO mbox(t)=msgbox t
#ELSEIF %def(%pb_cc32)
MACRO eol=$CRLF
MACRO mbox(t)=stdout t
#ENDIF
'--------------------
MACRO EnterCC
#IF %def(%pb_cc32)
LOCAL launched&
if (cursory = 1) and (cursorx = 1) then launched = -1
#ENDIF
END MACRO
'--------------------
MACRO ExitCC
#IF %def(%pb_cc32)
if launched then
input flush
stdout "Press any key to end"
waitkey$
end if
#ENDIF
END MACRO
''--------------------
'MACRO zbs(x)=string$(x,0) 'also defined in RMD160.BAS
'%HASHLENGTH = 20 'bytes
'%BLOCKSIZE = 64 'bytes
'TYPE HASH_CONTEXT
' pBuffer AS LONG PTR
' BufferLength AS LONG
' MD AS LONG PTR
' MD_Buffer AS STRING * %HASHLENGTH
'END TYPE
#INCLUDE "RMD160.BAS"
DECLARE FUNCTION Hex2Show$(Buffer$)
'====================
FUNCTION PBMain&()
LOCAL i&, plain$, hash$, shouldbe$, t$
LOCAL ctx AS HASH_CONTEXT ' defined in RMD160.BAS
EnterCC
'-- Standard RIPEMD-160 test vectors:
plain = "" 'empty string
hash = zbs(%HASHLENGTH)
shouldbe = chr$(&h9c,&h11,&h85,&ha5,&hc5,&he9,&hfc,&h54,&h61,&h28,&h08,&h97,&h7e,&he8,&hf5,&h48,&hb2,&h25,&h8d,&h31)
t = "plain: " + plain + eol
gosub DoRMD160
t = t + "hash: " + Hex2Show$(hash) + eol
t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol + eol
plain = "a"
hash = zbs(%HASHLENGTH)
shouldbe = chr$(&h0b,&hdc,&h9d,&h2d,&h25,&h6b,&h3e,&he9,&hda,&hae,&h34,&h7b,&he6,&hf4,&hdc,&h83,&h5a,&h46,&h7f,&hfe)
t = T + "plain: " + plain + eol
gosub DoRMD160
t = t + "hash: " + Hex2Show$(hash) + eol
t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol + eol
plain = "message digest"
hash = zbs(%HASHLENGTH)
shouldbe = chr$(&h5d,&h06,&h89,&hef,&h49,&hd2,&hfa,&he5,&h72,&hb8,&h81,&hb1,&h23,&ha8,&h5f,&hfa,&h21,&h59,&h5f,&h36)
t = t + "plain: " + plain + eol
gosub DoRMD160
t = t + "hash: " + Hex2Show$(hash) + eol
t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol + eol
plain = repeat$(1000000,"a")
hash = zbs(%HASHLENGTH)
shouldbe = chr$(&h52,&h78,&h32,&h43,&hc1,&h69,&h7b,&hdb,&he1,&h6d,&h37,&hf9,&h7f,&h68,&hf0,&h83,&h25,&hdc,&h15,&h28)
t = t + "Million chars test" + eol
gosub DoRMD160
t = t + "hash: " + Hex2Show$(hash) + eol
t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol + eol
mbox(t)
'============
ExitPBMain:
ExitCC
exit function
'============
DoRMD160:
REGISTER bufflen&
ctx.pBuffer = strptr(plain)
ctx.BufferLength = len(plain)
RMD160_Init ctx
bufflen = ctx.BufferLength
do while bufflen > (%BLOCKSIZE-1)
Compress ctx
ctx.pBuffer = ctx.pBuffer + %BLOCKSIZE
bufflen = bufflen - %BLOCKSIZE
loop
MDfinish ctx
hash = peek$(Ctx.MD, %HASHLENGTH)
RETURN
END FUNCTION
'====================
FUNCTION Hex2Show$(Buffer$)
REGISTER i&
LOCAL t$, b AS BYTE PTR
b = strptr(Buffer$)
for i = 0 to len(Buffer$)-1
t = t + hex$(@b[i],2) + " "
next i
function = t
END FUNCTION
'-- end TESTBED.BAS