web-token/jwt-encryption-algorithm-pbes2
Adds PBES2 password-based encryption algorithms for JWT/JWE in the web-token stack. Enables PBES2-HS256+A128KW, PBES2-HS384+A192KW and PBES2-HS512+A256KW support for secure key wrapping when encrypting tokens.
Installation Add the package via Composer:
composer require web-token/jwt-encryption-algorithm-pbes2
Basic Usage
Import the algorithm class and use it with a JWT library (e.g., firebase/php-jwt or lucadegasperi/oauth2-server):
use WebToken\JWT\Encryption\Algorithm\PBES2;
use WebToken\JWT\Encryption\Key\ContentEncryptionKey;
// Initialize PBES2 with a password and salt
$algorithm = new PBES2('my-secret-password', 'my-salt');
// Encrypt a key (e.g., for JWT encryption)
$key = new ContentEncryptionKey('my-key-data');
$encryptedKey = $algorithm->encrypt($key);
First Use Case Encrypt a symmetric key (e.g., AES-256) for secure JWT payload encryption:
$jwtPayload = ['user_id' => 123, 'exp' => time() + 3600];
$encryptedKey = $algorithm->encrypt($key); // From above
$jwt = \Firebase\JWT\JWT::encode($jwtPayload, $encryptedKey, 'PBES2');
Key Generation Generate a random AES key for payload encryption:
$aesKey = \Sodium\crypto_secretbox_keygen();
Key Encryption Use PBES2 to encrypt the AES key with a password-derived key:
$pbes2 = new PBES2(config('app.jwt_password'), config('app.jwt_salt'));
$encryptedKey = $pbes2->encrypt(new ContentEncryptionKey($aesKey));
JWT Creation Encode the JWT with the encrypted key:
$jwt = \Firebase\JWT\JWT::encode($payload, $encryptedKey, 'PBES2');
Decryption Decrypt the key during JWT verification:
$decryptedKey = $pbes2->decrypt($encryptedKey);
$decoded = \Firebase\JWT\JWT::decode($jwt, new \Firebase\JWT\Key($decryptedKey, 'HS256'));
Configuration
Store the password and salt in Laravel’s .env:
JWT_PASSWORD=your_strong_password_here
JWT_SALT=random_salt_string
Retrieve them in config/jwt.php:
'pbes2' => [
'password' => env('JWT_PASSWORD'),
'salt' => env('JWT_SALT'),
],
Service Provider Bind the algorithm to Laravel’s container for reuse:
$this->app->bind(PBES2::class, function ($app) {
return new PBES2(
$app['config']['jwt.pbes2.password'],
$app['config']['jwt.pbes2.salt']
);
});
Middleware Use middleware to decrypt keys during JWT verification:
public function handle($request, Closure $next) {
$token = $request->bearerToken();
$pbes2 = app(PBES2::class);
$decryptedKey = $pbes2->decrypt($token->key);
$request->merge(['decrypted_key' => $decryptedKey]);
return $next($request);
}
Password Strength
PBES2 relies on the password’s entropy. Use a long, random password (e.g., 32+ chars) or a passphrase. Avoid weak passwords like password123.
Salt Management
Algorithm Limitations
firebase/php-jwt requires custom handling).Key Derivation The package uses PBKDF2 under the hood. Default iterations may be insufficient for modern security. Override if needed:
$algorithm = new PBES2($password, $salt, 100000); // Custom iterations
Invalid Key Errors
Performance Issues
microtime(). If slow, reduce iterations or cache decrypted keys (short-lived).Library Conflicts
lucadegasperi/oauth2-server, register the algorithm explicitly:
$server->addEncryptionAlgorithm(new PBES2($password, $salt));
Custom Key Derivation
Extend PBES2 to use Argon2 or bcrypt:
class CustomPBES2 extends PBES2 {
public function deriveKey($password, $salt) {
return hash_pbkdf2('sha512', $password, $salt, 100000, 32, true);
}
}
Key Rotation
Implement a KeyRepository to manage encrypted keys:
class KeyRepository {
public function encryptAndStore($keyData) {
$encrypted = $this->pbes2->encrypt(new ContentEncryptionKey($keyData));
return $this->store($encrypted);
}
}
Logging Log decryption failures (without sensitive data) to detect brute-force attempts:
try {
$decrypted = $pbes2->decrypt($encryptedKey);
} catch (\Exception $e) {
\Log::warning("PBES2 decryption failed for key: " . substr($encryptedKey, 0, 10));
throw $e;
}
$algorithm = new PBES2($password, $salt, 10000, 'sha512');
How can I help you explore Laravel packages today?