Getting Random with REST

Public service announcement: This is going to be a “techie” post.

If interfacing with hardware random number generators via REST API is not your thing, you might want to pass on this one.

Over the years, I’ve built a number of devices that investigate the influence of intention on random events. These will undoubtedly be topics for future posts, but suffice to say, all required the use of a hardware based random number generator.

I’ve tried several different hardware RNGs, and have even built my own, but the two I like the best are the OneRNG and TrueRNG devices pictured to the right.

OneRNG Hardware Random Number Generator
TrueRNG Hardware Random Number Generator

They both work well with linux and SBCs like a RaspberryPi or BeagleBone. They also both use an avalanche effect from a diode circuit to generate the random noise. The data fills the entropy pool of the operating system and can be accessed (in linux) via /dev/random or /dev/urandom.

I haven’t done any analysis to see which has a higher bit rate, but both are sufficient for my purposes. I would give OneRNG a slight edge in that the hardware and software are open and fully published. Also, I find the onboard LED highly convenient as it can be used to test whether it’s operating properly. Otherwise, there’s no easy way to verify you’re getting output from the hardware versus the OS pseudo-random number generator.

RNG server using OneRNG in the Enigmatic lab

Both have thorough documentation on how to set up on a linux based system, but where I found info scarce is how to query the device to get a random number in the format that I wanted. Output is a stream of binary data by default, but for my purposes I need string representations of integers and floats.

After much Googling, I put together a solid setup for returning an integer within a set range (like between 1-100) and a float between 0 and 1. I wanted to share as a time saver for anyone interested.

Here’s the command I run from the linux CLI to get an integer within a range of 100 and 1000:

echo $(( 100+(`od -An -N2 -i /dev/random` )%(1000-100+1)))
decker@sonoya:~/scripts# echo $(( 100+(`od -An -N2 -i /dev/random` )%(1000-100+1)))
312

To change the range, substitute the two ‘100’ occurrences with a value for the low end and substitute ‘1000’ for the high end.

Here’s the code to get a single float value between 0 and 1:

(printf '%.19f\n' "0x0.$(od -N 8 -An -tx1 /dev/random | tr -d ' ')")
decker@sonoya:~/scripts# (printf '%.19f\n' "0x0.$(od -N 8 -An -tx1 /dev/random | tr -d ' ')")
0.6726632392320606169

Both these commands are useful in a quick linux shell script, but I also needed a more flexible way to get random numbers from different programing languages and from remote hosts.

Python Flask to the rescue! Flask is useful to setup quick python server with REST endpoints, perfect for my use case.

Before I share my code, a warning or two:

First, I’m not a programmer. I hack together quick scripts to get what I need done, there are probably (definitely) more elegant ways to accomplish this. Second, I’m running my flask server as root and using python to call a shell script that executes OS commands. Don’t do this in a production or public facing environment!

You can find the code at my github repository below. You will need to install flask prior to running.

https://github.com/deckerEnigmatic/rngRESTServer/tree/master

When you run the script you should see output like the below. This will create a server running on the local machine using TCP port 5000.

root@sonoya:~/scripts/rngrestserver# ./rngrestserver.py
 * Serving Flask app "rngrestserver" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

I have this running on a Raspberry Pi in my lab and use it to serve random numbers to remote hosts. A remote client can request a random number by hitting the correct REST endpoint with the appropriate parameters. Here’s the usage below:

Endpoint to request a random number within a range:

http://192.168.1.133:5000/rangeInt/1/100

Output is JSON key value pair. In this case a single integer between 1 and 100.

http://192.168.1.133:5000/rangeFloat

Output is a JSON key value pair returning a float.

If you work with hardware based RNGs I hope you found this post helpful. I spent some “quality” time learning cryptic shell commands to get the output in the format I needed. If you use any of my code, reach out and let me know!