security

Cryptographic Randomness

Security-sensitive tokens must be unpredictable. PHP provides random_bytes() and random_int() for values such as reset tokens, CSRF tokens, API credentials, and verification codes.

Core Controls

  • Use random_bytes() for tokens and encode bytes with hex or base64url when text is needed.
  • Use random_int() for unbiased security-sensitive integer ranges.
  • Do not use rand(), mt_rand(), timestamps, or sequential IDs for secrets.
  • Give tokens enough entropy and a short lifetime.
  • Store a hash of long-lived bearer tokens where practical.

Generate A Reset Token

PHP example
<?php

declare(strict_types=1);

$token = bin2hex(random_bytes(32));
$storedDigest = hash('sha256', $token);

echo strlen($token) . PHP_EOL;
echo strlen($storedDigest) . PHP_EOL;

// Prints:
// 64
// 64

Send the raw token to the user once. Store the digest with the user ID, purpose, expiry time, and a used-at marker. When the token comes back, hash it and compare the digest with hash_equals().

Integers Need Secure Randomness Too

Use random_int() for a security-sensitive numeric code:

PHP example
<?php

declare(strict_types=1);

$verificationCode = random_int(100000, 999999);

echo strlen((string) $verificationCode) . PHP_EOL;

// Prints:
// 6

A six-digit code has far less entropy than a long reset token, so use a short expiry and strict attempt limits.

Random Is Not The Whole Design

Token safety also needs purpose binding, expiry, single use, secure transport, revocation, and redaction from logs. A strong random value can still leak through URLs, analytics, support screenshots, or verbose error reporting.

In Application Work

Randomness is only one part of token safety. Expiry, single use, secure delivery, revocation, and avoiding logs matter too.

What To Check

Before moving on, make sure you can choose between random_bytes() and random_int(), store token digests, and design expiry, single-use, attempt-limit, and logging rules.

Practice

Practice: Create A Reset Token Plan

Requirements

  • Generate a token with random_bytes().
  • Store only a hash of the token.
  • Set an expiry and single-use rule.
  • Explain how the raw token reaches the user safely.
Show solution

Review Points

  • Use random_bytes() for tokens and encode bytes with hex or base64url when text is needed.
  • Use random_int() for unbiased security-sensitive integer ranges.
  • Do not use rand(), mt_rand(), timestamps, or sequential IDs for secrets.
  • Give tokens enough entropy and a short lifetime.
  • Store a hash of long-lived bearer tokens where practical.