Quanto è sicuramente casuale il java.security.SecureRandom di Oracle

10

Nell'ultimo anno ci sono state molte notizie sulle debolezze sfruttabili nella crittografia, originate da deboli generatori di numeri casuali. In alcuni casi era negligenza da parte degli sviluppatori, in altri era organizzazioni di intelligence che intenzionalmente sabotavano gli standard per la generazione sicura di RNG .

Che dire dell'implementazione del SecureRandom generatore di numeri casuali usato in JavaVM di Oracle? Quale algoritmo sta usando quando non ne specifichi uno? E questo algoritmo e la sua implementazione sono abbastanza sicuri da poter essere utilizzati in crittografia?

    
posta Philipp 31.12.2013 - 14:01
fonte

1 risposta

13

Il codice sorgente completo di JDK (non solo le classi standard, ma anche le classi specifiche di Sun e il codice nativo C ++) era disponibile sotto una "licenza di ricerca", e ho una copia sul mio disco, per JDK 1.6 (Suppongo che al giorno d'oggi tu andassi su OpenJDK).

Vediamo che la creazione di un'istanza java.security.SecureRandom implica il richiamo del PRNG predefinito che capita di essere la classe specifica del sole sun.security.provider.SecureRandom .

Il PRNG è seminato da sun.security.provider.SeedGenerator che a sua volta proverà a fare affidamento su ciò che l'OS fornisce, cioè /dev/urandom o /dev/random su sistemi Unix-like (come Linux), CryptGenRandom() di CryptoAPI su Windows. Se tali cose non sono disponibili (o disattivate dalla configurazione di JVM), il seed verrà estratto sincronizzando la velocità con cui il SO può cambiare i contesti tra i thread; questo è un meccanismo di fallback che è molto raramente, se non mai, innescato.

Il seed è espanso con quello che sembra essere un PRNG personalizzato e fatto in casa basato su SHA-1. Funziona così:

  • C'è uno stato s a 160 bit, che è 20 byte, ed è anche interpretato come un modulo intero 2 160 applicando la convenzione little-endian.
  • L'output è prodotto da blocchi di 20 byte.
  • Per produrre il prossimo pezzo c :
    • c = SHA-1 ( s )
    • s = s + c + 1 mod 2 160

C'è un meccanismo che assicura che s sia effettivamente cambiato in qualche punto; se s sembra non essere cambiato dall'aggiornamento, allora il suo primo byte viene incrementato con forza. Questo non è mai stato invocato; la probabilità che si verifichi tale evento è 2 -160 e forzarla con un seme speciale richiederebbe la rottura della resistenza di preimage di SHA-1, che non sappiamo come fare. / p>

Crittograficamente parlando, questo non è atroce; dovrebbe raggiungere un ciclo, in media, solo dopo circa 2 80 chunk e il ciclo dovrebbe avere la stessa lunghezza media; questo è molto (circa 24 milioni di miliardi di gigabyte), quindi va bene. Se SHA-1 è un random oracle quindi il PRNG è" ovviamente "sicuro fino a quando gli attaccanti non possono enumerare uno spazio a 160 bit (realisticamente non possono) e un dato seme non viene utilizzato per produrre più di 24 milioni di miliardi di gigabyte ( e non lo farà, non in un tempo ragionevole o addirittura irragionevole). Sappiamo che SHA-1 è non un oracolo casuale, ma sembra ancora abbastanza casuale.

Personalmente, non ritengo questo PRNG un problema per l'utilizzo crittografico; non ha una "costante magica" e quindi è molto improbabile che si trovi in una posizione arretrata. L'unica parte negativa è che è non standard , quindi sottovalutato.

Se (quando) ho bisogno di avere, in Java, casualità che è abbastanza buona per la crittografia formale (cioè buona, e anche dimostrabilmente valida per scopi di regolamentazione), quindi utilizzo java.security.SecureRandom per generare un seed iniziale (almeno 16 byte), quindi eseguo HMAC_DRBG (specificato in NIST SP800-90A ) (la stessa pubblicazione contiene il Dual_EC_DRBG di fama sinistre, ma HMAC_DRBG è nondimeno considerato buono e pulito dai crittografi).

    
risposta data 31.12.2013 - 23:11
fonte

Leggi altre domande sui tag