There’s been a lot of talk about Entropy as a Service lately and as someone with an interest in security it got me thinking why, what devices are really lacking entropy such that they’d risk pulling in someone else’s… IoT devices needing to generate Strong? cryptographic keys on or shortly after boot, Gitlab runners (Docker containers where /dev/random is not passed from the parent). Sounds like there is a need.

OpenBSD has high quality entropy and plenty of it, on a busy server with network services. So I thought I’d write up an EaaS offering using it. I started simply DDing bytes from /dev/urandom OpenBSD chroots it’s HTTPD daemon but that’s ok a MAKEDEV in webroot/dev solved that first hurdle.

Second hurdle I just couldn’t get python to run in OpenBSD’s chroot – It just wouldn’t execute. OpenBSD has long (>15 years?) supported(Pioneered?) W^X memory pages but since 2016 it became mandatory. If a program can’t cope with this it has to sit on the naughty partition (/usr/local by default) with wxallowed flag set a mount time. Python is marked as needed mixed writable and executable memory (Actually I think this is only needed by a few third party modules). Two options, enable wxallowed in httpd’s chroot but that’s weakening the security on an internet facing service, Ruby then… Nope same problem.

Perl then and arc4random (no longer a need for a chroot /dev/urandom) via BSD::arc4random module Perl has always had an eye on security, with -T it will help highlight, indeed stop you executing user input without first giving it a bit of a scrub. There are some implementation variations and standards, so I thought I’d add another very simple API.

curl --retry 2 https://entropy.rob-turner.net/api/v2/

Will return 512 bytes of base64 encoded entropy in the body and the epoch time in the http headers example below, this delivers time over https which can be used to sanity check ntp results, although personally you are reinventing the wheel here as yet again OpenBSD has solved this problem with Constraints in OpenNTPD

< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-type: text/plain: charset=utf-8
< Date: Mon, 29 Jul 2019 17:13:45 GMT
< Epoch-Time: 1564420425
< Server: OpenBSD httpd
< Transfer-Encoding: chunked 

You shouldn’t use this directly to make keys, instead you should combine it with other sources, hash and salt it the use that to stir your entropy pool, for example see below where I combine it with data from random.org which gets it’s entropy from atmospheric noise

SALT=$(dd if=/dev/urandom bs=64 count=1)
EPOCH=$(date --date="$(date +%H:%M:00)" +%s)
RESULTS=$(curl --retry 2 https://entropy.rob-turner.net/api/v2/ | base64 -d)
RAND=$(curl --retry 2 "https://www.random.org/cgi-bin/randbyte?nbytes=512&amp;format=b")
DATA=$(echo "${SALT}${EPOCH}${RESULTS}" | sha512)
MORE=$(echo "${SALT}${RAND}" | sha512)
echo "$DATA" > /dev/random
echo "$MORE" > /dev/random