From 3c2d70f2e64e2922345e89f2ceae47d2463faae1 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Thu, 20 May 2021 12:37:02 -0500 Subject: [PATCH] chore: add tests and docs for rsa with passphrase (#335) --- README.md | 34 ++++++++++++++++++++++++++++ src/JWT.php | 16 ++++++------- tests/JWTTest.php | 14 ++++++++++++ tests/rsa-with-passphrase.pem | 42 +++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 tests/rsa-with-passphrase.pem diff --git a/README.md b/README.md index 9f3d0846..66d7d014 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,40 @@ $decoded_array = (array) $decoded; echo "Decode:\n" . print_r($decoded_array, true) . "\n"; ``` +Example with a passphrase +------------------------- + +```php +// Your passphrase +$passphrase = '[YOUR_PASSPHRASE]'; + +// Your private key file with passphrase +// Can be generated with "ssh-keygen -t rsa -m pem" +$privateKeyFile = '/path/to/key-with-passphrase.pem'; + +// Create a private key of type "resource" +$privateKey = openssl_pkey_get_private( + file_get_contents($privateKeyFile), + $passphrase +); + +$payload = array( + "iss" => "example.org", + "aud" => "example.com", + "iat" => 1356999524, + "nbf" => 1357000000 +); + +$jwt = JWT::encode($payload, $privateKey, 'RS256'); +echo "Encode:\n" . print_r($jwt, true) . "\n"; + +// Get public key from the private key, or pull from from a file. +$publicKey = openssl_pkey_get_details($privateKey)['key']; + +$decoded = JWT::decode($jwt, $publicKey, array('RS256')); +echo "Decode:\n" . print_r((array) $decoded, true) . "\n"; +``` + Using JWKs ---------- diff --git a/src/JWT.php b/src/JWT.php index c68d4e15..4b85699f 100644 --- a/src/JWT.php +++ b/src/JWT.php @@ -153,14 +153,14 @@ public static function decode($jwt, $key, array $allowed_algs = array()) /** * Converts and signs a PHP object or array into a JWT string. * - * @param object|array $payload PHP object or array - * @param string $key The secret key. - * If the algorithm used is asymmetric, this is the private key - * @param string $alg The signing algorithm. - * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', - * 'HS512', 'RS256', 'RS384', and 'RS512' - * @param mixed $keyId - * @param array $head An array with header elements to attach + * @param object|array $payload PHP object or array + * @param string|resource $key The secret key. + * If the algorithm used is asymmetric, this is the private key + * @param string $alg The signing algorithm. + * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', + * 'HS512', 'RS256', 'RS384', and 'RS512' + * @param mixed $keyId + * @param array $head An array with header elements to attach * * @return string A signed JWT * diff --git a/tests/JWTTest.php b/tests/JWTTest.php index 46ea7ef0..7c3d9649 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -285,6 +285,20 @@ public function testRSEncodeDecode() $this->assertEquals($decoded, 'abc'); } + public function testRSEncodeDecodeWithPassphrase() + { + $privateKey = openssl_pkey_get_private( + file_get_contents(__DIR__ . '/rsa-with-passphrase.pem'), + 'passphrase' + ); + + $jwt = JWT::encode('abc', $privateKey, 'RS256'); + $keyDetails = openssl_pkey_get_details($privateKey); + $pubKey = $keyDetails['key']; + $decoded = JWT::decode($jwt, $pubKey, array('RS256')); + $this->assertEquals($decoded, 'abc'); + } + /** * @runInSeparateProcess * @dataProvider provideEncodeDecode diff --git a/tests/rsa-with-passphrase.pem b/tests/rsa-with-passphrase.pem new file mode 100644 index 00000000..ad55326f --- /dev/null +++ b/tests/rsa-with-passphrase.pem @@ -0,0 +1,42 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,D8AA4EC8D8B5883F09ACB308FB026C94 + +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 +-----END RSA PRIVATE KEY-----