Come generare dati pseudocasuali crittograficamente forti molto rapidamente?

6

Qual è il modo migliore per generare un flusso veloce di dati pseudocasuali crittograficamente forti senza installare pacchetti non comuni? Disegnare da / dev / urandom è troppo lento.

Mi è venuta l'idea di leggere la manpage "wipe":

will use the fresh RC6 algorythm as a PRNG; RC6 is keyed with the 128-bit seed, and then a null block is repeatedly encrypted to get the pseudo-random stream.

La crittografia di un blocco null con una sola chiave non è probabilmente l'idea migliore, specialmente quando sono richieste grandi quantità di dati pseudocasuali, quindi ho rapidamente fatto questo in bash:

while dd if=/dev/zero bs=$(shuf -n 1 -i 1024-67108864) count=1 2>/dev/null | openssl aes-256-cbc -nosalt -k "$(head -c 32 < /dev/random)"; do :; done > [whateverneedsrandomness]

Questo crittografa un flusso di zeri con un seme casuale a 32 byte. Il flusso viene riavviato in media ogni 32 MB (l'intervallo è compreso tra 1 KB e 64 MB con una risoluzione di un byte). L'intervallo di reseeding è casuale per impedire a chiunque di indovinare dove viene utilizzata una nuova chiave. Ho deciso di utilizzare CBC come modalità di blocco anziché CTR anche se è più veloce perché ho letto che CTR è valido solo per flussi costanti e la mia conoscenza crittografica molto limitata mi dice che un contatore ripetuto che si riavvia tutto il tempo non è un buona idea quando lo "stream" sarà lungo solo pochi MB, anche se non lo so per certo.

Una delle preoccupazioni che ho è se il flusso che sta lasciando openssl sia completamente criptato. Se l'input non è equamente divisibile per la dimensione del blocco, openssl lascerà vuoti i dati extra (lasciando "spazi vuoti" di 0 sparsi nel flusso risultante)? padding ha qualcosa a che fare con questo?

Quindi la mia domanda è, è un buon modo per creare dati casuali veloci? E c'è qualcosa che mi è sfuggito / ignorato, ecc., Come usare la modalità di blocco sbagliata?

    
posta kkarl88 24.10.2013 - 08:55
fonte

2 risposte

9

Modifica: l'ovvietà era accecante, quindi mi sono perso. OpenSSL offre già un'interfaccia al proprio PRNG interno, che è seminato con /dev/urandom della macchina, ma poi lo estende con la propria crittografia. Fai questo:

openssl rand 10000000

per produrre 10 milioni di byte pseudo-casuali. Sul mio laptop, questo sembra essere circa 3 volte più veloce di /dev/urandom , cioè 11 MByte / s circa. Se questo non è abbastanza veloce per te, continua a leggere.

Risposta originale:

Dipende davvero dall'hardware e dal contesto coinvolti. Dato che stai parlando di uno script bash, /dev/urandom e OpenSSL, suppongo che:

  • Usi Linux.
  • Vuoi produrre un grande file pieno di byte pseudocasuali.
  • Vuoi una soluzione che sia un insieme di pacchetti esistenti, "normali", non una soluzione programmatica.

In effetti, se si potesse scrivere il proprio codice C, le opzioni migliori sarebbero la crittografia AES in modalità CTR con AES-NI istruzioni (sul PC recente che offre queste istruzioni) o un codice stream dedicato (ad esempio uno dei questi ). Su una CPU Core2 a 2,4 GHz, potrei ottenere 700 MByte / s di byte pseudocasuali da Sosemanuk. Suppongo che tu sia limitato agli script.

L'uso della crittografia OpenSSL non è una cattiva idea, ma ci sono dettagli:

  • Randomizzare la lunghezza di ogni blocco è una complicazione inutile.
  • Non è necessario andare su AES-256; AES-128 è già a posto. AES-256 è più lento del 40% rispetto a AES-128 e non aggiunge alcun miglioramento pratico nella sicurezza.
  • Quando si crittografa una lunga sequenza di zeri con CBC, si sta effettivamente eseguendo il codice di blocco in modalità OFB (crittografare un blocco, crittografarlo di nuovo, e ancora e ancora). Questo è ragionevole finché rimani al di sotto del limite 2 n / 2 , il che significa che con AES (blocchi a 128 bit) non usi un blocco più lungo di < em> 2 64 blocchi da 16 byte, ovvero 250 milioni di terabyte. È probabile che non lo raggiungerai comunque. In questo senso, il "reseeding" non è veramente necessario.
  • Quando hai "risettato" (se decidi di mantenere questa funzione, che non è necessaria), usa /dev/urandom , non /dev/random . /dev/urandom va bene per la crittografia (gli script di avvio del sistema operativo assicurano che il PRNG interno sia correttamente seminato), nonostante i problemi paranoici errati dell'implementazione /dev/random . D'altra parte, /dev/random può bloccare, e quindi essere veramente lento (niente è più lento di un processo bloccato).
  • Attenzione alle stringhe. bash usa stringhe di caratteri; /dev/random e /dev/urandom restituiscono byte , compresi i byte di valore 0. Ciò potrebbe causare una chiave troncata artificialmente e una sicurezza ridotta. Questo non va bene. Invece, dovresti codificare i byte in esadecimale e gli argomenti -K e -iv da riga di comando con openssl .
  • OpenSSL può aggiungere un'intestazione che inizia con 8 byte fissi (quindi totalmente non casuali). Non lo fa se usi -K e -iv .
  • OpenSSL userà anche un po 'di padding in modo da ottenere un blocco extra di 16 byte alla fine (questo non è un problema, il padding è in chiaro e la crittografia lo "randomizza").

Questo porta al seguente script:

#!/bin/sh
key=$(dd if=/dev/urandom bs=16 count=1 2>/dev/null | md5sum | cut -d' ' -f1)
iv=$(dd if=/dev/urandom bs=16 count=1 2>/dev/null | md5sum | cut -d' ' -f1)
dd if=/dev/zero bs=65536 count=8192 2>/dev/null | openssl aes-128-cbc -K $key -iv $iv

Quando viene invocato, questo script emette una sequenza di esattamente 536870928 byte pseudocasuali, che sono adatti per scopi crittografici. Sentiti libero di modificare i parametri bs e count , ma ricorda che dd alloca un buffer RAM di dimensione bs , quindi di solito vuoi mantenere bs piccolo, ma non troppo piccolo per evitare troppi roundtrip nel kernel (da 8192 a 65536 di solito sono buoni valori).

Uso MD5 qui solo per comodità della conversione da byte a esadecimale (le carenze note di MD5 non hanno alcuna influenza sulla sicurezza in questo caso).

Questo script dovrebbe funzionare su qualsiasi installazione Linux decente. Usa solo i pacchetti che dovrebbero essere lì per impostazione predefinita. Sul mio portatile non molto potente, questo script produce byte pseudocasuali alla velocità di 73 MByte al secondo, che non è male e probabilmente sufficiente per i tuoi scopi (se questo non è sufficiente, probabilmente avrai altri problemi con I / O colli di bottiglia).

    
risposta data 24.10.2013 - 16:13
fonte
1

Se ti ritrovi spesso a svuotare la sorgente di dati casuali, ti consiglierei di investire in un generatore di numeri casuali hardware come link .

In genere sei limitato alla quantità di dati casuali che possono essere generati dall'hardware del generatore di numeri casuali sulla tua CPU. Dispositivi esterni come questi possono generare buoni dati casuali a un ritmo molto più veloce.

    
risposta data 24.10.2013 - 11:07
fonte

Leggi altre domande sui tag