2012-04-26 10 views
15

Sto lavorando a un progetto con un amico in cui è necessario generare un hash casuale. Prima che avessimo il tempo di discutere, entrambi abbiamo escogitato approcci diversi e, poiché utilizzano moduli diversi, volevo chiederti tutto ciò che sarebbe stato meglio, se c'è una cosa del genere.Che cosa è più casuale, hashlib o urandom?

hashlib.sha1(str(random.random())).hexdigest() 

o

os.urandom(16).encode('hex') 

Digitando questa domanda fuori ha mi ha fatto pensare che il secondo metodo è migliore. Semplice è meglio che complesso. Se sei d'accordo, quanto è affidabile questo per gli hash "casuali" che generano? Come potrei verificare questo?

risposta

36

Questa soluzione:

os.urandom(16).encode('hex') 

è la migliore poiché uses the OS generare casualità che dovrebbe utilizzabile per scopi crittografici (dipende da un'applicazione OS).

random.random() genera pseudo-random values.

L'hashing di un valore casuale non aggiunge nuove casualità.

+0

Questi sono tutti molto grandi risposte. Grazie. – Flowpoke

+0

AttributeError: l'oggetto 'bytes' non ha attributo 'encode' – treecoder

+0

@greengit: è molto probabile che il piccolo snippet sopra sia indirizzato alla versione 2.x di Python (non testata in 3.x) – ChristopheD

2

Testing casualità è notoriamente difficile - tuttavia, avrei scelto il secondo metodo, ma SOLO (o, solo per quanto viene in mente) per questo caso, in cui l'hash è seminato da un numero casuale.

Il punto di hash è quello di creare un numero che è molto diverso basato su leggere differenze di ingresso. Per il tuo caso d'uso, la casualità dell'input dovrebbe fare. Se, tuttavia, si desidera eseguire l'hash di un file e rilevare una differenza di un eensy, allora l'algoritmo hash si illumina.

Sono solo curioso, però: perché utilizzare un algoritmo hash? Sembra che tu stia cercando un numero puramente casuale, e ci sono molte librerie che generano uuid, che hanno garanzie di univocità molto più forti rispetto ai generatori di numeri casuali.

7

random.random() è un generatore di pseudo-radmom, ovvero i numeri vengono generati da una sequenza. se chiami random.seed(some_number), dopo di ciò la sequenza generata sarà sempre la stessa.

os.urandom() ottenere i numeri casuali dal sistema operativo, che utilizza un pool di entropia per raccogliere numeri casuali reali, in genere da eventi casuali da dispositivi hardware, esistono anche generatori di entropia speciali casuali per sistemi in cui sono presenti molti numeri casuali generato.

su sistema unix esistono tradizionalmente due generatori di numeri casuali: /dev/random e /dev/urandom. chiama al primo blocco se non c'è abbastanza entropia disponibile, mentre quando leggi /dev/urandom e non ci sono abbastanza dati di entropia disponibili, usa uno pseudo-rng e non blocca.

quindi l'utilizzo dipende in genere da ciò che è necessario: se sono necessari alcuni numeri casuali equamente distribuiti, allora il built-in prng dovrebbe essere sufficiente. per l'uso crittografico è sempre meglio usare numeri casuali reali.

7

La seconda soluzione ha chiaramente più entropia della prima.Supponendo che la qualità della sorgente dei bit casuali sarebbe lo stesso per os.urandom e random.random:

  • Nella seconda soluzione si recuperano 16 byte = 128 bit di valore di casualità
  • Nella prima soluzione si recuperano un valore in virgola mobile che ha approssimativamente 52 bit di casualità (IEEE 754 double, ignorando numeri subnormali, ecc ...). Poi lo fai in giro, il che, ovviamente, non aggiunge alcuna casualità.

Ancora più importante, si prevede che la qualità della casualità proveniente da os.urandom e documentato di essere molto meglio di quanto la casualità provenienti da random.random. La documentazione di os.urandom dice "adatto per l'uso crittografico".

Problemi correlati