Не всі генератори випадкових чисел однакові. Для безпеки потрібен криптографічно стійкий генератор (CSPRNG), результат якого неможливо передбачити.
Для токенів, паролів, кодів підтвердження - лише CSPRNG:
random_int(100000, 999999); // 6-значний код підтвердження
bin2hex(random_bytes(32)); // 64-символьний токен
Str::random(40); // у Laravel - теж на random_bytes
Чого не використовувати для безпеки:
rand(),mt_rand()- Mersenne Twister: швидкий, але передбачуваний. Знаючи кілька результатів, можна відновити внутрішній стан і передбачити наступні.uniqid()- це час з мікросекундами, а не випадковість.md5(time()),sha1(microtime())- хеш передбачуваного значення лишається передбачуваним.shuffle(),array_rand(),str_shuffle()- використовують нестійкий генератор.
Розширення Random (PHP 8.2) - об'єктний API з явним вибором рушія:
use Random\Randomizer;
use Random\Engine\Secure;
use Random\Engine\Mt19937;
$secure = new Randomizer(new Secure()); // CSPRNG за замовчуванням
$secure->getBytesFromString('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', 8); // код без схожих символів
$secure->shuffleArray($items); // безпечне перемішування
$seeded = new Randomizer(new Mt19937(42)); // відтворюваний: та сама послідовність з тим самим seed
$seeded->getInt(1, 100);
Відтворювана (seeded) випадковість корисна поза безпекою: тести, генерація даних, детерміновані вибірки («та сама випадкова добірка для того самого користувача сьогодні»).
Порівняння токенів - через hash_equals(), а зберігати токени доступу в базі краще хешованими (як паролі, але достатньо hash('sha256', ...), бо токен і так довгий і випадковий).