Introduction: A Raspberry Pi-based Truly Random Number Generator
Random numbers are essential for all kinds of things, especially cryptography. Computers, however, can only produce pseudorandom numbers, which can be "guessed" by using sophisticated software. Truly random numbers are hard to come by. Luckily, with a few wires and a Ras Pi, one can create a lot of random numbers very quickly.
For this project you will need:
1x Raspberry Pi
3x Breadboard wires
And, for the optional LED output section:
1x LED
1x current-limiting resistor (for the LED)
3x Breadboard wires
For this project you will need:
1x Raspberry Pi
3x Breadboard wires
And, for the optional LED output section:
1x LED
1x current-limiting resistor (for the LED)
3x Breadboard wires
Step 1: Wiring
This is the easiest wiring project you've ever done.
For the RNG inputs, connect breadboard wires to GPIO 4, 17, and 22. If that's all you want, you're done. skip to the coding.
For the LED output, connect a resistor and an LED in series (with the resistor on the positive pin of the LED), then connect the Pi's ground to the ground rail on the breadboard. Connect the other end of the LED to ground and the other end of the resistor to GPIO 25.
For the RNG inputs, connect breadboard wires to GPIO 4, 17, and 22. If that's all you want, you're done. skip to the coding.
For the LED output, connect a resistor and an LED in series (with the resistor on the positive pin of the LED), then connect the Pi's ground to the ground rail on the breadboard. Connect the other end of the LED to ground and the other end of the resistor to GPIO 25.
Step 2: Code
This code has 6 configurable parameters: Length of the random numbers to output (in bits), the three input pins, the output pin, and the Time to Sleep (tts). A shorter TTS speeds up the generator but reduces entropy. TTS defaults to 0.01 seconds.
#!/usr/bin/env python
#Uses floating inputs on GPIO4, GPIO17, and GPIO22 to generate truly random numbers
#Outputs to GPIO 25 when a new number is done and sends the number to STDOUT
import RPi.GPIO as GPIO
import sys
from time import sleep
GPIO.setmode(GPIO.BCM)
def getRBit(pin1, pin2, pin3, tts): #gets a random set of bits, XORs them, and outputs one random bit
bit1 = 0
bit2 = 0
bit3 = 0
bitv = 0
GPIO.setup(pin1, GPIO.IN)
GPIO.setup(pin2, GPIO.IN)
GPIO.setup(pin3, GPIO.IN)
sleep(tts) #Sleep so the CPU can mess around and change the EMF environment
bit1 = GPIO.input(pin1)
if bit1:
bit1 = 1
else:
bit1 = 0
sleep(tts) #Sleep so the CPU can mess around and change the EMF environment
bit2 = GPIO.input(pin2)
if bit2:
bit2 = 1
else:
bit2 = 0
sleep(tts) #Sleep so the CPU can mess around and change the EMF environment
bit3 = GPIO.input(pin3)
if bit3:
bit3 = 1
else:
bit3 = 0
#Now do some XOR logic
bitv = bit1 ^ bit2
out = bitv ^ bit3
return out
def getRInt(x, pin1, pin2, pin3, pin4, tts=0.01): #get an x-bit number by looping through a string a bunch. Pin4 is LEDout.
GPIO.setup(pin4, GPIO.OUT)
binstr = "" #Set up to be converted to binary
rint = 0
rbit = 0
i = 0
for i in range (0, x-1):
i += 1
rbit = getRBit(pin1, pin2, pin3, tts)
binstr = binstr + str(rbit)
#print(binstr) # For debug purposes
rint = int(binstr, 2)
GPIO.output(pin4, True)
sleep(0.2)
GPIO.output(pin4, False)
return rint
while True:
print(getRInt(64, 4, 17, 22, 25, 0.01)) #bits, in1, in2, in3, out, tts
#!/usr/bin/env python
#Uses floating inputs on GPIO4, GPIO17, and GPIO22 to generate truly random numbers
#Outputs to GPIO 25 when a new number is done and sends the number to STDOUT
import RPi.GPIO as GPIO
import sys
from time import sleep
GPIO.setmode(GPIO.BCM)
def getRBit(pin1, pin2, pin3, tts): #gets a random set of bits, XORs them, and outputs one random bit
bit1 = 0
bit2 = 0
bit3 = 0
bitv = 0
GPIO.setup(pin1, GPIO.IN)
GPIO.setup(pin2, GPIO.IN)
GPIO.setup(pin3, GPIO.IN)
sleep(tts) #Sleep so the CPU can mess around and change the EMF environment
bit1 = GPIO.input(pin1)
if bit1:
bit1 = 1
else:
bit1 = 0
sleep(tts) #Sleep so the CPU can mess around and change the EMF environment
bit2 = GPIO.input(pin2)
if bit2:
bit2 = 1
else:
bit2 = 0
sleep(tts) #Sleep so the CPU can mess around and change the EMF environment
bit3 = GPIO.input(pin3)
if bit3:
bit3 = 1
else:
bit3 = 0
#Now do some XOR logic
bitv = bit1 ^ bit2
out = bitv ^ bit3
return out
def getRInt(x, pin1, pin2, pin3, pin4, tts=0.01): #get an x-bit number by looping through a string a bunch. Pin4 is LEDout.
GPIO.setup(pin4, GPIO.OUT)
binstr = "" #Set up to be converted to binary
rint = 0
rbit = 0
i = 0
for i in range (0, x-1):
i += 1
rbit = getRBit(pin1, pin2, pin3, tts)
binstr = binstr + str(rbit)
#print(binstr) # For debug purposes
rint = int(binstr, 2)
GPIO.output(pin4, True)
sleep(0.2)
GPIO.output(pin4, False)
return rint
while True:
print(getRInt(64, 4, 17, 22, 25, 0.01)) #bits, in1, in2, in3, out, tts
Step 3: Uses and Notes
I suggest using this generator for encryption as the numbers that it generates are highly entropic and pretty much unguessable, barring a bruteforce attack. Using these numbers to seed, for example, the PHP PRNG is a great way to make its output unguessable.
A small note: it may take a VERY long time (~ several minutes) for the generator to make numbers with lots of bits (above 1k). Instead of doing that, I suggest seeding a pseudorandom generator with this truly random output. It's still unguessable.
A small note: it may take a VERY long time (~ several minutes) for the generator to make numbers with lots of bits (above 1k). Instead of doing that, I suggest seeding a pseudorandom generator with this truly random output. It's still unguessable.