File this under the "I'm bored and have nothing better to do" category. While coming into work this morning, I was curious if I could use my monitors as a cryptographically secure pseudorandom number generator (CSPRNG). I don't know what use this would have, if any, as your GNU/Linux operating system already ships a CSPRNG with /dev/urandom. So, in reality, there is really no need to write a userspace CSPRNG. But what the hell, let's give it a try anywho.
The "cryptographically secure" piece of this will come from the SHA-512 function. Basically, the idea is this:
- Take a screenshot of your monitors.
- Take the SHA-512 of that screenshot.
- Resize the screenshot to 10% it's original size.
- Take the SHA-512 of that resized file.
- Take the SHA-512 of your previous two SHA-512 digests.
- Take the last n-bits of that final digest as your random number.
Most GNU/Linux systems come with ImageMagick pre-installed, as well as the "sha512sum(1)" function. So thankfully, we won't need to install any software. So, here's a simple shell script that can achieve our goals:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/bin/sh # Produces random numbers in the range of [0, 65535]. # Not licensed. Released to the public domain. cd ~/Private # assuming you have an encrypted filesystem mounted here TS1=$(date +%Y%m%d%H%M%S%N) import -window root ${TS1}.png sha512sum ${TS1}.png > /tmp/SHA512SUMS TS2=$(date +%Y%m%d%H%M%S%N) convert -scale 10% ${TS1}.png ${TS2}.png sha512sum ${TS2}.png >> /tmp/SHA512SUMS DIGEST=$(sha512sum /tmp/SHA512SUMS) printf "%d\n" 0x$(printf "$DIGEST" | awk '{print substr($1, 125, 128)}') shred ${TS1}.png ${TS2}.png rm ${TS1}.png ${TS2}.png shred /tmp/SHA512SUMS rm /tmp/SHA512SUMS |
Running it for 10 random numbers:
$ for i in {1..10}; do sh monitor-csprng.sh; done 15750 36480 64651 7942 2367 10905 53889 9346 52726 63570
A couple things to note:
- This is slow, due to taking the screenshot, and resizing it.
- The data on your monitors should be sufficiently random. Chats, social updates, etc. The security of this will depend entirely on the entropy of the initial screenshot.
- You really should be saving your screenshots to an encrypted filesystem, such as eCryptfs.
- We're using timestamps with nanosecond accuracy to provide some additional entropy for the final SHA-512 digest.
- This is using the last 4 hexadecimal characters to be converted to decimal. In reality, it could be anything, including some convoluted dynamic search algorithm in the string.
It's worth noting that the entropy of the initial screenshot is critical, which is actually difficult to accurately measure. So, it may help to have a chat window or more open, with recent chat logs. Same could be said for social update "walls", with the most recent updates (Twitter, Facebook, Goodreads, etc.). Having a clock with seconds ticking in a status bar can also help (although not unpredictable, at least semi-unique). Tabs in browsers, running applications, etc. The more unpredictable your workspace in the screenshot, the better off you'll be. But, people in general suck at randomness, so I'm not advocating this as something you should rely on for a cryptographically secure random number generator.
If you wanted, you could add this to a terminal, giving you a sort of "disco rave" before taking the screenshot:
1 2 3 4 5 6 7 | #!/bin/sh # Disco lights in your terminal # No license. Released to the public domain while true; do printf "\e[38;5;$(($(od -d -N 2 -A n /dev/urandom)%$(tput colors)))m•\e[0m" done |
Get that running first, then take your screenshot. But then, if you're reading data off of /dev/urandom, you might as well do that for your random numbers anyway...
Post a Comment