# Funzione crittografica di hash

Una funzione crittografica di hash, in informatica, è una classe speciale delle funzioni di hash, che dispone di alcune proprietà che la rendono adatta all'uso in crittografia.
Si tratta di un algoritmo matematico che mappa dei dati di lunghezza arbitraria (messaggio) in una stringa binaria di dimensione fissa chiamata valore di hash, ma spesso viene indicata anche con il termine inglese message digest (o semplicemente digest). Tale funzione di hash è progettata per essere unidirezionale (one-way), ovvero una funzione difficile da invertire: l'unico modo per ricreare i dati di input dall'output di una funzione di hash ideale è quello di tentare una ricerca di forza-bruta di possibili input per vedere se vi è corrispondenza (match). In alternativa, si potrebbe utilizzare una tabella arcobaleno di hash corrispondenti.
La funzione crittografica di hash ideale deve avere alcune proprietà fondamentali:
* deve identificare univocamente il messaggio, non è possibile che due messaggi differenti, pur essendo simili, abbiano lo stesso valore di hash;
* deve essere deterministico, in modo che lo stesso messaggio si traduca sempre nello stesso hash;
* deve essere semplice e veloce calcolare un valore hash da un qualunque tipo di dato;
* deve essere molto difficile o quasi impossibile generare un messaggio dal suo valore hash se non provando tutti i messaggi possibili.
Tali caratteristiche permettono alle funzioni crittografiche di hash di trovare ampio utilizzo negli ambiti della sicurezza informatica, quali firme digitali, codici di autenticazione dei messaggi (MAC) e altre forme di autenticazione. Possono essere utilizzati anche come funzioni di hash ordinarie, per indicizzare i dati nelle tabelle di hash, per la rilevazione di impronte digitali, per rilevare dati duplicati o identificare in modo univoco i file e come checksum per rilevare la corruzione accidentale dei dati. Infatti, nei contesti di sicurezza informatica, i valori di hash crittografici sono talvolta chiamati «impronte digitali» o «checksum» anche se tutti questi termini hanno funzioni più generali con proprietà e scopi piuttosto diversi.

## Proprietà

La maggior parte delle funzioni di hash crittografiche è progettata per prendere in input una stringa di qualsiasi lunghezza e produrre in output un valore di hash di lunghezza fissa. Queste funzioni devono essere in grado di resistere a tutti gli attacchi basati sulla crittoanalisi: per fare questo, si definisce il livello di sicurezza di una funzione di hash crittografica facendo riferimento alle seguenti proprietà:
* Resistenza alla preimmagine Dato un valore di hash $h$, deve essere difficile risalire ad un messaggio $m$ con $hash(m)=h$. Questa proprietà deriva dal concetto di funzione unidirezionale. Funzioni che non dispongono di questa proprietà sono vulnerabili agli attacchi alla preimmagine.
* Resistenza alla preimmagine secondaria Dato un messaggio $m_{1}$, deve essere difficile trovare un secondo messaggio $m_{2}$ tale che $hash(m_{1})=hash(m_{2})$. Funzioni che non dispongono di questa proprietà sono vulnerabili agli attacchi alla seconda preimmagine.
* Resistenza alle collisioni Dati due messaggi $m_{1}$ e $m_{2}$, deve essere difficile che i due messaggi abbiano lo stesso hash, quindi con $hash(m_{1})=hash(m_{2})$. Tale coppia è chiamata collisione di hash crittografica. Questa proprietà a volte è indicata come forte resistenza alla collisione. La resistenza alla collisione implica una resistenza alla seconda preimmagine, ma non implica la resistenza alla preimmagine: rispetto a quest'ultimo, richiede un valore di hash almeno due volte più lungo, altrimenti le collisioni possono essere trovate da un attacco del compleanno.
Queste proprietà implicano che un eventuale attacco non permetta di rimpiazzare o modificare un messaggio senza conseguenze sul risultante valore di hash. Pertanto, se due stringhe hanno lo stesso digest, si può essere fiduciosi nel pensare che siano identiche. In particolare, la resistenza alla seconda preimmagine dovrebbe impedire ad avversario maligno di elaborare un messaggio con lo stesso hash di un messaggio che l'avversario stesso non può controllare. La resistenza alla collisione, invece, impedisce all'attaccante di creare due messaggi distinti con lo stesso hash.
In pratica, una funzione hash è solo una resistenza alla seconda pre-immagine; motivo per cui è considerata insicura e, di conseguenza, non raccomandata per applicazioni reali. D'altra parte, la resistenza alle collisioni risulta insufficiente per molti usi pratici: oltre ad essa, non dovrebbe essere possibile per un avversario trovare due messaggi con digest sostanzialmente simili o poter dedurre informazioni utili del messaggio partendo dal suo valore di hash. Quindi una funzione crittografica di hash deve essere il più possibile simile a una funzione casuale (spesso chiamata oracolo random) rimanendo comunque deterministica e semplice da calcolare. Ciò esclude le funzioni SWIFFT, delle quali è dimostrato che sono rigorosamente resistenti alla collisione, sempre se si suppone che determinati problemi sui reticoli ideali siano computazionalmente difficili; se intese come funzioni lineari, non portano a soddisfare queste proprietà. Gli algoritmi di checksum, ad esempio, come CRC e altri controlli di ridondanza ciclici, poiché lineari, sono progettati per soddisfare requisiti molto più deboli essendo troppo facili da invertire e generalmente non sono adatti come funzioni di hash crittografiche.
È importante precisare però che, pur possedendo una funzione in grado di soddisfare tutti questi criteri, si può ancora andare incontro a delle proprietà indesiderate. Le funzioni crittografiche di hash attualmente usate sono vulnerabili agli attacchi di lunghezza-estensione: dati $hash(m)$ e $len(m)$, ma non $m$, scegliendo un appropriato $m$, un attaccante può calcolare $hash(m''||m')$, dove $||$ indica la concatenazione. Questa proprietà può essere utilizzata per rompere gli schemi di autenticazione ingenui basati sulle funzioni hash. La costruzione di HMAC lavora su questi tipi di problemi.

### Grado di difficoltà

Nella crittografia pratica, con il termine "difficile" in genere si intende "quasi certamente oltre la portata di un qualsiasi avversario al quale deve essere impedito di rompere il sistema finché la sicurezza del sistema venga ritenuta importante". Il significato del termine è quindi leggermente dipendente dall'applicazione, poiché lo sforzo che un agente maligno può dedicare al suo lavoro è di solito proporzionale al suo guadagno previsto. Tuttavia, dal momento che gli sforzi da parte dell'attaccante aumentano rapidamente con la lunghezza del digest, gioverebbe il sistema se ad esso venissero aggiunte alcune dozzine di bit, con la capacità di neutralizzare anche un vantaggio di un migliaio di volte nel potere di elaborazione.
Per messaggi brevi, come ad esempio le password, si può riuscire ad invertire un hash provando tutti i messaggi possibili nell'insieme ma, poiché le funzioni crittografiche di hash sono progettate per essere calcolate rapidamente, sono state sviluppate delle funzioni di derivazione della chiave che richiedono maggiori risorse di calcolo rendendo, di conseguenza, più difficili possibili attacchi di forza bruta.
In alcune analisi teoriche, "difficile" assume un significato matematico specifico, come "non risolvibile nel tempo polinomiale asintotico". Tali interpretazioni di difficoltà sono importanti nello studio di funzioni crittografiche di hash probabilmente sicure, ma solitamente non hanno corrispondenza nella sicurezza pratica. Ad esempio, si può notare come un algoritmo di tempo esponenziale può talvolta essere abbastanza veloce da rendere un attacco fattibile; d'altra parte, un algoritmo di tempo polinomiale, contrariamente a quello esponenziale, può risultare troppo lento per qualsiasi uso pratico.

## Illustrazione

Un'illustrazione del potenziale uso di un hash crittografico è la seguente:
* Alice pone un problema difficile di matematica a Bob, affermando di averlo risolto;
* Bob vorrebbe risolvere anche lui lo stesso problema, ma vorrebbe essere sicuro che Alice non stia bluffando;
* Alice scrive la sua soluzione, calcola il suo hash e lo riferisce a Bob (mantenendo la soluzione segreta);
* quando Bob torna con la soluzione pochi giorni dopo, Alice può dimostrare di aver avuto la soluzione in precedenza rivelandola;
* Una volta rivelata, avendo l'hash di Bob, Alice può controllare che questo corrisponda effettivamente al valore di hash precedentemente calcolato da lei.
Nella pratica reale, Alice e Bob sono spesso programmi informatici e, ovviamente, il segreto consisterà in qualcosa di poco facile da imbrogliare: tale esempio riconduce quelli che in inglese vengono detti “schemi di impegno”.

## Applicazioni
### Verifica dell'integrità di un messaggio

Un'importante applicazione delle funzioni crittografiche di hash è nella verifica dell'integrità di un messaggio. Per mezzo di tali funzioni è possibile determinare, ad esempio, se sono state compiute modifiche ad un messaggio (o ad un file) confrontando il suo hash prima e dopo la trasmissione. Un particolare uso ne viene fatto nella maggior parte degli algoritmi di firma digitale, i quali utilizzano le funzioni di hash al fine di produrre una firma tale da garantire l'autenticità di un messaggio, evitando che un possibile destinatario modifichi un documento firmato da qualcun altro. Per questo motivo il valore di hash viene anche detto impronta digitale del messaggio. La verifica quindi dell'autenticità del valore di hash del messaggio viene considerata come prova di autenticità del messaggio stesso.
Verifica delle password
Nelle applicazioni che necessitano di un'adeguata autenticazione è troppo rischioso memorizzare le password di tutti gli utenti in chiaro, cioè su un file non cifrato, soprattutto nel caso in cui quest'ultimo venga compromesso. Un modo per evitare di andare incontro a una vera e propria violazione della sicurezza è quello di memorizzare solo il valore di hash di ogni password: una volta avvenuta l'autenticazione da parte dell'utente, viene calcolato l'hash della password da lui inserita e il risultato viene confrontato con l'hash memorizzato in precedenza. Spesso, la password viene concatenata con un valore casuale e non segreto, denominato salt (sale), prima ancora che venga applicata la funzione hash. Utilizzati insieme, ma memorizzati separatamente, producono un output che sostituisce le sole password, consentendo dunque agli utenti di autenticarsi. Tenendo in considerazione il sale e il fatto che, generalmente, gli utenti ne possiedono diversi, non è possibile archiviare tabelle di valori di hash pre-computati per le password comuni. Però, come già accennato in precedenza, essendo da un lato le password dei messaggi brevi e le funzioni di hash progettate per essere calcolate rapidamente dall'altro, è possibile essere soggetti ad attacchi di forza bruta (basta considerare che la GPU può provare miliardi di possibili password al secondo). In compenso, esistono delle funzioni, denominate funzioni di stretching della chiave, come PBKDF2, Bcrypt o Scrypt che "potenziano" le password per renderle più sicure di fronte ad un attacco di forza bruta.

### Proof-of-Work

Il sistema proof-of-work è una misura economica per scoraggiare attacchi di tipo denial of service e altri abusi di servizio (come lo spam su una rete) che impone certi lavori da parte del richiedente del servizio, di solito intesi come tempo di elaborazione di un computer. Una caratteristica fondamentale di questi sistemi è la loro asimmetria: il lavoro deve essere moderatamente complesso (ma fattibile) sul lato richiedente, ma nello stesso tempo, per il fornitore di servizi (service provider) risulta semplice da controllare. Un sistema famoso, usato nella generazione di bitcoin e in hashcash, usa inversioni di hash parziali per verificare che il lavoro sia stato fatto, in modo tale da sbloccare una ricompensa (detto reward di Bitcoin) nel caso di Bitcoin o come un token di buona volontà da inviare via e-mail ad Hashcash. In pratica, il mittente è tenuto a trovare un messaggio il cui valore hash inizia con un numero di bit zero: il lavoro medio che egli deve eseguire per trovare un messaggio valido è esponenziale nel numero di bit zero richiesti nel valore hash. D'altra parte, il destinatario può verificare la validità del messaggio eseguendo una singola funzione hash. Ad esempio, in hashcash, se ad un mittente venisse richiesto di generare un header il cui valore hash SHA-1 a 160 bit ha come primi 20 bit degli zeri, dovrà in media provare 219 volte prima di trovare un header valido.

### Identificatore di file o dati

In quelle applicazioni in cui si necessita di gestire grandi quantitativi di file, un digest dei messaggi può anche essere utile nell'identificazione di essi in maniera affidabile. Diversi sistemi di gestione di codice sorgente, tra cui Git, Mercurial e Monotone, utilizzano il sha1sum (un algoritmo che calcola e verifica gli hash SHA-1) di vari tipi di contenuti (contenuti di file, alberi di directory, informazioni genealogiche, ecc.) per identificarli in modo univoco. Lo stesso obiettivo vuole essere raggiunto dalle reti di condivisione di file peer-to-peer dove, ad esempio, in un link ed2k, un hash di tipo MD4 è combinato con la dimensione del file, fornendo informazioni sufficienti per individuare le origini del file stesso, scaricarlo e verificarne il contenuto. I collegamenti magnetici (magnet links) ne costituisce un altro esempio. Avendo a disposizione funzioni hash di un certo tipo, una delle principali applicazioni delle funzioni crittografiche è quella di consentire la rapida ricerca di dati in una tabella hash. Tuttavia, rispetto alle funzioni di hash standard, le funzioni crittografiche di hash tendono ad essere più dispendiose in termini di calcolo. Per questo motivo, vengono utilizzate in contesti in cui è necessario che gli utenti siano protetti dalla possibilità di contraffazione (creazione di dati con lo stesso digest) da parte di partecipanti potenzialmente dannosi.

### Generazione di numeri pseudocasuali e chiavi di derivazione

Le funzioni di hash possono essere impiegate anche per la generazione di stringhe pseudorandom o per la derivazione di chiavi e password da una singola chiave o password sicura.

## Funzioni di hash basate su cifrari a blocchi

Esistono diversi metodi per usare i cifrari a blocchi per la creazione di una funzione crittografica di hash, o meglio, di una funzione di compressione a senso unico. I metodi di applicazione somigliano alle modalità di funzionamento dei cifrari a blocchi utilizzate di solito nella crittografia. Molte funzioni di hash ben note, tra cui MD4, MD5, SHA-1 e SHA-2, sono costruite da componenti di cifratura a blocchi adatti allo scopo, con dei feedback per assicurare che la funzione risultante non sia invertibile. I finalisti di SHA-3 includevano delle funzioni con componenti di cifratura a blocchi (ad esempio Sklein o BLAKE), anche se, successivamente, è stata scelta la funzione Keccak, costruita invece su una funzione spugna. È possibile utilizzare un cifrario a blocchi standard come AES al posto di cifrari a blocchi custom, che potrebbero essere utili quando un sistema embedded ha bisogno di implementare sia la crittografia che l'hashing con dimensioni minime di codice o area hardware. Tale approccio però, può avere costi in efficienza e sicurezza.
I cifrari nelle funzioni di hash sono costruiti per l'hashing: essi usano grosse chiavi e blocchi, possono modificare in maniera efficiente le chiavi di ogni blocco e sono state progettate e verificate per la resistenza agli attacchi delle chiavi correlate. I cifrari di uso generale tendono ad avere diversi obiettivi di progettazione; in particolare, AES ha dimensioni di chiavi e di blocchi che lo rendono non banale da utilizzare per generare lunghi valori di hash. La crittografia AES diventa meno efficace quando la chiave cambia ogni blocco e gli attacchi relativi alla chiave lo rendono potenzialmente meno sicuro per l'utilizzo in una funzione hash, quanto nella crittografia.

## Design della funzione di hash
### Costruzione di Merkle-Damgård

Una funzione di hash deve essere in grado di elaborare un messaggio di lunghezza arbitraria in un output di lunghezza fissa: ciò può essere ottenuto spezzando l'input in una serie di blocchi di uguale dimensione e operando su di essi in sequenza usando una funzione di compressione a senso unico. La funzione di compressione può essere progettata appositamente per l'hashing o per essere costruita da una cifratura a blocchi. Una funzione di hash costruita con la costruzione di Merkle-Damgård è resistente alle collisioni e alla sua funzione di compressione; qualsiasi collisione per la funzione di hash completa può essere ricondotta ad una collisione nella funzione di compressione.
Nella costruzione di Merkle-Damgård, l'ultimo blocco processato deve essere "imbottito" senza ambiguità di una lunghezza padding: questo passaggio è fondamentale per la sicurezza di questa costruzione.
Le forme classiche di hash più comuni, tra cui SHA-1 e MD5 assumono questa forma.

### Differenza tra hash a pipe stretta ed hash a pipe larga

Un'applicazione diretta della costruzione di Merkle-Damgård, dove la dimensione dell'uscita hash è uguale alla dimensione dello stato interno (tra ogni fase di compressione), si traduce in un disegno di hash a pipe stretta (narrow pipe). Questo disegno causa molti difetti, tra cui estensioni di lunghezza, multicollisione, attacchi di messaggi lunghi, attacchi di generate-and-paste e non possono essere parallelizzati. Di conseguenza, le costruzioni moderne prevedono un hash a pipe larga (wide-pipe) che hanno una dimensione maggiore dello stato interno, che vanno dai ritocchi della costruzione di Merkle-Damgård a nuove costruzioni come la costruzione spugna e la costruzione di HAIFA. Nessuno dei partecipanti al concorso della funzione hash NIST utilizza una costruzione classica di Merkle-Damgård.
Nel frattempo, troncare l'output di un hash più lungo, come viene fatto in SHA-512/256, sconfigge anche molti di questi attacchi.

## Utilizzo per la costruzione di altre primitive crittografiche

Le funzioni di hash possono essere usate per costruire altre primitive crittografiche: per fare in modo che siano protette in modo crittografico, occorre prestare attenzione nel costruirle correttamente.
I codici di autenticazione dei messaggi (MAC), chiamati anche funzioni di hash con chiave, sono spesso costruite mediante funzioni di hash. HMAC si comporta come un MAC.
Proprio come i cifrari a blocchi possono essere usati per generare delle funzioni hash, vale il viceversa, ovvero anche quest'ultime possono essere utilizzate per costruire dei cifrari a blocchi. Le costruzioni di Luby-Rackoff, che utilizzano le funzioni di hash, possono essere sicure solo se la funzione di hash sottostante è altrettanto sicura. Inoltre, molte funzioni di hash (tra cui SHA-1 e SHA-2) sono costruite utilizzando una speciale cifratura a blocchi nel Davies-Meyer o in un'altra costruzione. Questo cifrario può essere anche utilizzato per funzionare in modo convenzionale, senza le stesse garanzie di sicurezza (vedasi SHACAL, BEAR e LION).
Anche i generatori di numeri pseudocasuali (PRNG) possono essere costruiti usando le funzioni hash; per fare questo si combina un seme casuale (segreto) con un contatore, dopodiché si effettua l'hashing.
Alcune funzioni di hash, come Sklein, Keccak e RadioGatún generano in output un flusso arbitrariamente lungo e possono essere utilizzati come un cifrario a flusso. Anche i cifrari a flusso possono essere costituiti dal digest di lunghezza fissa delle funzioni hash: questo viene fatto costruendo dapprima un generatore di numeri pseudocasuali crittograficamente sicuro, poi utilizzando il suo flusso di byte casuali come keystream. A tal proposito, SEAL è un cifrario di flusso che utilizza SHA-1 per generare tabelle interne, che vengono poi utilizzate in un generatore di keystream più o meno correlate all'algoritmo di hash. SEAL però, non è garantita per essere forte (o debole) come SHA-1.
Allo stesso modo, l'espansione della chiave dei cifrari a flusso HC-128 e HC-256 fa parecchio uso della funzione hash SHA256.

## Concatenazione di più funzioni di hash

Per gestire le collisioni, uno dei metodi più diffusi è quello dell'hash con concatenazione (chaining). Prima di Antoine Joux, noto crittografo francese, si sosteneva che l'output di concatenazione di due funzioni hash fornisse una resistenza alla collisione paragonabile agli algoritmi di hashing più robusti, maggiore rispetto a quella che sarebbero in grado di fornire le singole funzioni di hash. Per esempio, le versioni precedenti di Transport Layer Security (TLS) e Secure Sockets Layer (SSL) usano MD5 e SHA-1 come concatenazione. Da un simile ragionamento viene facile pensare che ciò avrebbe portato quindi a voler sfruttare le funzioni di hash deboli per poi procedere alla realizzazione di un algoritmo effettivamente più robusto; tuttavia, per la costruzione di Merkle-Damgård, il risultato concatenato non risulta essere necessariamente più resistente alla collisione rispetto alle sue componenti più forti. Più generalmente, se un attacco può produrre una collisione in uno stato interno della funzione di hash, l'equivalente di un attacco rivolto contro la costruzione concatenata corrisponde a un attacco del compleanno contro altre funzioni: ciò quindi non rende veritiero il concetto espresso in precedenza in merito alla concatenazione.
Lo stesso Joux, ha osservato che un numero pari a 2 collisioni scatenano n collisioni: se, per un aggressore, è fattibile riuscire a trovare due messaggi con lo stesso hash MD5, allora può trovare tutti i messaggi che desidera con identici hash MD5 senza più riscontrare alcuna difficoltà. L'ulteriore lavoro necessario per trovare una collisione SHA-1 (al di là della ricerca del compleanno esponenziale) richiede solo il tempo polinomiale.

## Algoritmi di hash crittografico

Al giorno d'oggi esistono molte funzioni crittografiche di hash, anche se è stato dimostrato che alcune di esse sono vulnerabili e, pertanto, sarebbe meglio se non venissero utilizzate. Anche se una funzione non è mai stata compromessa, un attacco crittografico andato a buon fine su una sua variante può compromettere la fiducia degli esperti, portando ad un successivo abbandono della funzione stessa. Ad esempio, nell'agosto del 2004 sono state riscontrate alcune debolezze in diverse funzioni di hash che in quel momento erano ritenute popolari, tra cui SHA-0, RIPEMD e MD5. In particolare, il 12 agosto, Joux, Carribault, Lemuet e Jalby hanno annunciato una collisione per il pieno algoritmo SHA-0: hanno potuto realizzare quanto accaduto utilizzando una generalizzazione dell'attacco Chabaud e Joux. È stato trovato che la collisione ha avuto complessità 2$^{51}$ e ha impiegato circa 80000 ore di CPU in un supercomputer con 256 processori Itanium 2 (pari a 13 giorni di utilizzo a tempo pieno del supercomputer). Successivamente, nel febbraio del 2005 è stato segnalato un attacco a SHA-1 che avrebbe trovato una collisione in circa 2$^{69}$ operazioni di hashing, piuttosto che in 2$^{80}$ previsti per una funzione di hash a 160 bit. Nell'agosto dello stesso anno, è stato segnalato un altro attacco a SHA-1 che avrebbe trovato collisioni in 2$^{63}$ operazioni.
Queste debolezze hanno messo in discussione la sicurezza degli algoritmi più robusti derivanti dalle funzioni di hash deboli: in particolare, SHA-1 (una versione rafforzata di SHA-0), RIPEMD-128 e RIPEMD-160 (entrambe sono le versioni rafforzate di RIPEMD). Data l'esistenza delle versioni rafforzate, gli algoritmi SHA-0 e RIPEMD sono stati sostituiti e, di conseguenza, sono adesso scarsamente utilizzati.
I ricercatori di sicurezza suggeriscono che le nuove applicazioni possono evitare questi problemi utilizzando le versioni più recenti della famiglia SHA (come SHA-2), oppure, utilizzando tecniche come l'hashing randomizzato (randomized hashing) che non richiede resistenza alle collisioni. Tuttavia, per garantire la robustezza a lungo termine delle applicazioni che utilizzano le funzioni di hash, c'è stata una competizione per progettare una sostituzione per l'algoritmo SHA-2. Il 2 ottobre 2012, Keccak è stato selezionato come vincitore della competizione delle funzioni di hash di NIST: una versione di questo algoritmo divenne uno standard FIPS il 5 agosto 2015, noto come SHA-3.
Un altro finalista della competizione, BLAKE, è stato ottimizzato per produrre BLAKE2 che è noto per essere più veloce di SHA-3, SHA-1 o MD5. Per questo motivo, si può riscontrare un utilizzo significativo di tale algoritmo in numerose applicazioni e librerie.
Il 23 febbraio 2017 un team di ricercatori di Google ha annunciato di aver realizzato con successo la prima collisione per SHA-1 nell'ambito del progetto SHAttered, avendo creato con successo due diversi file PDF aventi lo stesso hash.
| Algoritmo e variante | Algoritmo e variante | Dimensione dell'output (bit) | Dimensione dello stato interno (bit) | Dimensione del blocco (bit) | Dimensione max del messaggio (bit) | Dimensione della word (bit) | Passaggi | Operazioni | Collisioni trovate |
| SHA-0 | SHA-0 | 160 | 160 | 512 | 2$^{64}$ − 1 | 32 | 80 | +,and,or,xor, rotl | Sì |
| SHA-1 | SHA-1 | 160 | 160 | 512 | 2$^{64}$ − 1 | 32 | 80 | +,and,or,xor, rotl | Attacco 2$^{63}$ |
| SHA-2 | SHA-256/224 | 256/224 | 256 | 512 | 2$^{64}$ − 1 | 32 | 64 | +,and,or,xor,shr, rotr | Nessuna |
| SHA-2 | SHA-512/384 | 512/384 | 512 | 1024 | 2$^{128}$ − 1 | 64 | 80 | +,and,or,xor,shr, rotr | Nessuna |