L’SHA-256 (Secure Hash Algorithm 256-bit) è una funzione di hash crittografica appartenente alla famiglia SHA-2, progettata dalla NSA (National Security Agency) degli Stati Uniti. Viene comunemente utilizzata in molte applicazioni di sicurezza e integrità dei dati. Ecco una spiegazione di come funziona il meccanismo di crittografia SHA-256:
1. Input
SHA-256 accetta un input di lunghezza variabile e restituisce un hash (digest) di 256 bit (32 byte).
2. Padding
Prima che l’input venga elaborato, viene “riempito” (padding) per garantire che la lunghezza totale (in bit) sia un multiplo di 512. Il padding viene eseguito nel modo seguente:
- Aggiungi un singolo bit ‘1’ all’input.
- Aggiungi tanti bit ‘0’ quanti necessari per far sì che la lunghezza dell’input (in bit) meno 64 sia congruente a 448 modulo 512.
- Aggiungi i 64 bit della lunghezza dell’input originale in bit (big-endian).
3. Inizializzazione dei registri
SHA-256 utilizza otto variabili di lavoro a 32 bit, inizializzate con valori costanti (H0-H7). Questi valori sono derivati dalle radici quadrate dei primi otto numeri primi.
4. Processamento a blocchi
L’input riempito viene diviso in blocchi di 512 bit (64 byte). Ogni blocco viene elaborato attraverso diverse operazioni matematiche:
- Espansione del messaggio:
- Ogni blocco di 512 bit è suddiviso in 16 parole di 32 bit.
- Queste 16 parole vengono estese a 64 parole di 32 bit tramite operazioni bitwise e funzioni di rotazione.
- Compressione:
- Le otto variabili di lavoro sono inizializzate con i valori delle costanti di partenza.
- Per ogni parola del blocco esteso, viene eseguita una serie di operazioni di compressione che coinvolgono funzioni logiche (e.g., AND, OR, XOR), operazioni di rotazione e addizioni modulari.
- Le funzioni principali utilizzate in questa fase sono le funzioni di scelta (ch), di maggioranza (maj) e due funzioni di compressione (Σ0\Sigma_0Σ0 e Σ1\Sigma_1Σ1).
- Aggiornamento dei registri:
- I risultati delle operazioni di compressione vengono utilizzati per aggiornare le otto variabili di lavoro.
5. Concatenazione dei registri
Al termine dell’elaborazione di tutti i blocchi, i valori delle otto variabili di lavoro vengono concatenati per formare l’hash finale a 256 bit.
Pseudocodice di SHA-256
Ecco una versione semplificata del pseudocodice per SHA-256:
funzione SHA-256(messaggio)
// Inizializzazione dei registri
H0 = 0x6a09e667
H1 = 0xbb67ae85
H2 = 0x3c6ef372
H3 = 0xa54ff53a
H4 = 0x510e527f
H5 = 0x9b05688c
H6 = 0x1f83d9ab
H7 = 0x5be0cd19
// Padding del messaggio
messaggio_paddato = padding(messaggio)
// Processamento a blocchi
per ogni blocco da 512 bit nel messaggio_paddato
// Espansione del messaggio
W = espandi_blocco(blocco)
// Inizializzazione variabili di lavoro
a = H0
b = H1
c = H2
d = H3
e = H4
f = H5
g = H6
h = H7
// Compressione
per i da 0 a 63
T1 = h + Σ1(e) + ch(e, f, g) + K[i] + W[i]
T2 = Σ0(a) + maj(a, b, c)
h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2
// Aggiornamento registri
H0 = H0 + a
H1 = H1 + b
H2 = H2 + c
H3 = H3 + d
H4 = H4 + e
H5 = H5 + f
H6 = H6 + g
H7 = H7 + h
// Concatenazione dei registri per ottenere l'hash finale
hash = H0 || H1 || H2 || H3 || H4 || H5 || H6 || H7
ritorna hash
Funzioni ausiliarie
- ch(x, y, z): (x AND y) XOR (NOT x AND z)
- maj(x, y, z): (x AND y) XOR (x AND z) XOR (y AND z)
- Σ0(x): ROTR(x, 2) XOR ROTR(x, 13) XOR ROTR(x, 22)
- Σ1(x): ROTR(x, 6) XOR ROTR(x, 11) XOR ROTR(x, 25)
- ROTR(x, n): Ruota a destra x di n bit.
In sintesi, SHA-256 prende un input di lunghezza variabile, lo riempie, lo divide in blocchi, esegue una serie di operazioni di compressione e restituisce un hash di 256 bit. Questa funzione è progettata per essere resistente alle collisioni e pre-immagini, rendendola adatta per applicazioni di sicurezza.