qrand
is a Go package that provides random numbers derived, ultimately, from a non-deterministic, quantum-mechanical process.
import "github.com/bitfield/qrand"
The random data is provided by the ANU Quantum Numbers (AQN) API. You'll need an API key for this service, but it's free for limited use (see the website for details on how to pay for more data if you need it).
Here are a couple of example programs that show how you might use qrand
.
A common use of crypto/rand
in Go programs is to read a sequence of cryptographically secure random bytes (an initialization vector, for example). qrand
can do the same thing, but deriving its data from the quantum randomness provider.
The numbers
example shows how to do this:
q := qrand.NewReader(apiKey)
buf := make([]byte, 10)
_, err := q.Read(buf)
As you can see, this is very similar to the corresponding crypto/rand
example. The only difference here is that we need to create the reader first with NewReader
, because the provider requires an API key.
Go's math/rand
, on the other hand, is commonly used to provide random numbers within a desired interval, using something like rand.Intn
. This is useful in games, for example, or other programs that need “random-seeming” behaviour, but not strict cryptographic security.
The password
example shows how to do this with qrand
, by creating a randomness source:
rnd := rand.New(qrand.NewSource(qrand.NewReader(apiKey)))
password := make([]byte, 32)
for i := range password {
password[i] = chars[rnd.Intn(len(chars))]
}
There's a simple CLI tool to request and display a given number of random (hex) bytes. To install it:
go install github.com/bitfield/qrand/cmd/qrand@latest
To use it, pick the number of bytes you need (for example, 32), and run:
qrand 32
8e8c2771be5c2bb10d541a5bf6aa51203e0bce2d6d4fa267afd89a6e20df11f1
Random numbers should not be generated with a method chosen at random.
—Donald Knuth, “The Art of Computer Programming, Vol 2: Seminumerical Algorithms”
Most computer random number generators (RNGs) use a deterministic process, which means that given an initial seed value, the sequence of generated numbers is predictable.
For example, Go's standard math/rand
library uses a fairly simple algorithm to generate a random-looking, but still deterministic sequence of numbers. For most applications this is absolutely fine when seeded with a suitable value, such as the current Unix time in nanoseconds (which is the default from Go 1.20 onwards).
For any cryptographic purposes, though, math/rand
is insecure, and we should use crypto/rand
instead. crypto/rand
will use the most secure randomness source provided by the operating system; for example, on Linux systems this might be the /dev/urandom
or /dev/random
devices.
While this is still technically a pseudo-random source, it uses environmental 'noise' such as I/O activity, keystrokes, and so on, to generate numbers which are in practice (though not in principle) unpredictable.
For very high-security applications, though, we can use quantum-mechanical sources, such as the cosmic microwave background radiation:
The outcomes of quantum measurements, such as the spin of an electron or the polarization of a photon, are in principle unpredictable, to the best of our knowledge:
Hardware RNGs are available that can use such measurements to generate random data at fairly high bitrates (many GiB/s).
Australia National University provides a public quantum randomness source, derived from a hardware RNG, via its AQN service. This has a public API, which is the source of the data obtained with qrand
.
The random data is generated by a device that uses a laser to measure the quantum fluctuations of the vacuum:
- Symul, T., Assad, S. M., & Lam, P. K. (2011). Real time demonstration of high bitrate quantum random number generation with coherent laser light. Applied Physics Letters, 98(23)
- Haw, J. Y., Assad, S. M., Lance, A. M., Ng, N. H. Y., Sharma, V., Lam, P. K., & Symul, T. (2015). Maximization of extractable randomness in a quantum random-number generator. Physical Review Applied, 3(5), 054004.
You don't. The standard randomness source provided by your operating system, available via crypto/rand
, is almost certainly good enough for any application requiring strong randomness, such as cryptography (otherwise, we're all in trouble).
However, it's fun to use a source of randomness which is entirely non-deterministic (so far as we know) and provided directly by the Universe itself.
qrand
is primarily for fun, but just in case you're thinking of using it in programs, here's an important caveat.
For games and other non-cryptographic applications, as I mentioned, any reasonably random-looking data is fine. For speed, you'd normally use math/rand
for this.
But when you're doing cryptography (for example, hashing, signing, initializing ciphers, generating keys, and so on), math/rand
is not good enough, and that's what crypto/rand
is for.
Since crypto/rand
will use as secure a source of randomness as the local computer can provide, that's about as good as we can hope to get. This will probably derive from the operating system, as mentioned earlier.
Data from qrand
is both more and less secure than crypto/rand
's. More secure, because the outcomes of quantum measurements are unpredictable in principle, as we saw earlier, whereas software-based RNGs are merely unpredictable in practice.
Less secure, because it's coming over the network. Although the connection to the API uses TLS, and is thus encrypted, it's still possible that the data could be intercepted or modified by a third party (via a man-in-the-middle attack, for example). To put it another way, the random data obtained by qrand
is only as secure as your TLS connection to the AQN server.
And, of course, it all rather depends on whether you trust the AQN service itself. I offer no warranty of any kind that data obtained with qrand
is cryptographically secure. Nor could I if I wanted to, because qrand
itself is merely a client for this third-party service.
You have been warned.