RIPEMD-160 is another hash function; it computes a 160-bit message digest.

There is a RIPEMD-160 home page, with test vectors and pseudocode for RIPEMD-160.
For padding the message, RIPEMD-160 acts like MD4 (RFC 1320).

Find the RIPEMD-160 message digest of a string of octets.
Use the ASCII encoded string “Rosetta Code”.
You may either call an RIPEMD-160 library, or implement RIPEMD-160 in your language.

 
Module Checkit {
	Function Prepare_RiPeMd_160 {
		Dim Base 0,  K(5), K1(5)
		K(0)=0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E
		K1(0)=0x50A28BE6,0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000
		Dim Base 0,r(80), r1(80), s(80), s1(80)
		r(0)=0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
		r(16)=7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8
		r(32)= 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12
		r(48)=1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2
		r(64)=4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
		k=r() : k*=4   ' k is a pointer to array. We have to multiply to make them offsets
 
		r1(0)=5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12
		r1(16)=6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2
		r1(32)=15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13
		r1(48)=8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14
		r1(64)=12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
 
		k=r1() : k*=4
 
		s(0)=11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8
		s(16)=7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12
		s(32)=11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5
		s(48)=11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12
		s(64)=9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
 
		s1(0)=8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6
		s1(16)=9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11
		s1(32)=9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5
		s1(48)=15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8
		s1(64)=8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
 
		Dim Base 0, T(5), TT(5)
		T(0)=lambda ->binary.xor(binary.xor(number,number),number)
		T(1)=lambda (B,C,D)->binary.or(binary.and(B,C), binary.and(binary.not(B), D))
		T(2)=lambda ->binary.xor(binary.or(number, binary.not(number)), number)
		T(3)=lambda (B,C,D)->binary.or(binary.and(B,D), binary.and(C,binary.not(D)))
		T(4)=lambda ->binary.xor(number, binary.or(number, binary.not(number)))
 
		\\ no need for variables we read form stack with number
		TT(0)=lambda ->binary.xor(number, binary.or(number, binary.not(number)))
		TT(1)=lambda (BB,CC,DD)->binary.or(binary.and(BB,DD), binary.and(CC,binary.not(DD)))	
		TT(2)=lambda ->binary.xor(binary.or(number, binary.not(number)), number)
		TT(3)=lambda (BB,CC,DD)->binary.or(binary.and(BB,CC), binary.and(binary.not(BB),DD))	
		TT(4)=lambda ->binary.xor(binary.xor(number,number),number)
 
		\\ return of this function is a lambda function
		\\ all arrays are closures to this lambda
		=lambda K(),K1(),TT(), T(),r(),r1(), s(), s1() (&message$, ansi as boolean=true, ansiid=1033)-> {
			set fast!
			def h0 = 0x67452301, h1 = 0xEFCDAB89, h2 = 0x98BADCFE
			def h3 = 0x10325476, h4 = 0xC3D2E1F0
			def i, j, l, padding, l1, blocks, acc, f64 as boolean=true, oldid
			if ansi then oldid=locale : locale ansiid
			\\ we use a buffer of 64 bytes
			buffer clear message as byte*64
			l=len(message$)*if(ansi->1,2 )
			if binary.and(l,63)>55 then  padding=64 
			padding+= 64 - (l Mod 64)
			l1=padding+l+1
 
			f64=binary.and(l,63)<>0
 
			blocks=l1 div 64
rem
			Print "blocks:";blocks
			\\ now prepare the buffer
			PrepareBuffer()
			def decimal  A, B, C, D, E, AA, BB, CC, DD, EE, T, TT
			do
			A  = h0 : B  = h1 : C  = h2 : D  = h3 : E  = h4
			AA = h0 : BB = h1 : CC = h2 : DD = h3 : EE = h4
			for J=0 to 79 {
				JJ=J DIV 16
				PUSH binary.add(Binary.Rotate(binary.add(A,T(JJ)(B,C,D),eval(message ,r(j) as long),k(jj)), s(j)), e)
				A = E : E = D : D = Binary.Rotate(C, 10) : C = B : READ B 
				PUSH binary.add(Binary.Rotate(binary.add(AA,TT(JJ)(BB,CC,DD),eval(message, r1(j) as long),k1(jj)),s1(j)),EE)
				AA = EE : EE = DD : DD = Binary.Rotate(CC, 10) : CC = BB : READ BB
			}
			push binary.add(h1, C, DD)
			h1 = binary.add(h2, D, EE)
			h2 = binary.add(h3, E, AA)
			h3 = binary.add(h4, A, BB)
			h4 = binary.add(h0, B, CC)
			Read h0
			blocks--
rem
			print over $(0,8), blocks : Refresh
			if blocks=0 then exit
			PrepareBuffer()
			always
rem
			print
			buffer ans as byte*20
			\\ we put ulong (long is ulong in buffers)
			Return ans, 0:=h0 as long, 4:=h1 as long,8:=h2 as long, 12:=h3 as long, 16:=h4 as long
			=ans
			if ansi then locale oldid
			set fast
			Sub PrepareBuffer()
 
				if l-acc>=64 then
					LoadPart(64)
				else.if blocks=1 then
					return message, 0:=string$(chr$(0),32)
					if l-acc=0 and f64 then
						Return message, 56:=l*8 as long, 60 :=binary.shift(l,-29) as long
					else
						Return message, l-acc:=0x80, 56:=l*8 as long, 60 :=binary.shift(l,-29) as long
						if l>acc then LoadPart(l-acc)
					end if
				else
					Return message, l-acc:=0x80
					LoadPart(l-acc)
				end if
			End Sub
			sub LoadPart(many)
				\\ str$() convert to ansi, one byte per character
				\\ using 1033 as Ansi language
				if ansi then
					Return message, 0:=str$(mid$(message$,1+acc, many))
				else
					Return message, 0:=mid$(message$, 1+acc, many)
				end if
				acc+=many
			end sub
		}
	}
	Module TestHash (RIPEMD){
		Flush
		\\ push data to stack of values, as fifo (each entry append to end of stack)
		Data "b3be159860842cebaa7174c8fff0aa9e50a5199f","Rosetta Code"
		Data "9c1185a5c5e9fc54612808977ee8f548b2258d31",""
		Data "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe","a"
		Data "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc","abc"
		Data "5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"
		Data "f71c27109c692c1b56bbdceb5b9d2865b3708dbc","abcdefghijklmnopqrstuvwxyz"
		Data "b0e20b6e3116640286ed3a87a5713079b21f5189"
		Data "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
		Data "9b752e45573d4b39f4dbd3323cab82bf63326bfb", String$("1234567890",8)
rem		Data "52783243c1697bdbe16d37f97f68f08325dc1528", String$("a",1000000)
 
		While not empty
			Read check$, text$
			Print "RIPEMD160 for ";quote$(Left$(if$(len(text$)>30->left$(text$,27)+"...",  text$),30))
			\\ pass text$ by reference
			Display(RIPEMD(&text$))
		End While
 
		sub Display(ans)
			local answer$
			for i=0 to len(ans)-1
				answer$+=hex$(eval(ans,i),1)
			next i
			Print lcase$(answer$)
			Print lcase$(answer$)=check$
		end sub
	}
	TestHash Prepare_RiPeMd_160()	
}
Checkit
 