roundly-consulting/crypto-for-laravel
Crypto for Laravel adds a clean, framework-native layer for common cryptography tasks—encryption, decryption, hashing, and secure random/key generation—with config-driven setup, facades, and helpers so you can keep sensitive data safe without wiring low-level PHP crypto code yourself.
Install the package via Composer:
composer require roundly-consulting/crypto-for-laravel
Laravel’s package auto-discovery registers the service provider and Crypto facade automatically.
Publish the config (optional) – the package is “zero-config” for most primitives, but if you need default keys for JWS/HMAC or custom algorithm preferences, publish the config file:
php artisan vendor:publish --tag=crypto-config
Then set values in config/crypto.php (or use per-call arguments to override).
First use case – secure token generation
The quickest win is generating a cryptographically secure random token for API keys, password resets, or session identifiers:
use Roundly\Crypto\Facades\Crypto;
$token = Crypto::token(32); // 32 bytes of CSPRNG entropy, hex or base64url encoded
Store only a hash of the token in your database and compare using hash_equals.
Where to look next – Open the Crypto facade class (usually Roundly\Crypto\Facades\Crypto) to see the full list of methods grouped by primitive: totp(), hotp(), jws(), webauthn(), hmac(), token(), and codec helpers (base64url(), hex()). Each primitive is à la carte – use only what you need.
Use Crypto::token($bytes) to create opaque tokens. For storage, hash with hash('sha256', $token) and verify with hash_equals. This pattern is ideal for API keys, email verification links, and remember-me cookies.
// Generate a new secret for a user
$secret = Crypto::totp()->generateSecret();
// Display a QR code (otpauth://totp/...)
$uri = Crypto::totp()->provisioningUri($secret, $user->email, 'MyApp');
// Verify a code (with a window of ±1 time step to allow for clock drift)
$isValid = Crypto::totp()->verify($secret, $request->code, window: 1);
For HOTP (counter-based), use Crypto::hotp()->verify($secret, $counter, $code) and increment the counter after each successful verification.
Sign and verify JSON Web Signatures without pulling in a full JWT library:
$jws = Crypto::jws()->sign(['sub' => $user->id, 'exp' => now()->addHour()->timestamp], 'HS256', $key);
$payload = Crypto::jws()->verify($jws, 'HS256', $key); // returns array or throws
Use asymmetric algorithms (RS256, ES256) when the verifier should not be able to sign. The package handles base64url encoding and header validation.
For passkey registration and authentication, verify attestation and assertion signatures:
$valid = Crypto::webauthn()->verifyAssertion(
$clientDataJson,
$authenticatorData,
$signature,
$publicKeyPem,
$expectedChallenge,
$expectedOrigin,
$expectedRpId
);
Always generate the challenge with Crypto::token(32) and store it in the session per attempt.
$signature = Crypto::hmac()->sign($payload, $secret, 'sha256');
$valid = Crypto::hmac()->verify($payload, $signature, $secret, 'sha256');
Use hash_equals internally (the package does) to avoid timing attacks.
Convert between binary and URL-safe strings:
$encoded = Crypto::base64url()->encode($binary);
$decoded = Crypto::base64url()->decode($encoded);
Useful for JWT segments, WebAuthn challenges, and cookie values that must survive URL encoding.
window (e.g., 1 or 2) when verifying to tolerate clock skew. Ensure your server’s time is synced via NTP.alg header from an untrusted token. Always pass the expected algorithm explicitly to verify(). The package likely enforces this, but double-check.origin and rpId to prevent phishing..env or a secrets manager, not in version control. The config file should only reference env('CRYPTO_JWS_KEY').base64_encode.Carbon::setTestNow() when testing TOTP. Use known test vectors from RFC 6238 for HOTP/TOTP to validate your integration.TotpContract) in the container. You can swap implementations via the service provider if needed.How can I help you explore Laravel packages today?