Per quanto riguarda il tuo aggiornamento, le tue funzioni hash crittografiche standard (MD5, SHA-1, famiglia SHA-2, SHA-3) tentano di approssimare oracoli casuali (e non tentare di essere iniettivi). Cioè tentano di mappare qualsiasi input su un'uscita scelta uniformemente a caso nello spazio di output (e di fare questa mappatura in modo coerente). Con probabilità schiacciante, gli oracoli casuali non saranno iniettabili quando il numero di possibili input è significativamente più grande della radice quadrata del numero di output possibili, a causa del compleanno paradosso .
Ad esempio, se si dispone di un output hash a 128 bit (un hash di 16 byte con 2 128 output possibili) e si utilizza un oracle casuale per hash significativamente più di sqrt (2 128 ) = 2 64 input, inizia a diventare in modo schiacciante probabile che ci saranno collisioni. D'altra parte, se hai hash significativamente meno di 2 64 input, sarà molto improbabile avere una collisione se hai iniziato con un oracolo casuale ideale. (Se hai hash circa 2 64 input rispetto alla possibilità di essere iniettivo è approssimativamente 1/2; ci può essere una collisione o meno).
Come esempio specifico, se hai tutti i 2 72 possibili input da 9 byte la probabilità che un oracolo casuale sia iniettato su uno spazio di 16 byte è circa exp (-n 2 / 2m ) ≈ 10 -14231 , dove n = 2 72 ≈ 4.7 x 10 21 e m = 2 128 ≈ 3.4 x 10 38 . Questo è incredibilmente improbabile; più o meno equivalente a giocare a powerball (probabilità di vincere 1 su 292 milioni) due volte a settimana per 16 anni e vincere il jackpot ogni volta senza perdere biglietti. E ancora, questo è solo per un input da 9 byte; con un input di 15 byte la probabilità di essere iniettiva è di circa 10 -1127492937032632506267955467381579 !
Nel frattempo, se hai tutti i possibili input a 7 byte, ce ne sono solo 2 56 quindi con una grande probabilità non ci saranno collisioni (cioè sarà iniettabile). Poiché questo è significativamente meno di sqrt (2 128 ), un oracolo casuale non sarebbe iniettabile con probabilità con probabilità di 0,0000076 (circa 1 su 130 000 volte non sarebbe iniettivo e il resto del tempo sarebbe iniettivo).
Vedi la tabella delle probabilità su wikipedia per ulteriori informazioni.
È garantito che questa non è una prova per una specifica funzione di hash; per dimostrarlo dovremmo generare una collisione specifica all'interno dello spazio di input che in generale sarebbe difficile da mostrare.
Ora se hai bisogno di una funzione iniettiva che agisce in modo simile a un hash, questo è abbastanza semplice da ottenere usando un codice a blocchi (formalmente conosciuto come permutazione pseudocasuale ) come AES e scegliere una chiave casuale per crittografarlo con. I cifrari a blocchi sono necessariamente sia iniettivi che suriettivi. Se un codice a blocchi non era iniettivo, allora una persona con la chiave e la funzione di decrittografia e un blocco di testo cifrato da decifrare con non potevano forse recuperare il blocco originale.
Lo svantaggio dell'uso di un codice a blocchi invece di una funzione di hash è che il codice a blocchi richiede l'input di una sola lunghezza fissa e lo trasforma in output della stessa lunghezza fissa. Ad esempio, AES può solo prendere un input a 128 bit e trasformarlo in un output a 128 bit. (Sì, è possibile utilizzare le modalità di cifratura a blocchi per trasformare input più grandi, ma purché sia di uno a uno, la dimensione dell'output sarà della stessa lunghezza dell'input). Il fatto che una funzione hash possa prendere input di dimensioni variabili e generare un hash di dimensioni fisse lo rende ideale per molti scopi. Il fatto che questo requisito di hash per mappare input di dimensioni variabili presi da uno spazio di input molto grande in uno spazio di output più piccolo significa che non sarà un iniettore secondo il principio del pigeonhole, di solito non è un problema nella pratica.