Analyse des SHA-256 Hash Algorithmus
SHA-256 (von englisch secure hash algorithm, sicherer Hash-Algorithmus) ist die Bezeichnung für die kryptologische 256 Bit Hashfunktion welche von der Amerikanischen Nationalen Sicherheits Behörde NSA entwickelt und vom US-amerikanischen NIST 2001 als Nachfolger von SHA-1 als FIPS Standard (U.S. Federal Information Processing Standard) erklärt wurde.
Der SHA-2 Hash Algorthmus ist bei Sicherheits Software und Protokolle wie TLS und SSL, PGP, SSH, S/MIME, Bitcoin und IPsec weit verbreitet. Diverse cryptowährungen verwenden SHA-2 als Hauptbasis Ihres Geshäftsmodel. Bitcoin war die erste Crypto Währung welche double round of SHA-256 als Kern verwendet. SHA-256 wird bei Debian GNU/Linux verwendet um die Authentizität eines zu installierendes Software Packet festzustellen. SHA-256 and SHA-512 sind vorgesehen für den gebrauch in DNSSEC. Unix und Linux Betriebssystem Distibutoren verwenden 256- and 512-bit SHA-2 für das sichere Passwort Hashing ablegen im System.
Die Zahl 256 gibt die Länge des Hash (in Bit) an. Ein Typischer SHA-256 Hash sieht wie folgt aus.
'''730f75dafd73e047b86acb2dbd74e75dcb93272fa084a9082848f2341aa1abb6'''
Zur Erzeugung des Hash-Wertes bei SHA-256 wird die entsprechende Information in 512-Bit-Blöcke bzw. 16 x 32-Bit-Wörter aufgeteilt und iterativ mit 64 Konstanten und sechs logischen Funktionen verrechnet. Dabei wird mit einem Start-Hash aus acht 32-Bit-Wörtern begonnen. Dazu werden die ersten 32 Bits der Nachkommastelle der Quadrat Wurzeln der ersten acht Primzahlen (2 bis 19) verwendet welche jedoch am ende meistens eben keine Primzahlen mehr sind.
Eine kleine Änderung der Nachricht erzeugt einen komplett anderen Hash. Diese Hash Eigenschaft wird in der IT Industrie unter anderem auch dazu genutzt um die Echtheit und Vollständigkeit einer Information zu überprüfen. Damit lässt sich unter anderem auch überprüfen ob eine Datei fehlerfrei aus dem Internet kopiert werden konnte oder ob an der Datei welche Manipulationen vorgenommen wurden.
Notiz 1: Alle Variablen sind 32 bit unsigned Integers und addition ist mit modulo 232 gerechnet
Notiz 2: Für jede Runde, gibt es eine Konstantenrunde k[i] und ein eintrag in die Informations Matrix w[i], 0 ≤ i ≤ 63
Notiz 3: Die Kompression Funktion verwendet 8 Variablen, a bis h
Initialisierung des Start-Hash Werts bestehend aus den ersten 32 Bits der Nachkommastelle der Quadrat Wurzeln der ersten 8 Primzahlen (2 bis 19) verwendet
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19
Initialisierung der Konstanten bestehend aus den ersten 32 Bits der Nachkommastelle der Kubischen Wurzel der ersten 64 Primzahlen 2 bis 311
k[0..63] :=
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
Pre-processing:
append the bit '1' to the message
append k bits '0', where k is the minimum number >= 0 such that the resulting message
length (modulo 512 in bits) is 448.
append length of message (without the '1' bit or padding), in bits, as 64-bit big-endian integer
(this will make the entire post-processed length a multiple of 512 bits)
Process the message in successive 512-bit chunks:
break message into 512-bit chunks
for each chunk
create a 64-entry message schedule array w[0..63] of 32-bit words
(The initial values in w[0..63] don't matter, so many implementations zero them here)
copy chunk into first 16 words w[0..15] of the message schedule array
Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
for i from 16 to 63
s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10)
w[i] := w[i-16] + s0 + w[i-7] + s1
Initialize working variables to current hash value:
a := h0
b := h1
c := h2
d := h3
e := h4
f := h5
g := h6
h := h7
Compression function main loop:
for i from 0 to 63
S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
ch := (e and f) xor ((not e) and g)
temp1 := h + S1 + ch + k[i] + w[i]
S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
maj := (a and b) xor (a and c) xor (b and c)
temp2 := S0 + maj
h := g
g := f
f := e
e := d + temp1
d := c
c := b
b := a
a := temp1 + temp2
Add the compressed chunk to the current hash value:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e
h5 := h5 + f
h6 := h6 + g
h7 := h7 + h
Produce the final hash value (big-endian):
digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7