Getting Started
To get started quickly:
- Download the sample code and install it on an Arduino Uno.
- Download the Z1FFER
repository, and navigate to
<path to repo>/Scripts/Record Data
. In the terminal typepython record_data.py
. Answer the prompt asking you what serial port the Arduino is connected to (something like/dev/tty.usbmodem1411
on macOS). You should end up with a file calledrandom.dat
which will contain somewhat random data (for higher entropy see Conditioned Output).
Conditioned output
No hardware RNG is 100% random; even ones that have a theoretically truly random source, such as a radioactive element, rely on sensors that induce order in the device’s output. As a solution raw TRNG output is “conditioned” in order to create numbers of cryptographic quality. One way of doing this is to combine bytes using cipher block chaining (CBC) mixed with some encryption. The sample code below uses AES-CBC-MAC, which is recommended by NIST SP800-90B.
This Arduino code provides conditioned output. It combines several bytes using AES-CBC-MAC, and returns only the final byte (the MAC), which has higher entropy than the raw data.
Entropy output and health checks
Z1FFER 0.3.X has less randomness (0.87 bits of entropy per byte) than many RNGs, including earlier versions of Z1FFER (0.99 bits of entropy). However, in exchange, they are more reliable and more resistant to some kinds of attack. Also, they consistently output this amount of entropy, which makes for a good way of checking to see if the board is functioning properly. In an optimal setup, raw data would be streamed to a host machine that would check the stream's health and condition it. However, if you want cryptographic-quality numbers straight from Arduino, you can run the above conditioning sample code. Note that the extra computation slows the output down substantially. If you want speed, you should perform the conditioning on the host machine.
Troubleshooting
The Arduino code won't compile. The sample code here is optimized for Arduino
Uno. It uses pin registers to read data from the shield because they are substantially faster than
pinRead()
. If you are using an Arduino that is not based on AVR microcontrollers, such as the
Arduino Zero, the lower-level code will not compile. If you rewrite the code using pinRead()
send
it to me and I'll post it here.
The output isn't truly random. See my note above about conditioned output.