OneRNG
Pubblicato il dom 23 ottobre 2016 in informatica • 7 min read
Cos'è e come funziona
Circa un mese fa ho acquistato un piccolo dispositivo: l'OneRNG
.
L'OneRNG è un HWRNG
, o hardware random number generator, che si collega al pc tramite l'interfaccia USB.
Per generare dati casuali, esso sfrutta due sorgenti: un avalanche diode
, o diodo a valanga, che sfrutta l'effetto valanga; e un ricevitore RF che, variando ad intervalli casuali di tempo la frequenza, salta da un canale all'altro nella banda 2.4GHz e ogni volta campiona quanto captato prendendo in considerazione solo i bit meno significativi.
Siccome sarebbe possibile per un attaccante interferire con le frequenze radio il ricevitore RF è disabilitato di default, e viene lasciata all'utente la scelta se abilitarlo o meno.
I bit generati vengono a questo punto sottoposti ad un processo di whitening
. In questo si cerca di eliminare il bias
dovuto ad imperfezioni dei componenti elettrici e le eventuali correlazioni tra i bit per far sì che, nella sequenza di bit prodotta, 1
e 0
compaiano all'incirca con la stessa frequenza (50%). E' possibile disabilitare questo passaggio, abilitato di default, nel caso in cui l'utente volesse controllare i bit grezzi, o raw
, generati.
A questo punto i bit vengono memorizzati nella ram del dispositivo, in un buffer che lavora in modalità FIFO. Ciò significa che, man mano che arrivano nuovi dati quelli più vecchi vengono cancellati o, se richiesti, inviati all'interfaccia USB.
La sicurezza e la corrispondenza del progetto con quanto dichiarato dal costruttore possono essere valutate da chiunque, ammesso che abbia le conoscenze e le capacità, dal momento che sia gli schemi hardware che i sorgenti del firmware sono liberamente consultabili su internet.
Collegamenti versione interna
Di questo dispositivo esistono due versioni: una direttamente collegabile alla porta usb; e un'altra che si può collegare direttamente ai connettori USB presenti sulla scheda madre dei pc.
Al momento dell'acquisto era disponibile solo la seconda versione. L'ho acquistata, ma mi son dovuto documentare su come collegarla alla porta usb, visto che desideravo usarla su un portatile.
Ecco lo schema dei pin.
Installazione
Il primo passo, consigliato dai creatori è la verifica visuale dell'hardware.
L'OneRNG non richiede software particolare per essere usato su Gnu/Linux, ma è consigliabile installare i pacchetti rngd
, python-gnupg
e at
. Il primo è il demone che permette di interfacciare gli hwrng con il kernel. Il secondo serve per verificare l'autenticità del firmware ogni volta che si collega il dispositivo al pc.
La documentazione ufficiale fornisce le istruzioni per l'installazione su sistemi basati su Debian. Siccome io uso Arch Linux ho dovuto adattare le istruzioni.
Prima si installano i softwares necessari:
$ yaourt -S at python-gnupg rng-tools
$ sudo systemctl enable atd.service
$ sudo systemctl start atd.service
In seguito, dopo avere scaricato il pacchetto onerng_3.4.orig.tar.gz ed averne verificata l'autenticità controllando i checksum MD5 e SHA256,
onerng_3.4.orig.tar.gz | |
---|---|
MD5 | cbd9 4252 3ac5 3220 4393 2abc 9f36 16af |
SHA256 | 4430 137c 4bbf 4d1b 140c b56e 21b6 95e4 1521 8fb0 723c c6eb ae5a c494 3e56 b023 |
si può procedere all'installazione:
$ tar -xvzf onerng_3.4.orig.tar.gz
$ cd onerng_3.4
$ ./configure --prefix=/usr/local
$ sudo make install
$ sudo systemctl restart systemd-udevd.service
Ho dovuto modificare il file onerng.sh perché funzionasse come volevo. Questa è la patch.
Adesso collegando il dispositivo e lanciando il comando: /usr/local/sbin/onerng.sh daemon ttyACM0
dovrebbe funzionare.
Attenzione che ttyACM0
potrebbe cambiare. Per essere sicuri, dopo aver collegato il dispositivo, eseguite:
$ dmesg
fra le ultime righe dovrebbe esserci qualcosa di simile a questo:
cdc_acm 2-1.2:1.0: ttyACM0: USB ACM device
Per controllare che stia fornendo entropia al kernel tramite rngd eseguite:
$ cat /dev/random > /dev/null
il led del dispositivo dovrebbe lampeggiare a indicare il trasferimento di dati attraverso l'interfaccia USB.
Per fermare il demone basta eseguire: /usr/local/sbin/onerng.sh kill
.
Per sapere come cambiare le modalità di funzionamento su Gnu/Linux vi rimando alla documentazione ufficiale.
La documentazione riporta che il dispositivo funziona anche su Windows. Ma non ho provato.
Test entropia
Per controllare la qualità dell'entropia generata dal dispositivo ho fatto così:
stty raw -echo < /dev/ttyACM0
echo cmd0 > /dev/ttyACM0
echo cmdO > /dev/ttyACM0
dd if=/dev/ttyACM0 of=random-data.bin iflag=fullblock bs=4
Affinché la batteria di tests abbia senso è necessario generare un file di diverse decine o centinaia di MB. Per far ciò ci vuole del tempo dal momento che la velocità di produzione di dati casuali si assesta intorno ai 58 KB/s!
33640224+0 record dentro
33640224+0 record fuori
134560896 bytes (135 MB, 128 MiB) copied, 2329,52 s, 57,8 kB/s
Ho impiegato circa 40 minuti per generare 128 MiB o 134 MB di dati che ho salvato nel file random-data.bin
.
ENT
Testiamo la qualità del file generato:
# ent -b random-data.bin
Entropy = 1.000000 bits per bit.
Optimum compression would reduce the size
of this 1076487168 bit file by 0 percent.
Chi square distribution for 1076487168 samples is 0.55, and randomly
would exceed this value 45.67 percent of the times.
Arithmetic mean value of data bits is 0.5000 (0.5 = random).
Monte Carlo value for Pi is 3.142048519 (error 0.01 percent).
Serial correlation coefficient is 0.000007 (totally uncorrelated = 0.0).
I valori sembrano ottimi.
RNGTEST
Testiamo nuovamente il file con la suite rngtest
# rngtest < random-data.bin
rngtest: starting FIPS tests...
rngtest: entropy source drained
rngtest: bits received from input: 1076487168
rngtest: FIPS 140-2 successes: 53772
rngtest: FIPS 140-2 failures: 52
rngtest: FIPS 140-2(2001-10-10) Monobit: 8
rngtest: FIPS 140-2(2001-10-10) Poker: 8
rngtest: FIPS 140-2(2001-10-10) Runs: 18
rngtest: FIPS 140-2(2001-10-10) Long run: 30
rngtest: FIPS 140-2(2001-10-10) Continuous run: 4
rngtest: input channel speed: (min=353.213; avg=19324.449; max=19073.486)Mibits/s
rngtest: FIPS tests speed: (min=36.964; avg=118.620; max=147.856)Mibits/s
rngtest: Program run time: 8713323 microseconds
DIEHARDER
dieharder -a < random-data.bin
#=============================================================================#
# dieharder version 3.31.1 Copyright 2003 Robert G. Brown #
#=============================================================================#
rng_name |rands/second| Seed |
mt19937| 1.07e+08 | 697835169|
#=============================================================================#
test_name |ntup| tsamples |psamples| p-value |Assessment
#=============================================================================#
diehard_birthdays| 0| 100| 100|0.75122888| PASSED
diehard_operm5| 0| 1000000| 100|0.29286097| PASSED
diehard_rank_32x32| 0| 40000| 100|0.68215800| PASSED
diehard_rank_6x8| 0| 100000| 100|0.78634975| PASSED
diehard_bitstream| 0| 2097152| 100|0.45717075| PASSED
diehard_opso| 0| 2097152| 100|0.52793994| PASSED
diehard_oqso| 0| 2097152| 100|0.07601930| PASSED
diehard_dna| 0| 2097152| 100|0.81780900| PASSED
diehard_count_1s_str| 0| 256000| 100|0.05773551| PASSED
diehard_count_1s_byt| 0| 256000| 100|0.38460658| PASSED
diehard_parking_lot| 0| 12000| 100|0.36104913| PASSED
diehard_2dsphere| 2| 8000| 100|0.63235801| PASSED
diehard_3dsphere| 3| 4000| 100|0.69088317| PASSED
diehard_squeeze| 0| 100000| 100|0.65368689| PASSED
diehard_sums| 0| 100| 100|0.10603815| PASSED
diehard_runs| 0| 100000| 100|0.09607825| PASSED
diehard_runs| 0| 100000| 100|0.12139990| PASSED
diehard_craps| 0| 200000| 100|0.97523029| PASSED
diehard_craps| 0| 200000| 100|0.82634668| PASSED
marsaglia_tsang_gcd| 0| 10000000| 100|0.90514110| PASSED
marsaglia_tsang_gcd| 0| 10000000| 100|0.73349972| PASSED
sts_monobit| 1| 100000| 100|0.76723958| PASSED
sts_runs| 2| 100000| 100|0.09755009| PASSED
sts_serial| 1| 100000| 100|0.28480828| PASSED
sts_serial| 2| 100000| 100|0.01002843| PASSED
sts_serial| 3| 100000| 100|0.14798268| PASSED
sts_serial| 3| 100000| 100|0.93098809| PASSED
sts_serial| 4| 100000| 100|0.48844286| PASSED
sts_serial| 4| 100000| 100|0.87130349| PASSED
sts_serial| 5| 100000| 100|0.83979246| PASSED
sts_serial| 5| 100000| 100|0.61940174| PASSED
sts_serial| 6| 100000| 100|0.56442141| PASSED
sts_serial| 6| 100000| 100|0.88137535| PASSED
sts_serial| 7| 100000| 100|0.09894717| PASSED
sts_serial| 7| 100000| 100|0.93128300| PASSED
sts_serial| 8| 100000| 100|0.32497543| PASSED
sts_serial| 8| 100000| 100|0.51966769| PASSED
sts_serial| 9| 100000| 100|0.14089612| PASSED
sts_serial| 9| 100000| 100|0.66196272| PASSED
sts_serial| 10| 100000| 100|0.35722896| PASSED
sts_serial| 10| 100000| 100|0.91820212| PASSED
sts_serial| 11| 100000| 100|0.90711347| PASSED
sts_serial| 11| 100000| 100|0.68862639| PASSED
sts_serial| 12| 100000| 100|0.89332570| PASSED
sts_serial| 12| 100000| 100|0.28404443| PASSED
sts_serial| 13| 100000| 100|0.97874565| PASSED
sts_serial| 13| 100000| 100|0.95699804| PASSED
sts_serial| 14| 100000| 100|0.78300837| PASSED
sts_serial| 14| 100000| 100|0.21197719| PASSED
sts_serial| 15| 100000| 100|0.88684726| PASSED
sts_serial| 15| 100000| 100|0.64108862| PASSED
sts_serial| 16| 100000| 100|0.98893875| PASSED
sts_serial| 16| 100000| 100|0.96134073| PASSED
rgb_bitdist| 1| 100000| 100|0.95978106| PASSED
rgb_bitdist| 2| 100000| 100|0.67888214| PASSED
rgb_bitdist| 3| 100000| 100|0.53976165| PASSED
rgb_bitdist| 4| 100000| 100|0.99991855| WEAK
rgb_bitdist| 5| 100000| 100|0.17634384| PASSED
rgb_bitdist| 6| 100000| 100|0.72633098| PASSED
rgb_bitdist| 7| 100000| 100|0.50466003| PASSED
rgb_bitdist| 8| 100000| 100|0.63603276| PASSED
rgb_bitdist| 9| 100000| 100|0.97853515| PASSED
rgb_bitdist| 10| 100000| 100|0.10884572| PASSED
rgb_bitdist| 11| 100000| 100|0.38332441| PASSED
rgb_bitdist| 12| 100000| 100|0.83311998| PASSED
rgb_minimum_distance| 2| 10000| 1000|0.73048502| PASSED
rgb_minimum_distance| 3| 10000| 1000|0.80365932| PASSED
rgb_minimum_distance| 4| 10000| 1000|0.39634909| PASSED
rgb_minimum_distance| 5| 10000| 1000|0.05042959| PASSED
rgb_permutations| 2| 100000| 100|0.29827891| PASSED
rgb_permutations| 3| 100000| 100|0.42773147| PASSED
rgb_permutations| 4| 100000| 100|0.61540487| PASSED
rgb_permutations| 5| 100000| 100|0.32194101| PASSED
rgb_lagged_sum| 0| 1000000| 100|0.44978482| PASSED
rgb_lagged_sum| 1| 1000000| 100|0.34319264| PASSED
rgb_lagged_sum| 2| 1000000| 100|0.15636753| PASSED
rgb_lagged_sum| 3| 1000000| 100|0.59582094| PASSED
rgb_lagged_sum| 4| 1000000| 100|0.45639375| PASSED
rgb_lagged_sum| 5| 1000000| 100|0.98890951| PASSED
rgb_lagged_sum| 6| 1000000| 100|0.75362200| PASSED
rgb_lagged_sum| 7| 1000000| 100|0.99182650| PASSED
rgb_lagged_sum| 8| 1000000| 100|0.93306335| PASSED
rgb_lagged_sum| 9| 1000000| 100|0.23951408| PASSED
rgb_lagged_sum| 10| 1000000| 100|0.76050282| PASSED
rgb_lagged_sum| 11| 1000000| 100|0.87830187| PASSED
rgb_lagged_sum| 12| 1000000| 100|0.17785311| PASSED
rgb_lagged_sum| 13| 1000000| 100|0.51502949| PASSED
rgb_lagged_sum| 14| 1000000| 100|0.93862858| PASSED
rgb_lagged_sum| 15| 1000000| 100|0.29350929| PASSED
rgb_lagged_sum| 16| 1000000| 100|0.92137610| PASSED
rgb_lagged_sum| 17| 1000000| 100|0.04790957| PASSED
rgb_lagged_sum| 18| 1000000| 100|0.83045339| PASSED
rgb_lagged_sum| 19| 1000000| 100|0.23776364| PASSED
rgb_lagged_sum| 20| 1000000| 100|0.16448477| PASSED
rgb_lagged_sum| 21| 1000000| 100|0.46808427| PASSED
rgb_lagged_sum| 22| 1000000| 100|0.91785129| PASSED
rgb_lagged_sum| 23| 1000000| 100|0.31276912| PASSED
rgb_lagged_sum| 24| 1000000| 100|0.84447142| PASSED
rgb_lagged_sum| 25| 1000000| 100|0.14697633| PASSED
rgb_lagged_sum| 26| 1000000| 100|0.10487197| PASSED
rgb_lagged_sum| 27| 1000000| 100|0.58438343| PASSED
rgb_lagged_sum| 28| 1000000| 100|0.59350542| PASSED
rgb_lagged_sum| 29| 1000000| 100|0.74575590| PASSED
rgb_lagged_sum| 30| 1000000| 100|0.73822689| PASSED
rgb_lagged_sum| 31| 1000000| 100|0.77342179| PASSED
rgb_lagged_sum| 32| 1000000| 100|0.70643865| PASSED
rgb_kstest_test| 0| 10000| 1000|0.05111680| PASSED
dab_bytedistrib| 0| 51200000| 1|0.92709090| PASSED
dab_dct| 256| 50000| 1|0.89417035| PASSED
Preparing to run test 207. ntuple = 0
dab_filltree| 32| 15000000| 1|0.22596727| PASSED
dab_filltree| 32| 15000000| 1|0.95837561| PASSED
Preparing to run test 208. ntuple = 0
dab_filltree2| 0| 5000000| 1|0.83006970| PASSED
dab_filltree2| 1| 5000000| 1|0.48202773| PASSED
Preparing to run test 209. ntuple = 0
dab_monobit2| 12| 65000000| 1|0.69239362| PASSED
Anche questo test superato!
Qui si trova una comparativa di var RNG.
Conclusioni
Dai risultati dei test sembra che l'OneRNG sia un'ottima fonte di dati casuali. Ricordando poi che su Gnu/Linux i dati generati verrebbero dati in pasto a /dev/random
e non usati direttamente posso tranquillamente sostenere che l'OneRNG vale ogni centesimo speso per acquistarlo.
In futuro, non appena la versione con la porta USB integrata sarà nuovamente disponibile, ne acquisterò sicuramente un altro.
Prima di concludere una curiosità: il modo corretto di pronunciare OneRNG è One Ring!
I creatori, infatti, sono neozelandesi e il nome fa riferimento all'unico anello de Il Signore degli anelli.