#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
my @r = ((7,12,17,22) x 4 , (5,9,14,20) x 4 , (4,11,16,23) x 4 , (6,10
+,15,21) x 4);
my @k;
$k[$_] = (int(abs(sin($_+1))*(2**32))) for 0..63;
my $H0 = 0x67452301;
my $H1 = 0xefcdab89;
my $H2 = 0x98badcfe;
my $H3 = 0x10325476;
print "> ";
my @msg = map(ord, split // , <>);
pop @msg;
my $msgbin;
$msgbin .= 0 . sprintf('%b',$msg[$_]) for 0..$#msg;;
my $length = sprintf('%b',length $msgbin);
$length = 0 . $length while length $length < 64;
$msgbin .= 1;
$msgbin .= 0 until length $msgbin == 448 % 512;
$msgbin .= $length;
my @w;
for (my $i=0,my $j=0;$j<16;$i+=32,$j++) {
$w[$j] = (unpack("N", pack("B32", substr("0" x 32 . (substr($msgbin
+,$i,32)), -32)))) % (2**32);
}
my $a = $H0;
my $b = $H1;
my $c = $H2;
my $d = $H3;
my $f;
my $g;
for my $i (0..63) {
if ($i >= 0 && $i <= 15) {
$f = (($b & $c) | ((~$b) & $d)) % (2**32);
$g = $i;
} elsif ($i >= 16 && $i <= 31) {
$f = (($d & $b) | ((~$d) & $c)) % (2**32);
$g = (5*$i + 1) % 16;
} elsif ($i >= 32 && $i <= 47) {
$f = ($b ^ $c ^ $d) % (2**32);
$g = (3*$i + 1) % 16;
} elsif ($i >= 48 && $i <= 63) {
$f = ($c ^ ($b | (~$d))) % (2**32);
$g = (7*$i + 1) % 16;
}
my $temp = $d % (2**32);
$d = $c % (2**32);
$c = $b % (2**32);
$b = ($b + (($a + $f + $k[$i] + $w[$g]) << $r[$i])) % (2**32);
$a = $temp % (2**32);
}
$H0 = unpack("H8", pack("N", ($H0 + $a)));
$H1 = unpack("H8", pack("N", ($H1 + $b)));
$H2 = unpack("H8", pack("N", ($H2 + $c)));
$H3 = unpack("H8", pack("N", ($H3 + $d)));
my $digest = $H0.$H1.$H2.$H3;
print "> $digest\n";
|