True Random PSK Generator on a Raspi

In my previous blogpost I talked about the true random number generator (TRNG) within the Raspberry Pi. Now I am using it for a small online pre-shared key (PSK) generator at (IPv6-only) that you can use e.g. for site-to-site VPNs. Here are some details how I am reading the binary random data and how I built this small website.

This project is just for fun. I am using a Raspberry Pi 2 B with Raspbian GNU/Linux 9 (stretch), Kernel 4.9.59-v7+. It is accessible via IPv6 only. It consists of two parts: the random generation and the PHP script that reads it.


The hardware random generator is available on all Raspberry Pi models. With root privileges you can read out random data from /dev/hwrng. In order to route the hwrng to /dev/random you must install the rng-tools:

(Other guides list some more commands to edit the /etc/default/rng-tools file in order to set the hardware device, but I didn’t need that. In my case it was running out of the box without any further configuration.)

Now you can read random data from /dev/random without (!) root privileges such as: (with base64 encoding to have the binary random readable)

Just for interest you can watch the entropy_avail file which shows the current available entropy. Without the hardware random generator this would immediately decrease and only increase slowly. With the hwrng it stays between 2000-4000 constantly even if you read out random data quite often. You can use the following command to watch the available entropy while refreshing the output every 0.5 seconds:

Lucky Number Generator” by Jeremy Brooks is licensed under CC BY-NC 2.0

PHP Script

I am using a small PHP script that reads out random data from /dev/random and encodes it with base64 to have only printable characters. I adjusted the length to read out 21 bytes = 168 bits to have 28 chars after the base64 encoding which is a very good starting point for PSKs. That is: The security level is 168 bits for these random data which is quite good!

This is the PHP code snippet:

When you look at the page at you’ll see the quick-and-dirty approach. ;) Give it a try and press F5 for a couple of times – just for fun. Feel free to pick up a random string for your passwords, PSKs, whatever. Note that this servers runs at IPv6-only. If you don’t have IPv6 yet, go and ask your ISP or admin for it! (A last resort would be the usage of an online IPv6 proxy such as to get an idea of the site.) Anyway, this is a screenshot:

And of course I am using only TLS secured https. Thanks to Let’s Encrypt.

Featured image “44742” by Tekniska museet is licensed under CC BY 2.0.

3 thoughts on “True Random PSK Generator on a Raspi

  1. If there is anything I could change about the Linux kernel, it would be the following:

    1. Get rid of the blocking /dev/random, and just symlink it to /dev/urandom
    2. Remove the misunderstood /proc/sys/kernel/random/entropy_avail file
    3. Block reading from /dev/urandom on boot until it’s been sufficiently seeded

    Something you might want to be aware of, and may cause you to stop seeding /dev/urandom with the RPi HWRNG:

    Basically, this shows that if the HWRNG (like RDRAND or the RPi) knows the state of the CSPRNG, it can manipulate the state, to provide compromised output (IE: a backdoor).

    1. One quick comment- if you wanted to be fully trusted, rather than generating the PSK server-side, and sending it to the page, generate it client-side in JavaScript with window.crypto.getRandomValues(), which uses the browser’s CSPRNG (Chrome and Firefox both fallback to the OS CSPRNG for the data). Then people can be assured that you’re not logging the generated keys with IP addresses. Just a thought.

      1. Hey Aaron. Thanks a lot for your comments. Really appreciate it.

        Yes, I would not trust a server-side PSK generation as well. ;) It’s more or less a hobby project to have this TRNG running at the Pi. At least I can use it myself since I really know that I am not logging the keys.

Leave a Reply

Your email address will not be published. Required fields are marked *