1## Rationale (Design Decisions) 2 3### Reasoning Behind the Order of Preferred Random Data Sources 4 5The order is: 6 7 1. `libsodium if available` 8 2. `fread() /dev/urandom if available` 9 3. `mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)` 10 4. `COM('CAPICOM.Utilities.1')->GetRandom()` 11 12If libsodium is available, we get random data from it. This is the preferred 13method on all OSes, but libsodium is not very widely installed, so other 14fallbacks are available. 15 16Next, we read `/dev/urandom` (if it exists). This is the preferred file to read 17for random data for cryptographic purposes for BSD and Linux. This step 18is skipped on Windows, because someone could create a `C:\dev\urandom` 19file and PHP would helpfully (but insecurely) return bytes from it. 20 21Despite [strongly urging people not to use mcrypt in their projects](https://paragonie.com/blog/2015/05/if-you-re-typing-word-mcrypt-into-your-code-you-re-doing-it-wrong) 22(because libmcrypt is abandonware and the API puts too much responsibility on the 23implementor) we prioritize `mcrypt_create_iv()` with `MCRYPT_DEV_URANDOM` above 24the remaining implementations. 25 26The reason is simple: `mcrypt_create_iv()` is part of PHP's `ext/mcrypt` code, 27and is not part `libmcrypt`. It actually does the right thing: 28 29 * On Unix-based operating systems, it reads from `/dev/urandom` which 30 (unlike `/dev/random`) is the sane and correct thing to do. 31 * On Windows, it reads from `CryptGenRandom`, which is an exclusively Windows 32 way to get random bytes. 33 34If we're on Windows and don't have access to `mcrypt`, we use `CAPICOM.Utilities.1`. 35 36As of random_compat 2.0, we no longer fall through to OpenSSL. 37