MD5/Implementation: Difference between revisions

Content added Content deleted
m (→‎{{header|REXX}}: added whitespace.)
(Added Delphi example)
Line 1,339: Line 1,339:


As you see this asm is much faster than the D code compiled by dmd, but the D code compiled by ldc2 is a little faster still.
As you see this asm is much faster than the D code compiled by dmd, but the D code compiled by ldc2 is a little faster still.

=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{libheader| System.Classes}}
{{Trans|Go}}
<lang Delphi>
program MD5Implementation;

{$APPTYPE CONSOLE}

uses
System.SysUtils,
System.Classes;

type
TTestCase = record
hashCode: string;
_: string;
end;

var
testCases: array[0..6] of TTestCase = ((
hashCode: 'D41D8CD98F00B204E9800998ECF8427E';
_: ''
), (
hashCode: '0CC175B9C0F1B6A831C399E269772661';
_: 'a'
), (
hashCode: '900150983CD24FB0D6963F7D28E17F72';
_: 'abc'
), (
hashCode: 'F96B697D7CB7938D525A2F31AAF161D0';
_: 'message digest'
), (
hashCode: 'C3FCD3D76192E4007DFB496CCA67E13B';
_: 'abcdefghijklmnopqrstuvwxyz'
), (
hashCode: 'D174AB98D277D9F5A5611C2C9F419D9F';
_: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
), (
hashCode: '57EDF4A22BE3C955AC49DA2E2107B67A';
_: '12345678901234567890123456789' + '012345678901234567890123456789012345678901234567890'
));
shift: array of UInt32 = [7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21];
table: array[0..63] of UInt32;

procedure Init();
var
i: integer;

function fAbs(x: Extended): Extended;
begin
if x < 0 then
exit(-x);
exit(x);
end;

begin
for i := 0 to High(table) do
table[i] := Trunc((UInt64(1) shl 32) * fAbs(Sin(i + 1.0)));
end;

function Md5(s: string): TBytes;
const
BUFFER_SIZE = 16;
var
binary: TBytesStream;
buffer: Tarray<UInt32>;
messageLenBits: UInt64;
i, j, bufferIndex, count: integer;
byte_data: byte;
string_data: ansistring;
k, k1: Tarray<UInt32>;
f, rnd, sa: UInt32;
tmp: UInt64;
begin
k := [$67452301, $EFCDAB89, $98BADCFE, $10325476];

binary := TBytesStream.Create();

if not s.IsEmpty then
begin
string_data := Utf8ToAnsi(s);
binary.Write(Tbytes(string_data), length(string_data));
end;

byte_data := $80;
binary.Write(byte_data, 1);

messageLenBits := UInt64(s.Length * 8);
count := s.Length + 1;

while (count mod 64) <> 56 do
begin
byte_data := $00;
binary.Write(byte_data, 1);
inc(count);
end;

binary.Write(messageLenBits, sizeof(messageLenBits));

SetLength(buffer, BUFFER_SIZE);
SetLength(k1, length(k));

binary.Seek(0, soFromBeginning);

while binary.Read(buffer[0], BUFFER_SIZE * 4) > 0 do
begin
for i := 0 to 3 do
k1[i] := k[i];

for i := 0 to 63 do
begin
f := 0;
bufferIndex := i;
rnd := i shr 4;
case rnd of
0:
f := (k1[1] and k1[2]) or (not k1[1] and k1[3]);
1:
begin
f := (k1[1] and k1[3]) or (k1[2] and not k1[3]);
bufferIndex := (bufferIndex * 5 + 1) and $0F
end;
2:
begin
f := k1[1] xor k1[2] xor k1[3];
bufferIndex := (bufferIndex * 3 + 5) and $0F;
end;
3:
begin
f := k1[2] xor (k1[1] or not k1[3]);
bufferIndex := (bufferIndex * 7) and $0F;
end;
end;

sa := shift[(rnd shl 2) or (i and 3)];

k1[0] := k1[0] + f + buffer[bufferIndex] + table[i];

tmp := k1[0];

k1[0] := k1[3];
k1[3] := k1[2];
k1[2] := k1[1];

k1[1] := ((tmp shl sa) or (tmp shr (32 - sa))) + k1[1];
end;

for i := 0 to 3 do
k[i] := k[i] + k1[i];
end;

SetLength(result, BUFFER_SIZE);

binary.Clear;
for i := 0 to 3 do
binary.Write(k[i], 4);

binary.Seek(0, soBeginning);

binary.Read(Result, BUFFER_SIZE);

binary.Free;
end;

function BytesToString(b: TBytes): string;
var
v: byte;
begin
Result := '';
for v in b do
Result := Result + v.ToHexString(2);
end;

var
tc: TTestCase;

begin
Init;

for tc in testCases do
Writeln(Format('%s'#10'%s'#10, [tc.hashCode, BytesToString(md5(tc._))]));
Readln;
end.</lang>


=={{header|F#}}==
=={{header|F#}}==