NeuG, a True Random Number Generator Implementation
NeuG is an implementatio of True Random Number Generator, based on the sampling noise of ADCs (A/D converters).
It runs on STM32F103, and it outputs random bits at the rate of more than 80 kB/sec (kB = 1000-byte). The interface is USB, and it behaves as a device of communication device class. In GNU/Linux, it runs as /dev/ttyACM0. Note that tty discipline settings should be “raw”.
It is a true RNG, with SHA-256 conditioning component.
The Git repository
Please visit The Git Repository of NeuG.
Structure of NeuG
Here is a figure of the circuit.
NeuG 1.0.3 Signal sources /|<---+--- [ Analog input Vref ] 16 | |<-+-|--- [ Analog input Temperature Sensor ] +---/-[ADC1] <==| | | | | | |<-+ | +-+ | \|<---+ | |<---+ | +----| | MUX CTL >--+ | | |<---+ | +-+ | /| | | 16 | |<------- [ Analog input 0 ] (pull up to Vdd) | +---/-[ADC2] <==| | | | |<------- [ Analog input 1 ] (pull up to Vdd) | \| | | | MUX CTL >--+ | +------------------+ <============ (*1) | / 32 | | Put 4 times to output 32-bit V [ CRC-32 filter ] | | Put 35 times to output 1120-bit +---------------------------------+ <====== (*2) | / 32 | V [ Entropy Buffer ] | +--------------+ | | | | | Conditioning | 1120 | | Component |<------------/------------+ | | +-----| Hash_df | | | by | | | SHA-256 | | | | 128 | | |<--/--+ | +--------------+ | | | +---------------------------+ | / 256 | v Random Number Output <========== (*3)
STM32F103 has two built-in A/D converters. NeuG uses A/D converters’ outputs as entropy sources. It is considered noise of quantization error, plus noise from power supply, etc.
We chose four analog input sources of: built-in voltage reference, temperature sensor and two analog inputs which are pull-up to Vdd.
Note that those signal sources are arbitrary and doesn’t matter. It is sampling itself, which gives us the entropy.
By a single sampling of two channels, we get 32-bit (not all 32-bit is valid, as a A/D converter resolution is 12-bit only). We take four sampling of combinations: (Vref, IN0), (Temp, IN1), (Vref, IN1), and (Temp, IN0). Those 32-bit * 4 is fed into CRC32 filter.
We use STM32F103’s CRC32 calculation unit as a kind of filter. We put output of A/D converters into CRC32 calculation unit, four times, to get 4-byte output. This is done because computation of SHA-256 is expensive if the sequence is too long.
Output of CRC32 filter is collected 35 times, and it becomes 1120-bit (32 * 35). This is the noise source bits.
We put this 1120-bit and half of previous output (128-bit) to conditioning component.
Conditioning Component is implemented by Hash_df function which is composed by SHA-256. Since the noise source is not “white”, signal is whiten by this Conditioning Component.
A Little History of NeuG
NeuG 1.0.3
Upgrade of Chopstx and Fraucheky.
NeuG 1.0.2
Upgrade of Chopstx. Firmware upgrade process change.
NeuG 1.0.1
Upgrade of Chopstx and Fraucheky. Optimization change.
NeuG 1.0
Chopstx’s bug fix for interrupt handling, introducing Fraucheky, the GNU GPL container.
NeuG 0.11
Use its own thread library, Chopstx. Improve the speed by tweaking health tests.
NeuG 0.06
Use its own USB stack (same as newer Gnuk).
NeuG 0.05
Improve speed of SHA256 hash function. As a whole, the speed of random number generation increases 2%.
NeuG 0.04
Improve speed when NeuG device is connected to full-speed hub. If it’s not full-size frame (== 64-byte), full-speed host submits a frame to device once per 1ms frame.
Run health tests for CRC-32 filtered output mode, too. It results slower generation speed for the mode though.
NeuG 0.03
In September 2012, Seth Schoen kindly informed me about the draft of NIST SP 800-90B.
It requires a device to have certified “conditioning component” to be full entropy source.
Thus, my journey to seek good “conditioning component” finished at this point. I decided to use hash_df function by SHA-256 for “conditioning component”.
I concentrate other points than conditioning component, such as use of ADC2, to get more performance.
NeuG 0.02
I was not satisfied about the performance of NeuG 0.01 and was not sure the quality of its output (although I tested the output of NeuG 0.01 by Dieharder 3.31 and NIST STS 2.1.1 extensively).
I played a bit with NeuG after release of Gnuk 1.0, and replaced NeuG’s component from CRC16 buffer to the WELL RNG structure in NeuG 0.02, as it looked better.
NeuG 0.01 and Gnuk 1.0
Then, I implemented NeuG 0.01 which uses CRC16 buffer to whiten noise source.
Gnuk (as of version 1.0) uses the routine of NeuG 0.01.
Initial Idea of NeuG
While developing Gnuk, I need good random number generator. Gnuk needs good random number generator for data encryption key to encrypt private keys (of RSA).
Early days, Gnuk didn’t have random number generator, and it required random bits to be stored into its flash ROM. It required its user to put output of /dev/random into there.
Then I got an idea (Initial Idea of TRNG implementation) while playing with STM32F103.