CSPRNG
debt(d5/e1/b1/t7)
Closest to 'specialist tool catches' (d5). The term's detection_hints list semgrep, psalm, and phpstan as tools that can detect insecure random function usage (rand(), mt_rand(), uniqid(), array_rand(), shuffle()). These are specialist static analysis tools, not default linters that run automatically in most PHP setups.
Closest to 'one-line patch' (e1). The quick_fix states to simply replace rand()/mt_rand() calls with random_bytes(n) or random_int(min, max). This is a direct single-call swap requiring no architectural changes.
Closest to 'minimal commitment' (b1). Using CSPRNG functions like random_bytes() and random_int() is a localized choice at the call site. It doesn't impose ongoing maintenance burden or shape future development — it's just picking the right function for security-sensitive randomness.
Closest to 'serious trap' (t7). The misconception explicitly states developers believe 'rand() and mt_rand() are random enough for security tokens.' This contradicts how 'random' functions work in security contexts elsewhere — most developers assume anything called 'random' is unpredictable. The functions look safe, produce output that appears random, but are entirely predictable given seed observation. This matches how similar concepts mislead developers from other ecosystems.
Also Known As
TL;DR
Explanation
A CSPRNG is a random number generator that satisfies cryptographic security requirements: its output must be statistically indistinguishable from truly random data, and knowing past output must not allow predicting future output. PHP's random_bytes() and random_int() use the OS CSPRNG (/dev/urandom on Linux, CryptGenRandom on Windows). Regular rand(), mt_rand(), and uniqid() are NOT CSPRNGs and must not be used for security-sensitive values.
Common Misconception
Why It Matters
Common Mistakes
- Using rand(), mt_rand(), or array_rand() for security tokens, session IDs, or CSRF tokens.
- Using uniqid() which is based on microtime and guessable.
- Seeding mt_srand() with a predictable value like time() and using the output for secrets.
- Not using random_bytes() or random_int() which are PHP's CSPRNG wrappers since PHP 7.
Code Examples
// Predictable token — seeded by time:
$token = md5(uniqid(mt_rand(), true)); // WRONG
// Correct:
$token = bin2hex(random_bytes(32));
// PHP 7+ — CSPRNG built in, no configuration needed
$bytes = random_bytes(32); // 32 random bytes from OS CSPRNG
$int = random_int(1, 100); // secure random int in range
$token = bin2hex(random_bytes(32)); // 64-char hex token
$b64 = base64_encode(random_bytes(32)); // base64 encoded
// URL-safe base64 (no +/= chars)
$urlSafe = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
// For OTPs
$otp = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);
// NEVER use: rand(), mt_rand(), uniqid(), microtime() for security purposes
// They are NOT cryptographically secure