


From `mt_rand` to `random_int`: Generating Cryptographically Secure Numbers
Jul 28, 2025 am 04:42 AMmt_rand() is not secure for cryptographic purposes because it uses the Mersenne Twister algorithm, which produces predictable output, may be poorly seeded, and is not designed for security. 2. For secure random number generation, use random_int() instead, as it draws from the operating system’s cryptographically secure pseudorandom number generator (CSPRNG) and is resistant to prediction and timing attacks. 3. Avoid common mistakes such as assuming all random functions are equivalent, mishandling ranges in random_int(), or combining secure and insecure functions like random_int() and mt_rand(), which undermines security. 4. For PHP versions earlier than 7.0, install the paragonie/random_compat library via Composer to use random_int() and random_bytes() securely. 5. mt_rand() remains acceptable only for non-security-sensitive tasks such as shuffling quiz questions, generating UI IDs, or game mechanics where unpredictability is not critical. 6. Always use cryptographically secure functions like random_int() when dealing with authentication tokens, session keys, password resets, or any user-facing secrets to ensure robust security.
Generating random numbers in PHP has evolved significantly over the years — especially when it comes to security. If you're still using mt_rand()
for sensitive operations like generating tokens, passwords, or session keys, it's time to upgrade. Here's why and how to move from mt_rand()
to random_int()
for cryptographically secure number generation.

Why mt_rand()
Isn’t Secure
mt_rand()
uses the Mersenne Twister algorithm, which is great for simulations, games, or shuffling data — but not secure for cryptography.
- Predictable output: Given enough outputs, an attacker can reverse-engineer the internal state and predict future values.
- Not seeded properly by default: Especially in older PHP versions, seeding could be weak or based on predictable values like timestamps.
- Not designed for security: It’s a pseudo-random number generator (PRNG) meant for performance, not unpredictability.
Example: If you use
mt_rand(1, 1000000)
to generate a password reset token, an attacker might brute-force or predict possible values over time.![]()
Use random_int()
for Security-Critical Code
PHP 7 introduced random_int()
, part of the random
extension (built into PHP 7.0 ), which generates cryptographically secure random integers.
$secureRandomNumber = random_int(1, 1000000);
This function:

- Pulls randomness from the OS-level CSPRNG (like
/dev/urandom
on Linux orCryptGenRandom
on Windows). - Is resistant to prediction and timing attacks.
- Blocks only if the system’s entropy pool is empty (very rare on modern systems).
? Use
random_int()
when you need unpredictable numbers:
- CSRF tokens
- Password reset keys
- Session identifiers (though PHP handles this internally)
- Any user-facing secret
Common Mistakes and Pitfalls
Even with random_int()
, developers can slip up:
Assuming all random functions are equal
Don’t fall into the trap of replacingrand()
withmt_rand()
and calling it "fixed." Onlyrandom_int()
,random_bytes()
, or libraries likeparagonie/random_compat
are secure.Improper range handling
random_int($min, $max)
must have valid bounds. Avoid negative ranges or$min > $max
.Trying to "improve" randomness
Don’t do things like:// ? Don't do this $num = random_int(1, 100) * mt_rand(1, 10);
Mixing secure and insecure sources weakens the result.
Backward Compatibility: PHP < 7.0
If you're stuck on PHP 5.x, use the paragonie/random_compat
library:
composer require paragonie/random_compat
Now you can safely use:
$secureNumber = random_int(1, 100); $bytes = random_bytes(16);
It polyfills random_int()
and random_bytes()
using secure sources, even on older PHP versions.
When Is mt_rand()
Still Okay?
There are still valid uses for mt_rand()
— just not where security matters:
- Shuffling a list of quiz questions
- Generating non-sensitive IDs for UI elements
- Game mechanics where fairness ≠ security
But when in doubt, use random_int()
.
Basically, if it touches user authentication, access control, or secrets — go cryptographically secure. The switch from mt_rand()
to random_int()
is simple, safe, and future-proof.
The above is the detailed content of From `mt_rand` to `random_int`: Generating Cryptographically Secure Numbers. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

UseIntl.NumberFormatwithuser-specificlocalesforcorrectdigitgroupinganddecimalseparators.2.Formatcurrencyusingstyle:'currency'withISO4217codesandlocale-specificsymbolplacement.3.ApplycompactnotationforlargenumberstoenhancereadabilitywithunitslikeMor??

mt_rand()isnotsecureforcryptographicpurposesbecauseitusestheMersenneTwisteralgorithm,whichproducespredictableoutput,maybepoorlyseeded,andisnotdesignedforsecurity.2.Forsecurerandomnumbergeneration,userandom_int()instead,asitdrawsfromtheoperatingsystem

Using BCMath extension is the key to solving the accuracy of PHP financial calculations, because it performs decimal operations with arbitrary precision through strings, avoiding rounding errors of floating-point numbers; 2. You must always pass in the form of a string and set the scale parameters (such as bcadd('0.1','0.2',2)) to ensure that the result is accurate to the required decimal places; 3. Avoid passing the floating-point numbers directly to the BCMath function, because the accuracy has been lost before passing the parameters; 4. You can set the global decimal places through bccale(2) to ensure that the financial calculation retains two decimals uniformly; 5. BCMath default truncation rather than rounding, and you need to implement the rounding logic yourself (such as through the bcround function); 6. The input value needs to be verified.

When it is necessary to process integers exceeding PHP_INT_MAX (such as 9223372036854775807), 1. Any precision mathematical library such as GMP extension or brick/math should be used; 2. GMP is based on C library, with high performance but requires server support; 3. Brick/math is a pure PHP implementation, which is easy to port but slower; 4. When initializing large numbers, strings must be used to prevent accuracy loss; 5. All operations should avoid floating-point numbers to ensure accuracy. The final choice depends on the degree of environmental control, performance requirements and code style preferences, but large integers need to be safely initialized in strings.

PHP's loose type system is both powerful and dangerous in numeric type conversion. 1. When using loose comparison (==), PHP will convert non-numeric strings to 0, resulting in 'hello'==0 to true, which may cause security vulnerabilities. Strict comparisons (===) should always be used when needed. 2. In arithmetic operation, PHP will silently convert the string, such as '10apples' becomes 10, and 'apples10' becomes 0, which may cause calculation errors. The input should be verified using is_numeric() or filter_var(). 3. In the array key, a numeric string such as '123' will be converted into an integer, causing '007' to become 7, and the format is lost, which can be avoided by adding a prefix. 4. Function parameters

is_numeric()checksifavaluecanbeinterpretedasanumber,acceptingformatslikehex,scientificnotation,andwhitespace,butonlyreturnsabooleanwithouttypecasting.2.filter_var()withFILTER_VALIDATE_INTorFILTER_VALIDATE_FLOATvalidatesandsanitizesbyreturningtheactua

The problem of inaccurate floating point numbers is common in PHP, especially in financial calculations or precise comparisons. The root cause is that decimal decimals cannot be stored accurately in binary floating point representation (IEEE754 standard), resulting in results such as 0.1 0.2≠0.3; 1. When comparing floating point numbers equality, you should use tolerance values (epsilon) instead of directly using ==; 2. Financial calculations should avoid using floating point numbers, and instead use integers (such as in units of division) or BCMath extension; 3. BCMath performs arbitrary precision calculations through strings, which are suitable for high-precision scenarios, but have low performance; 4. It should be noted that PHP type conversion may implicitly convert strings or integers to floating point numbers to introduce errors; in short, inaccurate floating point numbers is a general calculation problem, but in

intdiv()performstrueintegerdivisionandissaferforwholenumbers,whilecasting(int)afterdivisionrisksfloating-pointprecisionerrors.2.Bothtruncatetowardzero,butcastingcanyieldincorrectresultswithnegativeorimprecisevaluesduetofloatrepresentationissues.3.int
