Quantum entropy source on a breadboard

As unequivocal proof of the ease with which you can build a high quality, cryptographic strength entropy source, here is one we built earlier on Granny’s wooden breadboard:-

1. The making.

A wooden breadboard implementation of the simplest quantum entropy source based on a Chekhov circuit.

The breadboarded entropy source.

Schematic of the simplest quantum entropy source based on a Chekhov circuit.


It is a Chekhov circuit, which is the simplest possible entropy generating circuit. So simple in fact that we built it on a wooden board (literally a breadboard). And even used real steel nails. The circuit is named after Anton Chekhov, who said “Only entropy comes easy”. Such wisdom! Essentially, it’s a common BZX 27 volt Zener diode plus 680 kΩ current limiting resistor thus:-

Simplest possible entropy source schematic based on a Zener diode, resistor and battery. A Chekhov Circuit.

Simplest possible entropy generating circuit, called a Chekhov circuit.

The thermo-nuclear shielding (box made of cryptographic plastic) is necessary to protect the Zener from all light as the junction is within a transparent glass encapsulation. Incident light disrupts the electron avalanche effect and reduces the entropy signal. Nominal reverse current = 18uA as the battery is actually ~39V. 36V is only the nominal value of 4 no. 9V batteries. Frankly, the diode current is somewhat higher, probably nearer 30uA as we use a direct x1 BNC cable. That’s about 110 trillion electrons tumbling through the junction every second. The combined 1MΩ scope impedance and limiting resistor parallel out at about 404 kΩ. This resistance acts with the junction capacitance to marginally distort the expected characteristic log normal signal distribution.

The Zener diode at the heart of our quantum entropy generator on a wooden breadboard.

The 27V Zener diode itself.

It’s a true quantum entropy source for the reasons explained previously in relation to the Avalanche effect within Zener diodes. It really doesn’t have to involve lasers or vacuum point energy to be quantum based. Although stale bread crumbs, semi-dried tomato juice and rotting pieces of salami can have a deleterious effect on circuit impedances and thus entropy rates. Lunches aside, our Chekhov circuit produces a mean unamplified entropy signal of 1.93Vpp under standard sampling.

2. The running.

A mean (un-amplified) entropy signal of 1.93Vpp from the simplest quantum entropy source based on a Chekhov circuit.

A mean (un-amplified) entropy signal of 1.93Vpp.

The above ~1.9Vpp signal is readily manipulated by keen individuals, and guaranteed to be caused by the Avalanche effect rather than some unspecified consequence of huge amplifier gain/power supply noise. And readily extracted from.

NIST and at least one popular cryptography forum seem to rigorously promote the diametrically opposite view, repeating over and over the futility of DIY constructions. Why? The proof is on the chopping board. Just turn it on…

On/Off switch for a breadboarded quantum entropy source based on a Chekhov circuit.

Quantum control.

Then stick the entire thing up an Arduino. Sampling was as: = 127 + analogRead(portNo) - analogRead(portNo) to only use the lower 8 bits of the Arduino’s ADC. This decreases sample storage space, and increases the entropy transfer rate off the Arduino. Bear in mind that this is only an entropy source, not a complete TRNG. Thus we are not looking for uniform output distributions at this stage. We’ll take what we can get. And what we got is available in the ‘Related files’ section below, including raw samples from an oscilloscope and an Arduino Uno, and some Python3 categorisation and utility scripts.

One of the fundamental paradigms of this site is that you don’t trust no one, and certainly not an obscure REALLYREALLYRANDOM.COM. The raw data is supplied for you to analyse yourselves, and to reach your own independent conclusions. But don’t believe the data either. Build this source, gather your own data and see what you think. Simply treat our data, code and formulae as hypothetical possibilities of what might be in a utopian cryptographic future. Like serving suggestions on tinned food.

3. The analysis.

First impression: Just as in US Supreme Court Justice Stewart’s definition, The Casablanca Test: “I know it [obscenity/pornography] when I see it,” we can tell that the sampled signal contains a good rate of entropy by seeing a visual representation. The following 400 pixel x 400 pixel image is a direct 1:1 greyscale view on the sampled data bytes. No recognizable patterns exist at either the micro or macro scales.

8 bit visual representation (and x16 zoom) of Arduino sampled entropy.

8 bit visual representation (and x16 zoom) of Arduino sampling.

Waveform and probability distribution of samples from a Zener diode entropy source.

Waveform and probability distribution of Arduino samples.

If you view the signal in the probability domain as above, we see a close similarity to the signal from the Zenerglass, a device built and sampled on similar principles. We characterize the histogram as a shifted bathtub distribution, typical of double samples with an offset. Sample autocorrelation is less than 0.0035, suggesting that they may be IID. We confirm this with an IID permutation test at the NIST standard 0.001 level. The maximum shuffled compression ratio was 1.00044. The pairwise sampling has proven sufficient to nullify any correlations.

Autocorrelation of samples from a Zener diode entropy source.

Autocorrelation of Arduino samples.

IID test of samples from a Zener diode entropy source.

IID test of Arduino samples.

The above permuted compressions test is our proprietary IID test, which is safely passed. Our tests are likewise confirmed by the following SP 800-90B IID test output:-

$ ./ea_iid -v -i -a /tmp/breadboard.bin 8
Opening file: '/tmp/breadboard.bin'
Loaded 1200000 samples of 256 distinct 8-bit-wide symbols
Number of Binary samples: 9600000
Calculating baseline statistics...
  Raw Mean: 126.980571
  Median: 127.000000
  Binary: false

Literal MCV Estimate: mode = 21451, p-hat = 0.017875833333333334, p_u = 0.018187394258475383
Bitstring MCV Estimate: mode = 4806186, p-hat = 0.50064437500000003, p_u = 0.50106004734293053
H_original: 5.780917
H_bitstring: 0.996945
min(H_original, 8 X H_bitstring): 5.780917

Chi square independence
  score = 25573.684818
  degrees of freedom = 25490
  p-value = 0.354506

Chi square goodness of fit
  score = 2168.182062
  degrees of freedom = 2088
  p-value = 0.108316

** Passed chi square tests

LiteralLongest Repeated Substring results
  P_col: 0.00945183
  Length of LRS: 6
  Pr(X >= 1): 0.40151
** Passed length of longest repeated substring test

Beginning initial tests...

Initial test results
              excursion: 45579.9
     numDirectionalRuns: 799801
     lenDirectionalRuns: 9
  numIncreasesDecreases: 605614
          numRunsMedian: 600013
          lenRunsMedian: 19
           avgCollision: 12.7425
           maxCollision: 50
         periodicity(1): 11411
         periodicity(2): 11493
         periodicity(8): 11263
        periodicity(16): 11495
        periodicity(32): 11265
          covariance(1): 1.93506e+10
          covariance(2): 1.93509e+10
          covariance(8): 1.9349e+10
         covariance(16): 1.93477e+10
         covariance(32): 1.935e+10
            compression: 1.13442e+06

Beginning permutation tests... these may take some time
Permutation Test (core 02): 0):  tests passed0 tests passed
Permutation Test (core 5): 0 tests passed
1): 0 tests passed

4): 0 tests passed
Permutation Test (core 3): 0 tests passed
Permutation Test (core 2): 0 tests passed
Permutation Test (core 5): 0 tests passed
Permutation Test (core 1): 0 tests passed
Permutation Test (core 0): 0 tests passed
Permutation Test (core 4): 0 tests passed
Permutation Test (core 3): 0 tests passed
Permutation Test (core 2): 0 tests passed
Permutation Test (core 5): 0 tests passed
Permutation Test (core 1): 0 tests passed
Permutation Test (core 0): 0 tests passed
Permutation Test (core 4): 0 tests passed
Permutation Test (core 3): 1 tests passed
                              ...ts passed
Permutation Test (core 0): 18 tests passed
Permutation Test (core 3): 18 tests passed
Permutation Test (core 4): 18 tests passed
Permutation Test (core 2): 18 tests passed
Permutation Test (core 5): 18 tests passed
Permutation Test (core 1): 18 tests passed
Permutation Test (core 0): 18 tests passed
Permutation Test (core 3): 18 tests passed

                statistic  C[i][0]  C[i][1]  C[i][2]
                excursion       6       0      45
       numDirectionalRuns      18       1       5
       lenDirectionalRuns       2       4       6
    numIncreasesDecreases       7       0       6
            numRunsMedian       6       0      12
            lenRunsMedian      12       5       1
             avgCollision       6       0       7
             maxCollision       4       2       8
           periodicity(1)       6       0      32
           periodicity(2)       6       0      67
           periodicity(8)      14       0       6
          periodicity(16)       6       0      55
          periodicity(32)       7       0       6
            covariance(1)       6       0     127
            covariance(2)       6       0      69
            covariance(8)       6       0      16
           covariance(16)       8       0       6
           covariance(32)       6       0      16
              compression       6       0     540
(* denotes failed test)

** Passed IID permutation tests

We can then simply move onto an ent test to find Pmax and thus the min.entropy ($H_\infty$) rate:-

$ ent -c /tmp/samples-10ksa.bin
Value Char Occurrences Fraction
  0                4   0.000003
  1                8   0.000007
  2                7   0.000006
  3                6   0.000005
  4               15   0.000013
  5               13   0.000011
  6               18   0.000015
  7               15   0.000013
  8               23   0.000019
  9               24   0.000020
 10               19   0.000016
 11               32   0.000027
 12               30   0.000025
 13               35   0.000029
 14               38...
122   z        18950   0.015792
123   {        19824   0.016520
124   |        20431   0.017026
125   }        21012   0.017510
126   ~        21168   0.017640
127            21370   0.017808
128            21451   0.017876     *****    Pmax(Px = i)
129            21357   0.017798
130            20407   0.017006
131            19810   0.016508
132            18839   0.015699
133            18112   0.015093
134            16965   0.014138
135            16346   0.013622
               ...21   0.000017
247   �           18   0.000015
248   �            5   0.000004
249   �           11   0.000009
250   �           14   0.000012
251   �            8   0.000007
252   �            9   0.000008
253   �            6   0.000005
254   �            4   0.000003
255   �           12   0.000010

Total:       1200000   1.000000

Entropy = 7.046544 bits per byte.

A cmix compressive entropy measurement produces a cross entropy of 7.056 bits/byte (double sample), which is within 0.13% of the above theoretical Shannon entropy under an IID assumption. Based on a Pmax of 0.017876 and confirmation of the data as IID, we can say that native $H_\infty$ of this breadboard source is 5.8 bits/byte (double sample). That’s an internal Arduino entropy generation rate of ~26kbps (114,692us for 512 double samples) under standard sampling.

4. The conclusion.

Randomness extraction and off loading from the Arduino board will of course lower this figure considerably. So what can we do with this..?

Cryptographic objective Rate
Our bang for buck 18.9 bps/g
We create a single 256 bit key/IV < 0.1s
We rotate 256 bit keys 25/s
We fill 100 larger sized Tweets 35s
We create a 1MB one time pad 20min.
Speed of Fourmilab’s HotBits 800bps
Speed of NIST’s Randomness Beacon 8.5bps
Speed of Arduino Entropy Library 64bps

For the above comparisons table, we have assumed an $n \over m$ relationship of 2 across a generic $\text{Ext}: \{0,1\}^n \to \{0,1\}^m$ randomness extractor, followed by a further factor of safety of 2. Final on-board cryptographic TRNG rate = 6,500bps under standard sampling.

All that’s necessary is a Zener diode, resistor, batteries and a working hammer. Not too shoddy .