danidiaz
danidiaz

Reputation: 27766

How to produce a "securely random" string token in Haskell?

I want to produce string tokens to implement the password reset functionality of a web app. They can be v4 UUIDs but it is not required.

I want each token to be "securely random" in the sense of this SO question. The system's entropy pool should be sampled for each generated token.

I found the uuid package, that generates v4 UUIDs. The docs mention that

we use the System.Random StdGen as our random source.

but it is unclear to me if this is enough.

Is there other library that I should use instead?

Upvotes: 2

Views: 808

Answers (1)

user2847643
user2847643

Reputation: 2935

The requirement that the system entropy pool should be sampled on each generated token sounds suspicious. Entropy is usually a scarce resource.

Let's agree that /dev/random is definitely out. Other processes may need it, it could lead to potential denial of service etc. First and foremost though, /dev/random blocks on read when it deems the entropy pool insufficient so it's a definite no. /dev/urandom on the other hand should be perfectly fine. Some say that it has issues in some odd cases (for example right after boot on diskless machines) but let's no go there.

Note that on most systems /dev/[u]random both use the same algorithm. The difference is that /dev/urandom never blocks but also not necessarily uses any new entropy on each read. So if using /dev/urandom counts as "sampling the system entropy pool" then whatever solution you have that properly uses it is probably fine.

However, it comes at a cost of impurity. Reading from /dev/urandom forces us into IO. Being haskellers we have to at least consider alternatives and we are in luck if only we drop the entropy-sample requirement which seems weird to begin with.

Instead we can use a crypto-secure deterministic RNG and only seed it from /dev/random. ChaChaDRG from cryptonite which is an implementation of DJB's ChaCha would be a good choice. Since it is deterministic we only need IO to get the initial seed. Everything after that is pure.

Cryptonite offers getRandomBytes so you can tweak the length of the token to suit your needs.

Upvotes: 1

Related Questions