Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
239
Task/MD5-Implementation/OoRexx/md5-implementation.rexx
Normal file
239
Task/MD5-Implementation/OoRexx/md5-implementation.rexx
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
#!/usr/bin/env rexx
|
||||
|
||||
/* Expected results:
|
||||
0xd41d8cd98f00b204e9800998ecf8427e <== ""
|
||||
0x0cc175b9c0f1b6a831c399e269772661 <== "a"
|
||||
0x900150983cd24fb0d6963f7d28e17f72 <== "abc"
|
||||
0xf96b697d7cb7938d525a2f31aaf161d0 <== "message digest"
|
||||
0xc3fcd3d76192e4007dfb496cca67e13b <== "abcdefghijklmnopqrstuvwxyz"
|
||||
0xd174ab98d277d9f5a5611c2c9f419d9f <== "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
0x57edf4a22be3c955ac49da2e2107b67a <== "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
*/
|
||||
|
||||
md5 = .md5~new; md5~update(""); say md5~digest
|
||||
md5 = .md5~new; md5~update("a"); say md5~digest
|
||||
md5 = .md5~new; md5~update("abc"); say md5~digest
|
||||
md5 = .md5~new; md5~update("message digest"); say md5~digest
|
||||
md5 = .md5~new("abcdefghijklmnopqrstuvwxyz"); say md5~digest
|
||||
md5 = .md5~new("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); md5~update("abcdefghijklmnopqrstuvwxyz0123456789"); say md5~digest
|
||||
md5 = .md5~new; md5~update("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); say md5~digest
|
||||
|
||||
-- requires OORexx 4.2.0 or later
|
||||
-- standard numeric digits of 9 is not enough in this case
|
||||
::options digits 20
|
||||
|
||||
-- Implementation mainly based on pseudocode in https://en.wikipedia.org/wiki/MD5
|
||||
::class md5 public
|
||||
|
||||
::method init
|
||||
expose a0 b0 c0 d0 count buffer index K. s -- instance variables
|
||||
use strict arg chunk=""
|
||||
-- Initialize message digest
|
||||
a0 = .int32~new('67452301'x,"C") -- A
|
||||
b0 = .int32~new('efcdab89'x,"C") -- B
|
||||
c0 = .int32~new('98badcfe'x,"C") -- C
|
||||
d0 = .int32~new('10325476'x,"C") -- D
|
||||
-- The 512 bit chunk buffer
|
||||
buffer = .mutablebuffer~new('00'x~copies(64),64)
|
||||
-- The position in the buffer to insert new input
|
||||
index = 1
|
||||
-- message bytecount
|
||||
count = 0
|
||||
-- initialize leftrotate amounts
|
||||
nrs = .array~of(7,12,17,22)
|
||||
s = nrs~union(nrs)~union(nrs)~union(nrs)
|
||||
nrs = .array~of(5,9,14,20)
|
||||
s = s~union(nrs)~union(nrs)~union(nrs)~union(nrs)
|
||||
nrs = .array~of(4,11,16,23)
|
||||
s = s~union(nrs)~union(nrs)~union(nrs)~union(nrs)
|
||||
nrs = .array~of(6,10,15,21)
|
||||
s = s~union(nrs)~union(nrs)~union(nrs)~union(nrs)
|
||||
-- initialize sinus derived constants.
|
||||
-- sin function from RXMath Library shipped with OORexx
|
||||
-- see ::routine directive at the end of the code
|
||||
do i=0 to 63
|
||||
K.i = .int32~new(((2**32)*(sin(i+1,16,R)~abs))~floor)
|
||||
end
|
||||
-- process initial string if any
|
||||
self~update(chunk)
|
||||
exit
|
||||
|
||||
::method update
|
||||
expose a0 b0 c0 d0 count buffer index K. s -- instance variables
|
||||
use strict arg chunk
|
||||
count += chunk~length
|
||||
if chunk~length<65-index then do
|
||||
buffer~overlay(chunk,index)
|
||||
index += chunk~length
|
||||
end
|
||||
else do
|
||||
split = 65-index+1
|
||||
parse var chunk part =(split) chunk
|
||||
buffer~overlay(part,index)
|
||||
index = 65
|
||||
end
|
||||
-- Only process completely filled buffer
|
||||
do while index=65
|
||||
A = a0
|
||||
B = b0
|
||||
C = c0
|
||||
D = d0
|
||||
do i=0 to 63
|
||||
select
|
||||
when i<16 then do
|
||||
F = D~xor(B~and(C~xor(D)))
|
||||
g = i
|
||||
end
|
||||
when i<32 then do
|
||||
F = C~xor(D~and(B~xor(C)))
|
||||
g = (5*i+1)//16
|
||||
end
|
||||
when i<48 then do
|
||||
F = B~xor(C)~xor(D)
|
||||
g = (3*i+5)//16
|
||||
end
|
||||
otherwise do
|
||||
F = C~xor(B~or(D~xor(.int32~new('ffffffff'x,"C"))))
|
||||
g = (7*i)//16
|
||||
end
|
||||
end
|
||||
M = .int32~new(buffer~substr(g*4+1,4)~reverse,"C") -- 32bit word in little-endian
|
||||
dTemp = D
|
||||
D = C
|
||||
C = B
|
||||
B = (B + (A+F+K.i+M)~bitrotate(s[i+1]))
|
||||
A = dTemp
|
||||
end
|
||||
a0 = a0+A
|
||||
b0 = b0+B
|
||||
c0 = c0+C
|
||||
d0 = d0+D
|
||||
parse var chunk part 65 chunk
|
||||
index = part~length+1
|
||||
buffer~overlay(part,1,part~length)
|
||||
end
|
||||
exit
|
||||
|
||||
::method digest
|
||||
expose a0 b0 c0 d0 count buffer index K s -- instance variables
|
||||
padlen = 64
|
||||
if index<57 then padlen = 57-index
|
||||
if index>57 then padlen = 121-index
|
||||
padding = '00'x~copies(padlen)~bitor('80'x)
|
||||
bitcount = count*8//2**64
|
||||
lowword = bitcount//2**32
|
||||
hiword = bitcount%2**32
|
||||
lowcount = lowword~d2c(4)~reverse -- make it little-endian
|
||||
hicount = hiword~d2c(4)~reverse -- make it little-endian
|
||||
self~update(padding || lowcount || hicount)
|
||||
return a0~string || b0~string || c0~string || d0~string
|
||||
|
||||
-- A convenience class to encapsulate operations on non OORexx-like
|
||||
-- things such as little-endian 32-bit words
|
||||
::class int32 public
|
||||
|
||||
::attribute arch class
|
||||
|
||||
::method init class
|
||||
self~arch = "little-endian" -- can be adapted for multiple architectures
|
||||
|
||||
-- Method to create an int32 like object
|
||||
-- Input can be a OORexx whole number (type="I") or
|
||||
-- a character string of 4 bytes (type="C")
|
||||
-- input truncated or padded to 32-bit word/string
|
||||
::method init
|
||||
expose char4 int32
|
||||
use strict arg input, type="Integer"
|
||||
-- type must be one of "I"nteger or "C"haracter
|
||||
t = type~subchar(1)~upper
|
||||
select
|
||||
when t=='I' then do
|
||||
char4 = input~d2c(4)
|
||||
int32 = char4~c2d
|
||||
end
|
||||
when t=='C' then do
|
||||
char4 = input~right(4,'00'x)
|
||||
int32 = char4~c2d
|
||||
end
|
||||
otherwise do
|
||||
raise syntax 93.915 array("IC",type)
|
||||
end
|
||||
end
|
||||
exit
|
||||
|
||||
::method xor -- wrapper for OORexx bitxor method
|
||||
expose char4
|
||||
use strict arg other
|
||||
return .int32~new(char4~bitxor(other~char),"C")
|
||||
|
||||
::method and -- wrapper for OORexx bitand method
|
||||
expose char4
|
||||
use strict arg other
|
||||
return .int32~new(char4~bitand(other~char),"C")
|
||||
|
||||
::method or -- wrapper for OORexx bitor method
|
||||
expose char4
|
||||
use strict arg other
|
||||
return .int32~new(char4~bitor(other~char),"C")
|
||||
|
||||
::method bitleft -- OORexx shift (<<) implementation
|
||||
expose char4
|
||||
use strict arg bits
|
||||
bstring = char4~c2x~x2b
|
||||
bstring = bstring~substr(bits+1)~left(bstring~length,'0')
|
||||
return .int32~new(bstring~b2x~x2d)
|
||||
|
||||
-- For those who like to code the shift operation in a traditional way
|
||||
::method '<<'
|
||||
forward to (self) message("bitleft")
|
||||
|
||||
::method bitright -- OORexx shift (>>) implementation
|
||||
expose char4
|
||||
use strict arg bits, signed=.false
|
||||
bstring = char4~c2x~x2b
|
||||
fill = '0'
|
||||
if signed then fill = bstring~subchar(1)
|
||||
bstring = bstring~left(bstring~length-bits)~right(bstring~length,fill)
|
||||
return .int32~new(bstring~b2x~x2d)
|
||||
|
||||
-- For those who like to code the shift operation in a traditional way
|
||||
::method '>>'
|
||||
forward to (self) message("bitright")
|
||||
|
||||
::method bitnot -- OORexx not implementation
|
||||
expose char4
|
||||
return .int32~new(char4~bitxor('ffffffff'x)~c2d,"C")
|
||||
|
||||
::method bitrotate -- OORexx (left) rotate method
|
||||
expose char4
|
||||
use strict arg bits, direction='left'
|
||||
d = direction~subchar(1)~upper
|
||||
if d=='L' then do
|
||||
leftpart = self~bitleft(bits)
|
||||
rightpart = self~bitright(32-bits)
|
||||
end
|
||||
else do
|
||||
leftpart = self~bitleft(32-bits)
|
||||
rightpart = self~bitright(bits)
|
||||
end
|
||||
return rightpart~or(leftpart)
|
||||
|
||||
::method int -- retrieve integer as number
|
||||
expose int32
|
||||
return int32
|
||||
|
||||
::method char -- retrieve integer as characters
|
||||
expose char4
|
||||
return char4
|
||||
|
||||
::method '+' -- OORexx method to add 2 .int32 instances
|
||||
expose int32
|
||||
use strict arg other
|
||||
return .int32~new(int32+other~int)
|
||||
|
||||
::method string -- retrieve integer as hexadecimal string
|
||||
expose char4
|
||||
return char4~reverse~c2x~lower
|
||||
|
||||
-- Simplify function names for the necessary 'RxMath' functions
|
||||
::routine sin EXTERNAL "LIBRARY rxmath RxCalcSin"
|
||||
Loading…
Add table
Add a link
Reference in a new issue