RosettaCodeData/Task/MD5/ALGOL-68/md5.alg

151 lines
4.6 KiB
Text
Raw Permalink Normal View History

2015-11-18 06:14:39 +00:00
# Based on wikipedia article pseudocode #
# s specifies the per-round shift amounts #
[]INT s = (7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22,
5, 9,14,20, 5, 9,14,20, 5, 9,14,20, 5, 9,14,20,
4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23,
6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21);
[]BITS k = (16rd76aa478, 16re8c7b756, 16r242070db, 16rc1bdceee,
16rf57c0faf, 16r4787c62a, 16ra8304613, 16rfd469501,
16r698098d8, 16r8b44f7af, 16rffff5bb1, 16r895cd7be,
16r6b901122, 16rfd987193, 16ra679438e, 16r49b40821,
16rf61e2562, 16rc040b340, 16r265e5a51, 16re9b6c7aa,
16rd62f105d, 16r02441453, 16rd8a1e681, 16re7d3fbc8,
16r21e1cde6, 16rc33707d6, 16rf4d50d87, 16r455a14ed,
16ra9e3e905, 16rfcefa3f8, 16r676f02d9, 16r8d2a4c8a,
16rfffa3942, 16r8771f681, 16r6d9d6122, 16rfde5380c,
16ra4beea44, 16r4bdecfa9, 16rf6bb4b60, 16rbebfbc70,
16r289b7ec6, 16reaa127fa, 16rd4ef3085, 16r04881d05,
16rd9d4d039, 16re6db99e5, 16r1fa27cf8, 16rc4ac5665,
16rf4292244, 16r432aff97, 16rab9423a7, 16rfc93a039,
16r655b59c3, 16r8f0ccc92, 16rffeff47d, 16r85845dd1,
16r6fa87e4f, 16rfe2ce6e0, 16ra3014314, 16r4e0811a1,
16rf7537e82, 16rbd3af235, 16r2ad7d2bb, 16reb86d391);
OP + = (BITS a, b) BITS:
BEGIN
BITS c = BIN (ABS (a AND 16rffff) + ABS (b AND 16rffff));
BITS d = BIN (ABS (a SHR 16) + ABS (b SHR 16) + ABS (c SHR 16));
(c AND 16rffff) OR (d SHL 16)
END;
#[0:63]LONG INT k;
FOR i FROM 0 TO 63 DO
k[i] := ENTIER (ABS (sin(i+1)) * LONG INT(2)**32)
OD;#
PROC md5 = (STRING intext) STRING:
BEGIN
# Initialize variables: #
BITS a0 := 16r67452301,
a1 := 16refcdab89,
a2 := 16r98badcfe,
a3 := 16r10325476;
STRING text := intext;
# Pre-processing: adding a single 1 bit #
text +:= REPR 128;
# Pre-processing: padding with zeros
append "0" bit until message length in bits ≡ 448 (mod 512) #
WHILE ELEMS text MOD 64 ≠ 56 DO
text +:= REPR 0
OD;
# append original length in bits mod (2 pow 64) to message #
text +:= dec2asc (ELEMS intext * 8);
# MD5 rounds #
# Process the message in successive 512-bit chunks: #
WHILE text ≠ "" DO
# for each 512-bit (64 byte) chunk of message #
[]CHAR chunk = text[1:64]; text := text[65:];
# break chunk into sixteen 32-bit words M[j], 0 <= j <= 15 #
[0:15]BITS m;
FOR j FROM 0 TO 15 DO
m[j] := BIN (ABS chunk[j*4+1]) OR
BIN (ABS chunk[j*4+2]) SHL 8 OR
BIN (ABS chunk[j*4+3]) SHL 16 OR
BIN (ABS chunk[j*4+4]) SHL 24
OD;
INT g;
BITS a, b, c, d, f, dtemp;
# Initialize hash value for this chunk #
a := a0;
b := a1;
c := a2;
d := a3;
FOR i FROM 0 TO 63 DO
IF 0 <= i AND i <= 15 THEN
f := (b AND c) OR ((NOT b) AND d);
g := i
ELIF 16 <= i AND i <= 31 THEN
f := (d AND b) OR ((NOT d) AND c);
g := (5×i + 1) MOD 16
ELIF 32 <= i AND i <= 47 THEN
f := b XOR c XOR d;
g := (3×i + 5) MOD 16
ELIF 48 <= i AND i <= 63 THEN
f := c XOR (b OR (NOT d));
g := (7×i) MOD 16
FI;
dtemp := d;
d := c;
c := b;
b := b + leftrotate ((a + f + k[1+i] + m[g]), s[1+i]);
a := dtemp
OD;
# Add this chunk's hash to result so far #
a0 := a0 + a;
a1 := a1 + b;
a2 := a2 + c;
a3 := a3 + d
OD;
revhex (a0) + revhex (a1) + revhex (a2) + revhex (a3)
END;
PROC leftrotate = (BITS x, INT c) BITS:
(x SHL c) OR (x SHR (32-c));
# dec2asc: dec to 8 byte asc #
PROC dec2asc = (INT nn)STRING:
BEGIN
STRING h := ""; INT n := nn;
FOR i TO 8 DO
h +:= REPR (n MOD 256);
n ÷:= 256
OD;
h
END;
PROC revhex = (BITS x) STRING :
BEGIN # Convert to lowercase hexadecimal STRING #
PROC hexdig = (BITS x) CHAR: (REPR (ABS(x) <= 9 | ABS(x) + ABS("0") | ABS(x) - 10 + ABS("a")));
hexdig (x SHR 4 AND 16rf) +
hexdig (x AND 16rf) +
hexdig (x SHR 12 AND 16rf) +
hexdig (x SHR 8 AND 16rf) +
hexdig (x SHR 20 AND 16rf) +
hexdig (x SHR 16 AND 16rf) +
hexdig (x SHR 28 AND 16rf) +
hexdig (x SHR 24 AND 16rf)
END;
STRING testmsg = "The quick brown fox jumps over the lazy dog";
STRING checksum = "9e107d9d372bb6826bd81d3542a419d6";
print ((testmsg, new line));
print ((checksum, new line));
STRING test = md5 (testmsg);
IF test = checksum THEN
print (("passed", new line));
print ((test, new line))
ELSE
print (("failed"))
FI