L'articolo di Wikipedia sulle funzioni di hash è molto buono, ma qui darò la mia opinione.
Che cos'è un hash?
"Hash" è in realtà un termine generico con significati formali diversi in contesti diversi. Non esiste un'unica risposta perfetta alla tua domanda. Spiegherò il concetto generale alla base e menzionerò alcuni degli usi più comuni del termine.
Un "hash" è una funzione definita funzione hash
che accetta come oggetti di input e genera una stringa o un numero. Gli oggetti di input sono generalmente membri di tipi di dati di base come stringhe, numeri interi o più grandi composti da altri oggetti come strutture definite dall'utente. L'output è in genere un numero o una stringa. Il nome "hash" si riferisce spesso a questo output. Il verbo "hash" spesso significa "applica una funzione hash". Le proprietà principali che dovrebbe avere una funzione hash sono:h
- Dovrebbe essere facile da calcolare e
- Gli output dovrebbero essere relativamente piccoli.
Esempio:
Supponiamo di voler eseguire l'hashing dei numeri nell'intervallo da 0 a 999.999.999 al numero compreso tra 0 e 99. Una semplice funzione di hash può essere .h ( x ) = xmod100
Proprietà aggiuntive comuni:
A seconda del caso d'uso, è possibile che la funzione hash soddisfi le proprietà aggiuntive. Ecco alcune proprietà aggiuntive comuni:
Uniformità : spesso vogliamo che gli hash degli oggetti siano distinti. Inoltre potremmo voler "diffondere" gli hash. Se voglio eseguire l'hashing di alcuni oggetti in 100 bucket (quindi l'output della mia funzione hash è un numero compreso tra 0 e 99), di solito spero che circa 1/100 oggetti atterrino nel bucket 0, circa 1/100 atterrino in secchio 1 e così via.
Resistenza alle collisioni crittografiche : a volte questo è preso ancora di più, ad esempio, nella crittografia potrei volere una funzione hash tale che per un avversario è difficile dal punto di vista computazionale trovare due input diversi che mappano sullo stesso output.
Compressione : spesso desidero eseguire il hash di input arbitrariamente grandi in un output di dimensioni costanti o in un numero fisso di bucket.
Determinismo : potrei desiderare una funzione hash il cui output non cambi tra le esecuzioni, ovvero l'output della funzione hash sullo stesso oggetto rimarrà sempre lo stesso. Ciò può sembrare in conflitto con l'uniformità di cui sopra, ma una soluzione è scegliere una volta la funzione hash in modo casuale e non cambiarla tra le esecuzioni.
Alcune applicazioni
Un'applicazione comune è in strutture di dati come una tabella hash, che sono un modo per implementare dizionari. Qui, allocare un po 'di memoria, diciamo, 100 "secchi"; quindi, quando viene richiesto di memorizzare una coppia (chiave, valore) nel dizionario, si esegue l'hashing della chiave in un numero 0-99 e si memorizza la coppia nel bucket corrispondente in memoria. Quindi, quando ti viene chiesto di cercare una chiave, esegui l'hashing della chiave in un numero 0-99 con la stessa funzione hash e controlla quel bucket per vedere se quella chiave è lì. In tal caso, si restituisce il suo valore.
Tieni presente che puoi anche implementare dizionari in altri modi, ad esempio con un albero di ricerca binario (se i tuoi oggetti sono comparabili).
Un'altra applicazione pratica sono i checksum, che sono modi per verificare che due file siano uguali (ad esempio, il file non è stato danneggiato dalla sua versione precedente). Poiché è molto improbabile che le funzioni hash mappino due input allo stesso output, si calcola e memorizza un hash del primo file, solitamente rappresentato come una stringa. Questo hash è molto piccolo, forse solo poche decine di caratteri ASCII. Quindi, quando si ottiene il secondo file, l'hash e si verifica che l'output sia lo stesso. In tal caso, quasi sicuramente è lo stesso file byte per byte.
Un'altra applicazione è nella crittografia, in cui questi hash dovrebbero essere difficili da "invertire" - vale a dire, dato l'output e la funzione hash, dovrebbe essere difficile dal punto di vista computazionale l'input che ha portato a quell'output. Un uso di questo è per le password: invece di archiviare la password stessa, memorizzi un hash crittografico della password (forse con alcuni altri ingredienti). Quindi, quando un utente immette una password, calcoli il suo hash e controlli che corrisponda all'hash corretto; in tal caso, dici che la password è corretta. (Ora anche qualcuno che può cercare e scoprire l'hash salvato sul server non ha un tempo così semplice fingendo di essere l'utente.) Questa applicazione può essere un caso in cui l'output è lungo o più lungo dell'input, dal momento che l'ingresso è così breve.