The "what and why" for generating secure random data in various programming languages has been adequately covered elsewhere. In a nutshell:
Use /dev/urandom instead of /dev/random.
What hasn't been adequately covered is the how. So without further ado, how to safely generate random numbers in...
- C/C++
- Common Lisp
- Erlang
- Go
- Java
- JavaScript (Client-Side, In-Browser)
- .NET
- Node.js
- PHP
- Python
- Ruby
- Rust
General Requirements for Inclusion
Every solution on this page must exclusively read from the kernel's CSPRNG and fail closed. Userspace RNGs and insecure RNG fallbacks will not be accepted. This means the following sources of entropy are used, depending on platform:
- Windows:
-
RtlGenRandom
-
- Linux:
-
getrandom
(if available)- This does the correct thing: It blocks until seeded, and then never again.
-
/dev/urandom
(older Linux kernels)- For software that runs during the Linux boot, poll
/dev/random
until it's available. This means/dev/urandom
has been seeded and you can safely read from/dev/urandom
for all your cryptographic purposes. Don't read from/dev/random
.
- For software that runs during the Linux boot, poll
-
- OpenBSD:
-
getentropy()
-
arc4random_buf()
with ChaCha20 (not RC4)
-
- Other Unix-like (including OS X):
-
/dev/urandom
-
Solutions that rely on haveged, egd, etc. are not acceptable for consideration.
Cryptographically Secure Randomness in C/C++
The easiest and safest solution here is to add libsodium as a dependency to your project and just use randombytes_buf()
.
If this isn't considered an acceptable solution, take a close look at how libsodium implements these functions. The PHP team adopted a similar approach in the internal random_bytes
implementation.
#include "sodium.h"
int foo() {
char myString[32];
uint32_t myInt;
randombytes_buf(myString, 32);
/* myString will be an array of 32 random bytes, not null-terminated */
myInt = randombytes_uniform(10);
/* myInt will be a random number between 0 and 9 */
}
"Just use libsodium if you can," also applies for almost every other language below.
Cryptographically Secure Randomness in Common Lisp
As always, libsodium should be your first option.
Alternatively, if you're using the Ironclad cryptography library, you can just use the crypto:strong-random
API they expose.
(ql:quickload "ironclad")
(crypto:random-data 32) => 32 random bytes
(crypto:random-bits 128) => 128-bit random integer
(crypto:strong-random 1024) => random integer in (0, 1,024]
(crypto:strong-random 1.0) => random float in (0, 1.0]
Cryptographically Secure Randomness in Erlang
Don't use the crypto
module for this, as it just wraps OpenSSL (which in turn exposes a userland PRNG via RAND_bytes()
rather than the operating system's CSPRNG).
Instead, use Erlang's libsodium bindings. Added bonus: Now you have libsodium available to satisfy all of your project's cryptography needs.
RandomBytes = libsodium_randombytes:buf(32).
RandomInt = libsodium_randombytes:uniform(1000).
Cryptographically Secure Randomness in Go
Go provides a package called crypto/rand that you should use. It does everything right (but make you're using crypto/rand
and not math/rand
).
Refer to the example code provided in the Go documentation for crypto/rand
(which you can run from the browser).
Cryptographically Secure Randomness in Java
Aside from just using libsodium (recommended), Java's SecureRandom
class is straightforward:
SecureRandom csprng = new SecureRandom();
byte[] randomBytes = new byte[32];
csprng.nextBytes(randomBytes);
Important: Despite its name, don't use SecureRandom.getInstanceStrong()
! On Linux, this is the equivalent to reading /dev/random
which is a pointless performance killer. The default for new SecureRandom()
in Java 8 is to read from /dev/urandom
, which is what you want.
Also, don't attempt to seed the RNG manually. Java's default behavior is to read from the OS's CSPRNG.
Furthermore, never call SecureRandom.generateSeed()
, which on some platforms always uses /dev/random
instead of /dev/urandom
which kills your app's performance.
Cryptographically Secure Randomness in JavaScript (Client-Side, In-Browser)
First, make sure you're not making a terrible mistake.
Then, use window.crypto.getRandomValues()
if it's available, and fail hard
if it's not. There really aren't any other options.
See the section on CSPRNGs in Node.js for server-side JavaScript, which has its own nuances.
Cryptographically Secure Randomness in .NET (C#)
The generally accepted solution is to use System.Security.Cryptography.RNGCryptoServiceProvider
, like so:
RandomNumberGenerator csprng = new RNGCryptoServiceProvider();
byte[] rawByteArray = new byte[32];
csprng.getBytes(rawByteArray);
If you need to generate cryptoraphically secure integers, check out how this was implemented in the CryptoRandom class in the Inferno (a .NET cryptography library by Stan Drapkin).
Cryptographically Secure Randomness in Node.js
Your best bet until they move away from OpenSSL is node-sodium:
var csprng = require("sodium").Random;
var bytes = csprng.randombytes_buf(32);
If you want to throw caution to the wind and use OpenSSL's PRNG today, read this guide to randomness by Sven Slootweg.
Cryptographically Secure Randomness in PHP
If you're running PHP 7, there are built-in functions for this:
$string = random_bytes(32);
$integer = random_int(0, PHP_INT_MAX);
If you're still on PHP 5, grab random_compat and then enjoy the same API as PHP 7.
composer require paragonie/random_compat:^2
Please use version 2. Version 1 would fall back to OpenSSL if there were no other sources of entropy available, which is an unnecessary source of security concerns. However, some people will explicitly lock themselves into version 1 for compatibility reasons.
If you are building a PHP 5 library that other people will use in their projects, set the requirement string in your composer.json
to ^1|^2
. Conversely, if you are building an application, set the requirement string to ^2
.
Cryptographically Secure Randomness in Python
If you aren't using libsodium:
- If you need random bytes, use
os.urandom()
. - If you need other forms of randomness, you want an instance of
random.SystemRandom()
instead of justrandom
.
import os
import sys
import random
# Random bytes
bytes = os.urandom(32)
csprng = random.SystemRandom()
# Random (probably large) integer
random_int = csprng.randint(0, sys.maxint)
Cryptographically Secure Randomness in Ruby
Feel free to use SecureRandom
on Ruby 2.5.0 and newer. Otherwise, use cryptosphere/Sysrandom, which is basically the 2.5.0+ RNG for <2.5.0 (and can monkey-patch itself in place of legacy SecureRandom).
To install sysrandom:
gem install sysrandom
Cryptographically Secure Randomness in Rust
The rand
crate provides several RNG
APIs, but the one you want to use is OsRng
. The source code that
powers OsRng
is available here.
Sample code provided by Jamie Turner:
//! Safe cryptographic random number generation in Rust.
//! Works on Windows, Mac, Linux, FreeBSD, etc.
extern crate rand; // https://crates.io/crates/rand
use rand::{Rng}; // The generic trait all random generators support.
use rand::os::{OsRng}; // Specific implementation of above for strong crypto.
fn main() {
// OsRng is a type of `Rng` that wraps /dev/urandom, getrandom(), etc.
let mut r = OsRng::new().unwrap();
// Random bytes.
let mut my_secure_bytes = vec![0u8; 1500];
r.fill_bytes(&mut my_secure_bytes);
// Primitive types and short arrays.
let my_secure_int: u64 = r.gen();
println!("First few bytes = {:?}; random int = {:?}",
&my_secure_bytes[..5], my_secure_int);
}
Both libsodium and ring are cryptography libraries available to Rust developers that offer (among other things) sane random number generators.
Is Your Favorite Language Missing?
We plan to update this page over time to cover more of the popular programming languages. If we haven't gotten to your favorite language yet, see if it has libsodium bindings available. If not, email our security team (security -at- this domain name
) and we'll see about adding a section for it here.