# 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.

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:-

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.

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.

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…

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.

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.

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 Permutati... ...snip... ...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...
...snip...
...0.015081
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
136...
...snip...
...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 .