NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Crypto for Laravel

Random tokens & secrets

Random generation is backed by random_bytes() and random_int(). Every generator validates its length and throws Random\InvalidLengthException rather than returning a weak value:

use RoundlyConsulting\Crypto\Facades\Crypto;

$bytes  = Crypto::random()->bytes(32);
$token  = Crypto::random()->token(40);          // base64url, ≥32 chars
$digits = Crypto::random()->numeric(6);
$alnum  = Crypto::random()->alphanumeric(24);
$code   = Crypto::random()->fromAlphabet('ABCDEFGHJKMNPQRSTUVWXYZ23456789', 10);
$secret = Crypto::random()->secret(32);         // base32, for TOTP

// Flat shortcuts for the common three:
Crypto::randomBytes(32);
Crypto::randomToken(40);
Crypto::randomSecret(32);

Or call the classes the facade fronts directly:

use RoundlyConsulting\Crypto\Random\Bytes;
use RoundlyConsulting\Crypto\Random\Secret;
use RoundlyConsulting\Crypto\Random\Token;

$bytes  = Bytes::generate(32);
$token  = Token::urlSafe(40);                 // base64url, ≥32 chars
$digits = Token::numeric(6);                  // digits only (numeric OTP / recovery code)
$alnum  = Token::alphanumeric(24);            // 0-9A-Za-z
$code   = Token::fromAlphabet('ABCDEFGHJKMNPQRSTUVWXYZ23456789', 10);   // no ambiguous characters
$secret = Secret::base32(32);                 // 32 base32 chars for an authenticator app
MethodOutputLength bounds
Bytes::generate($length)Raw CSPRNG bytes.1 to 1 MiB (Bytes::MAXIMUM_LENGTH).
Token::urlSafe($length = 40)Exactly $length base64url characters.32 (Token::MINIMUM_LENGTH) to 4096.
Token::numeric($length)Digits only, drawn uniformly.1 to 4096.
Token::alphanumeric($length)0-9A-Za-z, drawn uniformly.1 to 4096.
Token::fromAlphabet($alphabet, $length)A uniform draw of whole characters from your UTF-8 alphabet.1 to 4096; the alphabet must be non-empty, valid UTF-8.
Secret::base32($chars = 32)A base32 secret Totp, Hotp and Base32::decode() accept.1 to 4096 (Secret::MAXIMUM_CHARS); 1, 3 or 6 (mod 8) rounds up one character.

Upper bounds mean wiring a length to untrusted input can never self-inflict a memory or CPU DoS.

fromAlphabet() takes UTF-8 text and draws whole characters, so a multibyte alphabet (“äöü”, emoji) yields valid UTF-8 of exactly the requested number of characters; an alphabet that is not valid UTF-8 throws InvalidLengthException.

Secret::base32() — and Crypto::random()->secret() / randomSecret() — always returns a secret that Totp, Hotp and Base32::decode() accept. A length of 1, 3 or 6 (mod 8) has no canonical base32 form, so such a request rounds up one character (17 → 18 characters); every other length is exact. Rounding up keeps at least the requested entropy.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.