• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2021-

dist/H03-May-2021-1815

lib/H03-May-2021-331

other/H03-May-2021-18999

.scrutinizer.ymlH A D03-May-202169 44

.travis.ymlH A D03-May-20211.2 KiB5450

CHANGELOG.mdH A D03-May-202147 42

LICENSEH A D03-May-20211.1 KiB2317

RATIONALE.mdH A D03-May-20211.6 KiB3726

README.mdH A D03-May-20219.4 KiB233184

SECURITY.mdH A D03-May-20214.8 KiB10985

build-phar.shH A D03-May-2021134 52

composer.jsonH A D03-May-2021868 3534

phpunit.shH A D03-May-20211.5 KiB6146

phpunit.xml.distH A D03-May-2021963 3231

psalm-autoload.phpH A D03-May-2021231 107

psalm.xmlH A D03-May-2021596 2019

README.md

1# random_compat
2
3[![Build Status](https://travis-ci.org/paragonie/random_compat.svg?branch=master)](https://travis-ci.org/paragonie/random_compat)
4[![Scrutinizer](https://scrutinizer-ci.com/g/paragonie/random_compat/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/paragonie/random_compat)
5[![Latest Stable Version](https://poser.pugx.org/paragonie/random_compat/v/stable)](https://packagist.org/packages/paragonie/random_compat)
6[![Latest Unstable Version](https://poser.pugx.org/paragonie/random_compat/v/unstable)](https://packagist.org/packages/paragonie/random_compat)
7[![License](https://poser.pugx.org/paragonie/random_compat/license)](https://packagist.org/packages/paragonie/random_compat)
8[![Downloads](https://img.shields.io/packagist/dt/paragonie/random_compat.svg)](https://packagist.org/packages/paragonie/random_compat)
9
10PHP 5.x polyfill for `random_bytes()` and `random_int()` created and maintained
11by [Paragon Initiative Enterprises](https://paragonie.com).
12
13Although this library *should* function in earlier versions of PHP, we will only
14consider issues relevant to [supported PHP versions](https://secure.php.net/supported-versions.php).
15**If you are using an unsupported version of PHP, please upgrade as soon as possible.**
16
17## Important
18
19Although this library has been examined by some security experts in the PHP
20community, there will always be a chance that we overlooked something. Please
21ask your favorite trusted hackers to hammer it for implementation errors and
22bugs before even thinking about deploying it in production.
23
24**Do not use the master branch, use a [stable release](https://github.com/paragonie/random_compat/releases/latest).**
25
26For the background of this library, please refer to our blog post on
27[Generating Random Integers and Strings in PHP](https://paragonie.com/blog/2015/07/how-safely-generate-random-strings-and-integers-in-php).
28
29### Usability Notice
30
31If PHP cannot safely generate random data, this library will throw an `Exception`.
32It will never fall back to insecure random data. If this keeps happening, upgrade
33to a newer version of PHP immediately.
34
35## Installing
36
37**With [Composer](https://getcomposer.org):**
38
39    composer require paragonie/random_compat
40
41**Signed PHP Archive:**
42
43As of version 1.2.0, we also ship an ECDSA-signed PHP Archive with each stable
44release on Github.
45
461. Download [the `.phar`, `.phar.pubkey`, and `.phar.pubkey.asc`](https://github.com/paragonie/random_compat/releases/latest) files.
472. (**Recommended** but not required) Verify the PGP signature of `.phar.pubkey`
48   (contained within the `.asc` file) using the [PGP public key for Paragon Initiative Enterprises](https://paragonie.com/static/gpg-public-key.txt).
493. Extract both `.phar` and `.phar.pubkey` files to the same directory.
504. `require_once "/path/to/random_compat.phar";`
515. When a new version is released, you only need to replace the `.phar` file;
52   the `.pubkey` will not change (unless our signing key is ever compromised).
53
54**Manual Installation:**
55
561. Download [a stable release](https://github.com/paragonie/random_compat/releases/latest).
572. Extract the files into your project.
583. `require_once "/path/to/random_compat/lib/random.php";`
59
60The entrypoint should be **`lib/random.php`** directly, not any of the other files in `/lib`.
61
62## Usage
63
64This library exposes the [CSPRNG functions added in PHP 7](https://secure.php.net/manual/en/ref.csprng.php)
65for use in PHP 5 projects. Their behavior should be identical.
66
67### Generate a string of random bytes
68
69```php
70try {
71    $string = random_bytes(32);
72} catch (TypeError $e) {
73    // Well, it's an integer, so this IS unexpected.
74    die("An unexpected error has occurred");
75} catch (Error $e) {
76    // This is also unexpected because 32 is a reasonable integer.
77    die("An unexpected error has occurred");
78} catch (Exception $e) {
79    // If you get this message, the CSPRNG failed hard.
80    die("Could not generate a random string. Is our OS secure?");
81}
82
83var_dump(bin2hex($string));
84// string(64) "5787c41ae124b3b9363b7825104f8bc8cf27c4c3036573e5f0d4a91ad2eeac6f"
85```
86
87### Generate a random integer between two given integers (inclusive)
88
89```php
90try {
91    $int = random_int(0, 255);
92} catch (TypeError $e) {
93    // Well, it's an integer, so this IS unexpected.
94    die("An unexpected error has occurred");
95} catch (Error $e) {
96    // This is also unexpected because 0 and 255 are both reasonable integers.
97    die("An unexpected error has occurred");
98} catch (Exception $e) {
99    // If you get this message, the CSPRNG failed hard.
100    die("Could not generate a random int. Is our OS secure?");
101}
102
103var_dump($int);
104// int(47)
105```
106
107### Exception handling
108
109When handling exceptions and errors you must account for differences between
110PHP 5 and PHP7.
111
112The differences:
113
114* Catching `Error` works, so long as it is caught before `Exception`.
115* Catching `Exception` has different behavior, without previously catching `Error`.
116* There is *no* portable way to catch all errors/exceptions.
117
118#### Our recommendation
119
120**Always** catch `Error` before `Exception`.
121
122#### Example
123
124```php
125try {
126    return random_int(1, $userInput);
127} catch (TypeError $e) {
128    // This is okay, so long as `Error` is caught before `Exception`.
129    throw new Exception('Please enter a number!');
130} catch (Error $e) {
131    // This is required, if you do not need to do anything just rethrow.
132    throw $e;
133} catch (Exception $e) {
134    // This is optional and maybe omitted if you do not want to handle errors
135    // during generation.
136    throw new InternalServerErrorException(
137        'Oops, our server is bust and cannot generate any random data.',
138        500,
139        $e
140    );
141}
142```
143
144### Troubleshooting
145
146#### Exception: "Could not gather sufficient random data"**
147
148If an Exception is thrown, then your operating system is not secure.
149
1501. If you're on Windows, make sure you enable mcrypt.
1512. If you're on any other OS, make sure `/dev/urandom` is readable.
152   * FreeBSD jails need to expose `/dev/urandom` from the host OS
153   * If you use `open_basedir`, make sure `/dev/urandom` is allowed
154
155This library does not (and will not accept any patches to) fall back to
156an insecure random number generator.
157
158#### Version Conflict with [Other PHP Project]
159
160If you're using a project that has a line like this in its composer.json
161
162    "require" {
163        ...
164        "paragonie/random_compat": "~1.1",
165        ...
166    }
167
168...and then you try to add random_compat 2 (or another library that explicitly
169requires random_compat 2, such as [this secure PHP encryption library](https://github.com/defuse/php-encryption)),
170you will get a version conflict.
171
172The solution is to get the project to update its requirement string to allow
173version 2 and above to be used instead of hard-locking users to version 1.
174
175```diff
176"require" {
177    ...
178-    "paragonie/random_compat": "~1.1",
179+    "paragonie/random_compat": "^1|^2",
180    ...
181}
182```
183
184## Contributors
185
186This project would not be anywhere near as excellent as it is today if it
187weren't for the contributions of the following individuals:
188
189* [@AndrewCarterUK (Andrew Carter)](https://github.com/AndrewCarterUK)
190* [@asgrim (James Titcumb)](https://github.com/asgrim)
191* [@bcremer (Benjamin Cremer)](https://github.com/bcremer)
192* [@chriscct7 (Chris Christoff)](https://github.com/chriscct7)
193* [@CodesInChaos (Christian Winnerlein)](https://github.com/CodesInChaos)
194* [@ConnorVG (Connor S. Parks)](https://github.com/ConnorVG)
195* [@cs278 (Chris Smith)](https://github.com/cs278)
196* [@cweagans (Cameron Eagans)](https://github.com/cweagans)
197* [@dd32 (Dion Hulse)](https://github.com/dd32)
198* [@geggleto (Glenn Eggleton)](https://github.com/geggleto)
199* [@glensc (Elan Ruusamäe)](https://github.com/glensc)
200* [@GrahamCampbell (Graham Campbell)](https://github.com/GrahamCampbell)
201* [@ircmaxell (Anthony Ferrara)](https://github.com/ircmaxell)
202* [@jdevalk (Joost de Valk)](https://github.com/jdevalk)
203* [@jedisct1 (Frank Denis)](https://github.com/jedisct1)
204* [@juliangut (Julián Gutiérrez)](https://github.com/juliangut)
205* [@kelunik (Niklas Keller)](https://github.com/kelunik)
206* [@lt (Leigh)](https://github.com/lt)
207* [@MasonM (Mason Malone)](https://github.com/MasonM)
208* [@menkaff (Mehran NikNafs)](https://github.com/menkaff)
209* [@mmeyer2k (Michael M)](https://github.com/mmeyer2k)
210* [@narfbg (Andrey Andreev)](https://github.com/narfbg)
211* [@nicolas-grekas (Nicolas Grekas)](https://github.com/nicolas-grekas)
212* [@ocean90 (Dominik Schilling)](https://github.com/ocean90)
213* [@oittaa](https://github.com/oittaa)
214* [@oucil (Kevin Farley)](https://github.com/oucil)
215* [@philios33 (Phil Nicholls)](https://github.com/philios33)
216* [@redragonx (Stephen Chavez)](https://github.com/redragonx)
217* [@relaxnow (Boy Baukema)](https://github.com/relaxnow)
218* [@rchouinard (Ryan Chouinard)](https://github.com/rchouinard)
219* [@rugk](https://github.com/rugk)
220* [@SammyK (Sammy Kaye Powers)](https://github.com/SammyK)
221* [@scottchiefbaker (Scott Baker)](https://github.com/scottchiefbaker)
222* [@skyosev (Stoyan Kyosev)](https://github.com/skyosev)
223* [@sthen (Stuart Henderseon)](https://github.com/sthen)
224* [@stof (Christophe Coevoet)](https://github.com/stof)
225* [@teohhanhui (Teoh Han Hui)](https://github.com/teohhanhui)
226* [@tom-- (Tom Worster)](https://github.com/tom--)
227* [@tsyr2ko](https://github.com/tsyr2ko)
228* [@trowski (Aaron Piotrowski)](https://github.com/trowski)
229* [@twistor (Chris Lepannen)](https://github.com/twistor)
230* [@vinkla (Vincent Klaiber)](https://github.com/vinkla)
231* [@voku (Lars Moelleken)](https://github.com/voku)
232* [@xabbuh (Christian Flothmann)](https://github.com/xabbuh)
233