SHA-256 Pure Perl
Das Programm liest eine Datei ein, deren Name beim Start als Parameter übergeben wird. Es verarbeitet den Inhalt der Datei nach dem offiziellen SHA-256 Standard: Zuerst wird der Text gepolstert (Padding), dann in 512-Bit-Blöcke zerlegt und jeder Block durchläuft 64 Rechenschritte mit Bitoperationen wie Rotation, XOR und logischen Verknüpfungen. Die dabei entstehenden Zwischenwerte werden in acht 32-Bit-Variablen gespeichert und nach jeder Runde aktualisiert. Am Ende ergibt sich ein 256-Bit-Hashwert, der als 64-stellige Hex-Zeichenkette ausgegeben wird. Die Besonderheit: Alles geschieht vollständig in Perl, ohne externe Bibliotheken – ideal zum Verstehen des Algorithmus.
#!/usr/bin/perl
# SHA-256 Pure Perl implementation
use strict;
use warnings;
# Initial-Hashwerte H0–H7 (32 Bit)
# Sie stammen von den ersten 32 Bits der Quadratwurzeln der ersten 8 Primzahlen
my @H = (
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
);
# 64 Rundenschlüssel (Konstanten K0–K63)
# Sie stammen aus den ersten 32 Bits der Kubikwurzeln der ersten 64 Primzahlen
my @K = (
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
);
# Bitweise Rechtsrotation um $n Bits bei 32-Bit-Wert
# Beispiel: rotr(0b10110000, 2) → 0b00101100
sub rotr {
my ($x, $n) = @_;
return (($x >> $n) | ($x << (32 - $n))) & 0xffffffff;
}
# SHA-256 Kernfunktion
sub sha256 {
my ($msg) = @_;
my $bitlen = length($msg) * 8;
# Padding nach SHA256-Spezifikation: 1-Bit, gefolgt von 0-Bits, dann Länge
$msg .= chr(0x80);
$msg .= chr(0x00) while length($msg) % 64 != 56;
$msg .= pack("Q>", $bitlen); # 64-Bit-Länge big-endian
my @h = @H; # Arbeitskopie der Initial-Hashwerte
for (my $i = 0; $i < length($msg); $i += 64) {
my $chunk = substr($msg, $i, 64);
my @w = unpack("N16", $chunk); # 16 Wörter à 32 Bit
# Erweiterung auf 64 Wörter mit Bitoperationen
for my $t (16 .. 63) {
my $s0 = rotr($w[$t-15],7) ^ rotr($w[$t-15],18) ^ ($w[$t-15] >> 3);
my $s1 = rotr($w[$t-2],17) ^ rotr($w[$t-2],19) ^ ($w[$t-2] >> 10);
$w[$t] = ($w[$t-16] + $s0 + $w[$t-7] + $s1) & 0xffffffff;
}
# Initialisierung der Arbeitsvariablen a–h
my ($a,$b,$c,$d,$e,$f,$g,$h_) = @h;
# 64 Kompressionsrunden
for my $t (0 .. 63) {
# S1 = Kombination aus 3 Rotationen von e
my $S1 = rotr($e,6) ^ rotr($e,11) ^ rotr($e,25);
# ch = bedingte Auswahl: if e then f else g
my $ch = ($e & $f) ^ ((~$e) & $g);
my $temp1 = ($h_ + $S1 + $ch + $K[$t] + $w[$t]) & 0xffffffff;
# S0 = 3 Rotationen von a
my $S0 = rotr($a,2) ^ rotr($a,13) ^ rotr($a,22);
# maj = Mehrheit von a, b, c
my $maj = ($a & $b) ^ ($a & $c) ^ ($b & $c);
my $temp2 = ($S0 + $maj) & 0xffffffff;
# Schiebe die Arbeitsvariablen weiter
($h_,$g,$f,$e,$d,$c,$b,$a) =
($g,$f,$e,($d + $temp1) & 0xffffffff,
$c,$b,$a,($temp1 + $temp2) & 0xffffffff);
}
# Addiere Blockresultat zum aktuellen Hashwert
my @temp = ($a,$b,$c,$d,$e,$f,$g,$h_);
@h = map { ($h[$_] + $temp[$_]) & 0xffffffff } (0..7);
}
# Finale Ausgabe als hexadezimale Zeichenkette (8×32 Bit → 64 Hex-Zeichen)
return join('', map { sprintf("%08x", $_) } @h);
}
# Kommandozeilenargument: Dateiname
my $filename = shift;
# Prüfung: Wurde überhaupt ein Dateiname übergeben?
if (!$filename) {
die "FEHLER: Bitte gib den Dateinamen als Parameter an.\nBeispiel: ./sha256-pure_perl.pl test.txt\n";
}
# Prüfung: Existiert die Datei wirklich?
if (!-f $filename) {
die "FEHLER: Datei '$filename' existiert nicht oder ist ungültig.\n";
}
# Datei binär öffnen und Inhalt vollständig lesen
open(my $fh, '<', $filename) or die "Kann Datei '$filename' nicht öffnen: $!";
binmode($fh);
my $data = do { local $/; <$fh> };
close($fh);
# SHA256 berechnen & ausgeben
my $hash = sha256($data);
print "SHA256('$filename') = $hash\n";