210 lines
6.6 KiB
Ada
210 lines
6.6 KiB
Ada
with Ada.Text_IO; use Ada.Text_IO;
|
|
with Interfaces;
|
|
|
|
procedure Day_4 is
|
|
|
|
type Uint32 is mod 2**32;
|
|
type Uint64 is mod 2**64;
|
|
type Uint128 is mod 2**128;
|
|
type Byte is range 0 .. 2**8 -1;
|
|
for Byte'Size use 8;
|
|
|
|
package Uint128_IO is new Ada.Text_IO.Modular_IO( Uint128 );
|
|
package Uint32_IO is new Ada.Text_IO.Modular_IO( Uint32 );
|
|
|
|
type Byte_Array is array (Natural range <>) of Byte;
|
|
|
|
type Uint32_Array is array (Natural range <>) of Uint32;
|
|
|
|
function Hex( Num : Uint32 ) return String is
|
|
Str : String( 1 .. 8 );
|
|
Tally : Uint32 := Num;
|
|
Temp : Uint32;
|
|
begin
|
|
for I in reverse Str'Range loop
|
|
Temp := Tally mod 16;
|
|
case Temp is
|
|
when 0 .. 9 => Str(I) := Character'Val(48 + Temp);
|
|
when 10 .. 15 => Str(I) := Character'val(65 + (Temp - 10));
|
|
when others => Str(I) := 'x';
|
|
end case;
|
|
Tally := Tally / 16;
|
|
end loop;
|
|
|
|
return Str;
|
|
end Hex;
|
|
|
|
function Pad( Key : String ) return Byte_Array is
|
|
Size : Natural := Key'Length;
|
|
Mod_Size : Natural := Size mod 64;
|
|
Pad_Size : Natural;
|
|
Original : Uint64 := Uint64(Size) * 8;
|
|
begin
|
|
|
|
if Mod_Size <= 55 then
|
|
Pad_Size := 55 - Mod_Size;
|
|
else
|
|
Pad_Size := (63 - Mod_Size) + 56;
|
|
end if;
|
|
|
|
declare
|
|
B : Byte_Array( 0 .. Pad_Size + Size + 8);
|
|
begin
|
|
for I in Key'Range loop
|
|
B(I-1) := Byte(Character'Pos(Key(I)));
|
|
end loop;
|
|
|
|
B(Key'Last) := 16#80#;
|
|
|
|
for I in 1 .. Pad_Size loop
|
|
B(Key'Last + I) := 0;
|
|
end loop;
|
|
|
|
for I in 0 .. 7 loop
|
|
B(B'Last - (7-I)) := Byte((Original / 2**(8*I)) and 16#FF#);
|
|
end loop;
|
|
|
|
return B;
|
|
end;
|
|
|
|
end Pad;
|
|
|
|
function MD5( Key : String ) return Uint128 is
|
|
S : Uint32_Array( 0 .. 63 ) := (
|
|
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
|
|
);
|
|
|
|
K : Uint32_Array( 0 .. 63 ) := (
|
|
16#d76aa478#, 16#e8c7b756#, 16#242070db#, 16#c1bdceee#,
|
|
16#f57c0faf#, 16#4787c62a#, 16#a8304613#, 16#fd469501#,
|
|
16#698098d8#, 16#8b44f7af#, 16#ffff5bb1#, 16#895cd7be#,
|
|
16#6b901122#, 16#fd987193#, 16#a679438e#, 16#49b40821#,
|
|
16#f61e2562#, 16#c040b340#, 16#265e5a51#, 16#e9b6c7aa#,
|
|
16#d62f105d#, 16#02441453#, 16#d8a1e681#, 16#e7d3fbc8#,
|
|
16#21e1cde6#, 16#c33707d6#, 16#f4d50d87#, 16#455a14ed#,
|
|
16#a9e3e905#, 16#fcefa3f8#, 16#676f02d9#, 16#8d2a4c8a#,
|
|
16#fffa3942#, 16#8771f681#, 16#6d9d6122#, 16#fde5380c#,
|
|
16#a4beea44#, 16#4bdecfa9#, 16#f6bb4b60#, 16#bebfbc70#,
|
|
16#289b7ec6#, 16#eaa127fa#, 16#d4ef3085#, 16#04881d05#,
|
|
16#d9d4d039#, 16#e6db99e5#, 16#1fa27cf8#, 16#c4ac5665#,
|
|
16#f4292244#, 16#432aff97#, 16#ab9423a7#, 16#fc93a039#,
|
|
16#655b59c3#, 16#8f0ccc92#, 16#ffeff47d#, 16#85845dd1#,
|
|
16#6fa87e4f#, 16#fe2ce6e0#, 16#a3014314#, 16#4e0811a1#,
|
|
16#f7537e82#, 16#bd3af235#, 16#2ad7d2bb#, 16#eb86d391#
|
|
);
|
|
|
|
A0 : Uint32 := 16#67452301#;
|
|
B0 : Uint32 := 16#efcdab89#;
|
|
C0 : Uint32 := 16#98badcfe#;
|
|
D0 : Uint32 := 16#10325476#;
|
|
|
|
Data : Byte_Array := Pad(Key);
|
|
|
|
Output : Uint128 := 0;
|
|
|
|
begin
|
|
|
|
for I in 0 .. (Data'Length / 64) - 1 loop
|
|
declare
|
|
M : Uint32_Array( 0 .. 15 );
|
|
A : Uint32 := A0;
|
|
B : Uint32 := B0;
|
|
C : Uint32 := C0;
|
|
D : Uint32 := D0;
|
|
F : Uint32;
|
|
G : Uint32;
|
|
begin
|
|
for J in 0 .. 15 loop
|
|
declare
|
|
Index : Integer := (I*64) + (J*4);
|
|
begin
|
|
M(J) := Uint32(Data(Index));
|
|
M(J) := @ + Uint32(Data(Index + 1)) * 2**8;
|
|
M(J) := @ + Uint32(Data(Index + 2)) * 2**16;
|
|
M(J) := @ + Uint32(Data(Index + 3)) * 2**24;
|
|
end;
|
|
end loop;
|
|
|
|
|
|
for J in 0 .. 63 loop
|
|
if J >= 0 and J <= 15 then
|
|
F := (B and C) or ((not B) and D);
|
|
G := Uint32(J);
|
|
elsif J >= 16 and J <= 31 then
|
|
F := (D and B) or ((not D) and C);
|
|
G := (5*Uint32(J) + 1) mod 16;
|
|
elsif J >= 32 and J <= 47 then
|
|
F := B xor C xor D;
|
|
G := (3*Uint32(J) + 5) mod 16;
|
|
else
|
|
F := C xor (B or (not D));
|
|
G := (7*Uint32(J)) mod 16;
|
|
end if;
|
|
F := F + A + K(J) + M(Integer(G));
|
|
A := D;
|
|
D := C;
|
|
C := B;
|
|
B := B + Uint32(
|
|
Interfaces.Rotate_Left(
|
|
Interfaces.Unsigned_32(F), Natural(S(J))));
|
|
|
|
end loop;
|
|
|
|
A0 := @ + A;
|
|
B0 := @ + B;
|
|
C0 := @ + C;
|
|
D0 := @ + D;
|
|
end;
|
|
end loop;
|
|
|
|
declare
|
|
Output_Arr : Uint32_Array := [A0, B0, C0, D0];
|
|
begin
|
|
for I in 0 .. 3 loop
|
|
declare
|
|
Nibble : Uint32 := Output_Arr(I);
|
|
begin
|
|
for J in 0 .. 3 loop
|
|
Output := (@ * 2**8) + Uint128(Nibble mod 2**8);
|
|
Nibble := @ / 2**8;
|
|
end loop;
|
|
end;
|
|
end loop;
|
|
end;
|
|
|
|
return Output;
|
|
|
|
end MD5;
|
|
|
|
Base_Key : String := "yzbqklnj";
|
|
Index : Positive := 1;
|
|
|
|
MD5_Hash : Uint128;
|
|
|
|
begin
|
|
|
|
Uint128_IO.Put(MD5("a"), Base => 16);
|
|
New_Line;
|
|
|
|
loop
|
|
declare
|
|
Num : String := Index'Image;
|
|
begin
|
|
Put_Line("Testing: " & Base_Key & Num(Num'First + 1 .. Num'Last));
|
|
MD5_Hash := MD5(Base_Key & Num( Num'First + 1 .. Num'Last));
|
|
Uint128_IO.Put(MD5_Hash, Base => 16);
|
|
New_Line;
|
|
end;
|
|
|
|
exit when (MD5_Hash and 16#FFFFFF00000000000000000000000000#) = 0;
|
|
|
|
Index := @ + 1;
|
|
end loop;
|
|
|
|
Put_Line("Key is" & Index'Image);
|
|
|
|
end Day_4;
|