122 lines
4.3 KiB
Plaintext
122 lines
4.3 KiB
Plaintext
$ include "seed7_05.s7i";
|
|
include "bytedata.s7i";
|
|
include "bin32.s7i";
|
|
include "float.s7i";
|
|
include "math.s7i";
|
|
|
|
# Use binary integer part of the sines of integers (Radians) as constants:
|
|
const func array integer: createMd5Table is func
|
|
result
|
|
var array integer: k is 64 times 0;
|
|
local
|
|
var integer: index is 0;
|
|
begin
|
|
for index range 1 to 64 do
|
|
k[index] := trunc(abs(sin(flt(index))) * 2.0 ** 32);
|
|
end for;
|
|
end func;
|
|
|
|
const func string: md5 (in var string: message) is func
|
|
result
|
|
var string: digest is "";
|
|
local
|
|
# Specify the per-round shift amounts
|
|
const array integer: shiftAmount is [] (
|
|
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);
|
|
const array integer: k is createMd5Table;
|
|
var integer: length is 0;
|
|
var integer: wordIndex is 1;
|
|
var integer: index is 0;
|
|
var array bin32: m is 16 times bin32.value;
|
|
var integer: a0 is 16#67452301; # a
|
|
var integer: b0 is 16#efcdab89; # b
|
|
var integer: c0 is 16#98badcfe; # c
|
|
var integer: d0 is 16#10325476; # d
|
|
var bin32: a is bin32(0);
|
|
var bin32: b is bin32(0);
|
|
var bin32: c is bin32(0);
|
|
var bin32: d is bin32(0);
|
|
var bin32: f is bin32(0);
|
|
var integer: g is 0;
|
|
var bin32: temp is bin32(0);
|
|
begin
|
|
length := length(message);
|
|
# Append the bit '1' to the message.
|
|
message &:= '\16#80;';
|
|
# Append '0' bits, so that the resulting bit length is congruent to 448 (mod 512).
|
|
message &:= "\0;" mult 63 - (length + 8) mod 64;
|
|
# Append length of message (before pre-processing), in bits, as 64-bit little-endian integer.
|
|
message &:= bytes(8 * length, UNSIGNED, LE, 8);
|
|
|
|
# Process the message in successive 512-bit chunks:
|
|
while wordIndex <= length(message) do
|
|
# Break chunk into sixteen 32-bit little-endian words.
|
|
for index range 1 to 16 do
|
|
m[index] := bin32(bytes2Int(message[wordIndex fixLen 4], UNSIGNED, LE));
|
|
wordIndex +:= 4;
|
|
end for;
|
|
|
|
a := bin32(a0 mod 16#100000000);
|
|
b := bin32(b0 mod 16#100000000);
|
|
c := bin32(c0 mod 16#100000000);
|
|
d := bin32(d0 mod 16#100000000);
|
|
|
|
for index range 1 to 64 do
|
|
if index <= 16 then
|
|
f := d >< (b & (c >< d));
|
|
g := index;
|
|
elsif index <= 32 then
|
|
f := c >< (d & (b >< c));
|
|
g := succ((5 * index - 4) mod 16);
|
|
elsif index <= 48 then
|
|
f := b >< c >< d;
|
|
g := succ((3 * index + 2) mod 16);
|
|
else
|
|
f := c >< (b | (bin32(16#ffffffff) >< d));
|
|
g := succ((7 * pred(index)) mod 16);
|
|
end if;
|
|
|
|
temp := d;
|
|
d := c;
|
|
c := b;
|
|
b := bin32((ord(b) +
|
|
ord(rotLeft(bin32((ord(a) + ord(f) + k[index] + ord(m[g])) mod 16#100000000),
|
|
shiftAmount[index]))) mod 16#100000000);
|
|
a := temp;
|
|
end for;
|
|
|
|
# Add this chunk's hash to result so far:
|
|
a0 +:= ord(a);
|
|
b0 +:= ord(b);
|
|
c0 +:= ord(c);
|
|
d0 +:= ord(d);
|
|
end while;
|
|
|
|
# Produce the final hash value:
|
|
digest := bytes(a0 mod 16#100000000, UNSIGNED, LE, 4) &
|
|
bytes(b0 mod 16#100000000, UNSIGNED, LE, 4) &
|
|
bytes(c0 mod 16#100000000, UNSIGNED, LE, 4) &
|
|
bytes(d0 mod 16#100000000, UNSIGNED, LE, 4);
|
|
end func;
|
|
|
|
const func boolean: checkMd5 (in string: message, in string: hexMd5) is
|
|
return hex(md5(message)) = hexMd5;
|
|
|
|
const proc: main is func
|
|
begin
|
|
if checkMd5("", "d41d8cd98f00b204e9800998ecf8427e") and
|
|
checkMd5("a", "0cc175b9c0f1b6a831c399e269772661") and
|
|
checkMd5("abc", "900150983cd24fb0d6963f7d28e17f72") and
|
|
checkMd5("message digest", "f96b697d7cb7938d525a2f31aaf161d0") and
|
|
checkMd5("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b") and
|
|
checkMd5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f") and
|
|
checkMd5("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a") then
|
|
writeln("md5 is computed correct");
|
|
else
|
|
writeln("There is an error in the md5 function");
|
|
end if;
|
|
end func;
|