biox / pa

a simple password manager. encryption via age, written in portable posix shell
https://passwordass.org
Other
506 stars 21 forks source link

use 'openssl rand' as a fallback CSPRNG #29

Closed arcxio closed 4 months ago

arcxio commented 4 months ago

I decided to look into this one TODO comment, and after a bit of investigating, I found just one candidate of CSPRNG that could be available for use in a shell script if /dev/urandom fails, which is openssl rand.

now, I don't actually think this should be merged. first of all, the environment where openssl rand is available, but /dev/urandom is not, excludes almost any normally working current Unix-like desktop (which is what pa targets). in fact, I could only find Plan 9/9front in that category which doesn't have /dev/urandom, but it also wouldn't have openssl installed either, which discards this solution. it also can't simply fallback to /dev/random here either, because e.g. Plan 9's /dev/random is extremely slow and probably should not be used in pa (in general I guess it's just not possible to rely on a random device in systems which don't provide /dev/urandom):

The numbers are generated by a low priority kernel process that loops incrementing a variable. Each clock tick the variable is sampled and, if it has changed sufficiently, the last few bits are appended to a buffer. This process is inefficient at best producing at most a few hundred bits a second. Therefore, random should be treated as a seed to pseudo–random number generators which can produce a faster rate stream.

it would also be weird to explain that "openssl rand is an optional dependency, but not really, because it will never be called for practically everyone, that's just here as a theoretical fallback" (I felt insane just typing that out).

unless I'm missing a utility that's not openssl rand which could be used from shell and could be more ubiquitous on Unix-like systems than /dev/urandom, IMO it's safe to drop that TODO and just keep using /dev/urandom, until some upset experienced Plan 9 user offers a sane solution for their OS.

arcxio commented 4 months ago

on the note of falling back to /dev/random, OpenBSD manual has this to say:

For portability reasons, never use /dev/random. On OpenBSD, it is an alias for /dev/urandom, but on many other systems misbehaves by blocking because their random number generators lack a robust boot-time initialization sequence.

OpenSSL does fallback to /dev/random, /dev/hwrng, and /dev/srandom, but they only use them as a seed source to initialize their own RNG, pa shouldn't read from these devices directly, as they are not guaranteed to be non-blocking the way /dev/urandom is.

arcxio commented 4 months ago

CPython has os.urandom, which is a portable source of cryptographically secure random bytes, with a nice writeup in its comments. It sends system calls on Windows (out of scope), Linux, Solaris and OpenBSD (all have /dev/urandom), and relies on /dev/urandom otherwise. It also has a notable section specifically on alternatives to kernel RNGs:

Only use RNG running in the kernel. They are more secure because it is harder to get the internal state of a RNG running in the kernel land than a RNG running in the user land. The kernel has a direct access to the hardware and has access to hardware RNG, they are used as entropy sources.