Skip to content

A True Random Number Generator in a Pico

Convert a Pico device into a True Random Number Generator
  • Get true random numbers
  • Generate secret and private keys with true random numbers
  • Use it to feed your entropy sources
  • Add to your OS a module
Features

Generate uncorrelated random numbers

Use it as extern entropy source

Add a kernel module to feed urandom

Perform analysis

Open source: hardware and software

For an open audit by all the community. Hosted at Github.
It runs on any Raspberry Pico.
What is Pico Keys?

Pico Keys is a set of firmwares ready to run on any Raspberry Pico controller with the RP2040 chip. Each firmware (Pico HSM, Pico Fido and Pico OpenPGP) follows separate standardized specifications with different purposes but with a single common premise: having a personal key device.

How to run the firmware?

Just download the firmware for your board and load it. It will convert your Pico device into a personal key. Just plug it in your USB and it will be identified by your OS automatically.

Which firmware do I need?

If you need to generate and store dozens of keys, then go for Pico HSM. If you are looking for a personal token (Fido2) for secure logging, then go for Pico Fido. If you need to interface with PGP keys for secure e-mail, then go for Pico OpenPGP.

Do you provide the hardware?

No. You can acquire multiple boards mounting a RP2040 chip from different vendors. Our firmwares are ready to run on any board.

Start making your keys more secure

Never is too late to start to keep your keys safer. It is time to start

START TODAY

Download

Random Distribution

Ideally, a true random number generator must produce uniformly distributed random bytes, between 0 and 255, with a probability of 1/256~0.0039

Chi Square Test

These figures are the distribution of chi square tests and excess percentages. Ideally, the distribution of chi square tests must follow a chi square distribution with mean at 255. Excess percentage distribution must follow a uniform distribution.

Ent
$ ent sample.rng
Entropy = 7.999999 bits per byte.

Optimum compression would reduce the size
of this 1073741824 byte file by 0 percent.

Chi square distribution for 1073741824 samples is 839.56, and randomly
would exceed this value less than 0.01 percent of the times.

Arithmetic mean value of data bytes is 127.4993 (127.5 = random).
Monte Carlo value for Pi is 3.141625006 (error 0.00 percent).
Serial correlation coefficient is 0.000006 (totally uncorrelated = 0.0).
  • Entropy test should produce an ideal result of 8, as each byte has 8 bits.
  • Optimum compression test should produce an ideal result of 0 percent.
  • Chi square should be called with different sample tests and produce a chi square distribution.
  • Arithmetic mean should produce an ideal result of 127.5.
  • Pi test should be equal to pi number.
  • Serial correlation should be 0.

These results show that pico-rng is pretty random.

FIPS 140-2
$ cat sample.rng | rngtest
rngtest 2-unofficial-mt.14
Copyright (c) 2004 by Henrique de Moraes Holschuh
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

rngtest: starting FIPS tests...
rngtest: entropy source exhausted!
rngtest: bits received from input: 8589934592
rngtest: FIPS 140-2 successes: 429141
rngtest: FIPS 140-2 failures: 355
rngtest: FIPS 140-2(2001-10-10) Monobit: 42
rngtest: FIPS 140-2(2001-10-10) Poker: 41
rngtest: FIPS 140-2(2001-10-10) Runs: 138
rngtest: FIPS 140-2(2001-10-10) Long run: 136
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=9661835.749; avg=23078154805.083; max=0.000)bits/s
rngtest: FIPS tests speed: (min=5.699; avg=239.429; max=261.281)Mibits/s
rngtest: Program run time: 34612429 microseconds

In these results, we have a total number of trials 429496 (429141+355).

  • The acceptable result of Monobit test is 1 failed trial for every 9662 trials. For 429496 trials, the number of failed trials should be less than 429496/9662=44.45.
  • The acceptable result of Poker test is 1 failed trial for every 10078 trials. For 429496 trials, the number of failed trials should be less than 42.62.
SP800-90B
$ ./ea-iid sample.rng
Calculating baseline statistics...
H_original: 7.995587
H_bitstring: 0.999863
min(H_original, 8 X H_bitstring): 7.995587
** Passed chi square tests

** Passed length of longest repeated substring test

** Passed IID permutation tests

SP800-90b is the superseded version of FIPS 140-2 (rngtest). Can be obtained from here https://github.com/usnistgov/SP800-90B_EntropyAssessment.

Diehard
$ dieharder -a -g 201 -k 2 -Y 1 -m 2 -f sample.rng
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |           filename             |rands/second|
 file_input_raw|                      batch1.rng|  3.57e+07  |
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     200|0.17739498|  PASSED
      diehard_operm5|   0|   1000000|     200|0.97387049|  PASSED
# The file file_input_raw was rewound 1 times
  diehard_rank_32x32|   0|     40000|     200|0.37394022|  PASSED
# The file file_input_raw was rewound 2 times
    diehard_rank_6x8|   0|    100000|     200|0.09038266|  PASSED
# The file file_input_raw was rewound 2 times
   diehard_bitstream|   0|   2097152|     200|0.71785604|  PASSED
# The file file_input_raw was rewound 4 times
        diehard_opso|   0|   2097152|     200|0.37146068|  PASSED
# The file file_input_raw was rewound 5 times
        diehard_oqso|   0|   2097152|     200|0.35763562|  PASSED
# The file file_input_raw was rewound 5 times
         diehard_dna|   0|   2097152|     200|0.01889729|  PASSED
# The file file_input_raw was rewound 5 times
diehard_count_1s_str|   0|    256000|     200|0.63258197|  PASSED
# The file file_input_raw was rewound 6 times
diehard_count_1s_byt|   0|    256000|     200|0.65359815|  PASSED
# The file file_input_raw was rewound 6 times
 diehard_parking_lot|   0|     12000|     200|0.83176205|  PASSED
# The file file_input_raw was rewound 6 times
    diehard_2dsphere|   2|      8000|     200|0.64543002|  PASSED
# The file file_input_raw was rewound 6 times
    diehard_3dsphere|   3|      4000|     200|0.01258942|  PASSED
# The file file_input_raw was rewound 8 times
     diehard_squeeze|   0|    100000|     200|0.67578527|  PASSED
# The file file_input_raw was rewound 8 times
        diehard_sums|   0|       100|     200|0.23981668|  PASSED
# The file file_input_raw was rewound 8 times
        diehard_runs|   0|    100000|     200|0.77427455|  PASSED
        diehard_runs|   0|    100000|     200|0.08390099|  PASSED
# The file file_input_raw was rewound 9 times
       diehard_craps|   0|    200000|     200|0.59348655|  PASSED
       diehard_craps|   0|    200000|     200|0.23828837|  PASSED
# The file file_input_raw was rewound 24 times
 marsaglia_tsang_gcd|   0|  10000000|     200|0.15517856|  PASSED
 marsaglia_tsang_gcd|   0|  10000000|     200|0.00447239|   WEAK
# The file file_input_raw was rewound 31 times
 marsaglia_tsang_gcd|   0|  10000000|     300|0.02554040|  PASSED
 marsaglia_tsang_gcd|   0|  10000000|     300|0.00100578|   WEAK
# The file file_input_raw was rewound 39 times
 marsaglia_tsang_gcd|   0|  10000000|     400|0.00299305|   WEAK
 marsaglia_tsang_gcd|   0|  10000000|     400|0.00008767|   WEAK
# The file file_input_raw was rewound 46 times
 marsaglia_tsang_gcd|   0|  10000000|     500|0.00201489|   WEAK
 marsaglia_tsang_gcd|   0|  10000000|     500|0.00004067|   WEAK
# The file file_input_raw was rewound 54 times
 marsaglia_tsang_gcd|   0|  10000000|     600|0.00028460|   WEAK
 marsaglia_tsang_gcd|   0|  10000000|     600|0.00000323|   WEAK
# The file file_input_raw was rewound 61 times
 marsaglia_tsang_gcd|   0|  10000000|     700|0.00004334|   WEAK
 marsaglia_tsang_gcd|   0|  10000000|     700|0.00000055|  FAILED
# The file file_input_raw was rewound 61 times
         sts_monobit|   1|    100000|     200|0.11868265|  PASSED
# The file file_input_raw was rewound 61 times
            sts_runs|   2|    100000|     200|0.55674493|  PASSED
# The file file_input_raw was rewound 61 times
          sts_serial|   1|    100000|     200|0.99669244|   WEAK
          sts_serial|   2|    100000|     200|0.46102720|  PASSED
          sts_serial|   3|    100000|     200|0.44562932|  PASSED
          sts_serial|   3|    100000|     200|0.84230024|  PASSED
          sts_serial|   4|    100000|     200|0.98548763|  PASSED
          sts_serial|   4|    100000|     200|0.57495245|  PASSED
          sts_serial|   5|    100000|     200|0.77085975|  PASSED
          sts_serial|   5|    100000|     200|0.56476358|  PASSED
          sts_serial|   6|    100000|     200|0.45650075|  PASSED
          sts_serial|   6|    100000|     200|0.05289356|  PASSED
          sts_serial|   7|    100000|     200|0.27201114|  PASSED
          sts_serial|   7|    100000|     200|0.76400695|  PASSED
          sts_serial|   8|    100000|     200|0.62348338|  PASSED
          sts_serial|   8|    100000|     200|0.57277685|  PASSED
          sts_serial|   9|    100000|     200|0.38071419|  PASSED
          sts_serial|   9|    100000|     200|0.07625829|  PASSED
          sts_serial|  10|    100000|     200|0.47989859|  PASSED
          sts_serial|  10|    100000|     200|0.11112817|  PASSED
          sts_serial|  11|    100000|     200|0.92833035|  PASSED
          sts_serial|  11|    100000|     200|0.69376394|  PASSED
          sts_serial|  12|    100000|     200|0.84887524|  PASSED
          sts_serial|  12|    100000|     200|0.97617601|  PASSED
          sts_serial|  13|    100000|     200|0.65397230|  PASSED
          sts_serial|  13|    100000|     200|0.56436970|  PASSED
          sts_serial|  14|    100000|     200|0.51868029|  PASSED
          sts_serial|  14|    100000|     200|0.92953669|  PASSED
          sts_serial|  15|    100000|     200|0.85158213|  PASSED
          sts_serial|  15|    100000|     200|0.93993540|  PASSED
          sts_serial|  16|    100000|     200|0.35998600|  PASSED
          sts_serial|  16|    100000|     200|0.20807684|  PASSED
# The file file_input_raw was rewound 61 times
          sts_serial|   1|    100000|     300|0.19573096|  PASSED
          sts_serial|   2|    100000|     300|0.85406665|  PASSED
          sts_serial|   3|    100000|     300|0.06590447|  PASSED
          sts_serial|   3|    100000|     300|0.45707402|  PASSED
          sts_serial|   4|    100000|     300|0.44442263|  PASSED
          sts_serial|   4|    100000|     300|0.52775404|  PASSED
          sts_serial|   5|    100000|     300|0.40217529|  PASSED
          sts_serial|   5|    100000|     300|0.06010705|  PASSED
          sts_serial|   6|    100000|     300|0.08040223|  PASSED
          sts_serial|   6|    100000|     300|0.00547743|  PASSED
          sts_serial|   7|    100000|     300|0.24575210|  PASSED
          sts_serial|   7|    100000|     300|0.28977315|  PASSED
          sts_serial|   8|    100000|     300|0.36868885|  PASSED
          sts_serial|   8|    100000|     300|0.49522777|  PASSED
          sts_serial|   9|    100000|     300|0.40957917|  PASSED
          sts_serial|   9|    100000|     300|0.09110499|  PASSED
          sts_serial|  10|    100000|     300|0.77559781|  PASSED
          sts_serial|  10|    100000|     300|0.19716611|  PASSED
          sts_serial|  11|    100000|     300|0.80459107|  PASSED
          sts_serial|  11|    100000|     300|0.44572782|  PASSED
          sts_serial|  12|    100000|     300|0.20184427|  PASSED
          sts_serial|  12|    100000|     300|0.60780140|  PASSED
          sts_serial|  13|    100000|     300|0.76273905|  PASSED
          sts_serial|  13|    100000|     300|0.60473178|  PASSED
          sts_serial|  14|    100000|     300|0.24687487|  PASSED
          sts_serial|  14|    100000|     300|0.66722555|  PASSED
          sts_serial|  15|    100000|     300|0.85162176|  PASSED
          sts_serial|  15|    100000|     300|0.81632309|  PASSED
          sts_serial|  16|    100000|     300|0.72398028|  PASSED
          sts_serial|  16|    100000|     300|0.26061444|  PASSED
# The file file_input_raw was rewound 61 times
         rgb_bitdist|   1|    100000|     200|0.80303319|  PASSED
# The file file_input_raw was rewound 62 times
         rgb_bitdist|   2|    100000|     200|0.44511426|  PASSED
# The file file_input_raw was rewound 62 times
         rgb_bitdist|   3|    100000|     200|0.15306427|  PASSED
# The file file_input_raw was rewound 63 times
         rgb_bitdist|   4|    100000|     200|0.52424083|  PASSED
# The file file_input_raw was rewound 64 times
         rgb_bitdist|   5|    100000|     200|0.62602197|  PASSED
# The file file_input_raw was rewound 64 times
         rgb_bitdist|   6|    100000|     200|0.27582205|  PASSED
# The file file_input_raw was rewound 65 times
         rgb_bitdist|   7|    100000|     200|0.83928387|  PASSED
# The file file_input_raw was rewound 67 times
         rgb_bitdist|   8|    100000|     200|0.78920891|  PASSED
# The file file_input_raw was rewound 68 times
         rgb_bitdist|   9|    100000|     200|0.10426661|  PASSED
# The file file_input_raw was rewound 69 times
         rgb_bitdist|  10|    100000|     200|0.56345552|  PASSED
# The file file_input_raw was rewound 71 times
         rgb_bitdist|  11|    100000|     200|0.67837353|  PASSED
# The file file_input_raw was rewound 73 times
         rgb_bitdist|  12|    100000|     200|0.77285406|  PASSED
# The file file_input_raw was rewound 73 times
rgb_minimum_distance|   2|     10000|    2000|0.99326519|  PASSED
# The file file_input_raw was rewound 73 times
rgb_minimum_distance|   3|     10000|    2000|0.89490386|  PASSED
# The file file_input_raw was rewound 74 times
rgb_minimum_distance|   4|     10000|    2000|0.63482997|  PASSED
# The file file_input_raw was rewound 74 times
rgb_minimum_distance|   5|     10000|    2000|0.04956198|  PASSED
# The file file_input_raw was rewound 74 times
    rgb_permutations|   2|    100000|     200|0.59389551|  PASSED
# The file file_input_raw was rewound 74 times
    rgb_permutations|   3|    100000|     200|0.84473217|  PASSED
# The file file_input_raw was rewound 75 times
    rgb_permutations|   4|    100000|     200|0.67098621|  PASSED
# The file file_input_raw was rewound 75 times
    rgb_permutations|   5|    100000|     200|0.71477222|  PASSED
# The file file_input_raw was rewound 76 times
      rgb_lagged_sum|   0|   1000000|     200|0.20844392|  PASSED
# The file file_input_raw was rewound 77 times
      rgb_lagged_sum|   1|   1000000|     200|0.52704060|  PASSED
# The file file_input_raw was rewound 79 times
      rgb_lagged_sum|   2|   1000000|     200|0.68631913|  PASSED
# The file file_input_raw was rewound 82 times
      rgb_lagged_sum|   3|   1000000|     200|0.04971017|  PASSED
# The file file_input_raw was rewound 86 times
      rgb_lagged_sum|   4|   1000000|     200|0.11342937|  PASSED
# The file file_input_raw was rewound 91 times
      rgb_lagged_sum|   5|   1000000|     200|0.08126696|  PASSED
# The file file_input_raw was rewound 96 times
      rgb_lagged_sum|   6|   1000000|     200|0.20866831|  PASSED
# The file file_input_raw was rewound 102 times
      rgb_lagged_sum|   7|   1000000|     200|0.52239049|  PASSED
# The file file_input_raw was rewound 109 times
      rgb_lagged_sum|   8|   1000000|     200|0.68232225|  PASSED
# The file file_input_raw was rewound 116 times
      rgb_lagged_sum|   9|   1000000|     200|0.13755031|  PASSED
# The file file_input_raw was rewound 124 times
      rgb_lagged_sum|  10|   1000000|     200|0.82473876|  PASSED
# The file file_input_raw was rewound 133 times
      rgb_lagged_sum|  11|   1000000|     200|0.10861154|  PASSED
# The file file_input_raw was rewound 143 times
      rgb_lagged_sum|  12|   1000000|     200|0.10432254|  PASSED
# The file file_input_raw was rewound 153 times
      rgb_lagged_sum|  13|   1000000|     200|0.18082599|  PASSED
# The file file_input_raw was rewound 164 times
      rgb_lagged_sum|  14|   1000000|     200|0.13220862|  PASSED
# The file file_input_raw was rewound 176 times
      rgb_lagged_sum|  15|   1000000|     200|0.08158678|  PASSED
# The file file_input_raw was rewound 189 times
      rgb_lagged_sum|  16|   1000000|     200|0.02760994|  PASSED
# The file file_input_raw was rewound 202 times
      rgb_lagged_sum|  17|   1000000|     200|0.14079614|  PASSED
# The file file_input_raw was rewound 217 times
      rgb_lagged_sum|  18|   1000000|     200|0.23268911|  PASSED
# The file file_input_raw was rewound 231 times
      rgb_lagged_sum|  19|   1000000|     200|0.50758360|  PASSED
# The file file_input_raw was rewound 247 times
      rgb_lagged_sum|  20|   1000000|     200|0.66798605|  PASSED
# The file file_input_raw was rewound 263 times
      rgb_lagged_sum|  21|   1000000|     200|0.13844382|  PASSED
# The file file_input_raw was rewound 281 times
      rgb_lagged_sum|  22|   1000000|     200|0.44084188|  PASSED
# The file file_input_raw was rewound 299 times
      rgb_lagged_sum|  23|   1000000|     200|0.90104158|  PASSED
# The file file_input_raw was rewound 317 times
      rgb_lagged_sum|  24|   1000000|     200|0.80347842|  PASSED
# The file file_input_raw was rewound 337 times
      rgb_lagged_sum|  25|   1000000|     200|0.07703809|  PASSED
# The file file_input_raw was rewound 357 times
      rgb_lagged_sum|  26|   1000000|     200|0.69854447|  PASSED
# The file file_input_raw was rewound 377 times
      rgb_lagged_sum|  27|   1000000|     200|0.26315861|  PASSED
# The file file_input_raw was rewound 399 times
      rgb_lagged_sum|  28|   1000000|     200|0.58852190|  PASSED
# The file file_input_raw was rewound 421 times
      rgb_lagged_sum|  29|   1000000|     200|0.42224280|  PASSED
# The file file_input_raw was rewound 445 times
      rgb_lagged_sum|  30|   1000000|     200|0.18274721|  PASSED
# The file file_input_raw was rewound 468 times
      rgb_lagged_sum|  31|   1000000|     200|0.18647377|  PASSED
# The file file_input_raw was rewound 493 times
      rgb_lagged_sum|  32|   1000000|     200|0.83130153|  PASSED
# The file file_input_raw was rewound 493 times
     rgb_kstest_test|   0|     10000|    2000|0.05507241|  PASSED
# The file file_input_raw was rewound 494 times
     dab_bytedistrib|   0|  51200000|       2|0.22222222|  PASSED
# The file file_input_raw was rewound 494 times
             dab_dct| 256|     50000|       2|0.98359769|  PASSED
Preparing to run test 207.  ntuple = 0
# The file file_input_raw was rewound 495 times
        dab_filltree|  32|  15000000|       2|0.75609132|  PASSED
        dab_filltree|  32|  15000000|       2|1.00000000|  FAILED
Preparing to run test 208.  ntuple = 0
# The file file_input_raw was rewound 495 times
       dab_filltree2|   0|   5000000|       2|1.00000000|  FAILED
       dab_filltree2|   1|   5000000|       2|1.00000000|  FAILED
Preparing to run test 209.  ntuple = 0
# The file file_input_raw was rewound 496 times
        dab_monobit2|  12|  65000000|       2|1.00000000|  FAILED