From af25c2e01c09c53d6f085f6c24c2f83373f989f7 Mon Sep 17 00:00:00 2001 From: Kelvin Mo Date: Fri, 28 Jan 2022 20:59:39 +1100 Subject: [PATCH] Additional tests --- tests/JWETest.php | 117 ++++++++++++++++++++++++++++++++++++++++++++-- tests/JWTTest.php | 4 +- 2 files changed, 116 insertions(+), 5 deletions(-) diff --git a/tests/JWETest.php b/tests/JWETest.php index 49e0ed1..a01882b 100644 --- a/tests/JWETest.php +++ b/tests/JWETest.php @@ -59,18 +59,63 @@ protected function getDirectKeySet() { } public function testEncryptRSA() { + // From Appendix A.2 of RFC 7516 $plaintext = 'Live long and prosper.'; - $public_set = $this->getPublicKeySet(); - $jwe = new JWE(["alg" => "RSA1_5","enc" => "A128CBC-HS256"], $plaintext); - $token = $jwe->encrypt($public_set); + $stub = $this->getMockBuilder('SimpleJWT\JWE') + ->setConstructorArgs([["alg" => "RSA1_5","enc" => "A128CBC-HS256"], $plaintext]) + ->setMethods(['generateCEK']) + ->setMethods(['generateIV']) + ->getMock(); + $stub->method('generateCEK')->willReturn(base64_decode('BNMfxVSd/P4LZJ36P6pqzmt81C1vawnbyLEA8I+cLM8=')); + $stub->method('generateIV')->willReturn('AxY8DCtDaGlsbGljb3RoZQ'); + + // We cannot directly compare the compact JWE format result, as the RSA1_5 padding + // involves a random string generated by OpenSSL. Therefore we generate the JWE in + // JSON format and compare each component other than the encrypted key. + $token_json = json_decode($stub->encrypt($public_set, null, JWE::JSON_FORMAT), true); + $this->assertEquals('eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0', $token_json['protected']); + $this->assertEquals('KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY', $token_json['ciphertext']); + $this->assertEquals('AxY8DCtDaGlsbGljb3RoZQ', $token_json['iv']); + $this->assertEquals('9hH0vgRfYgPnAHOd8stkvw', $token_json['tag']); + } + + public function testDecryptRSA() { + $plaintext = 'Live long and prosper.'; + + $token = 'eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPhcCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPgwCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.9hH0vgRfYgPnAHOd8stkvw'; $private_set = $this->getPrivateKeySet(); $test_jwe = JWE::decrypt($token, $private_set, 'RSA1_5'); $this->assertEquals($plaintext, $test_jwe->getPlaintext()); } + public function testEncryptAESKW() { + // From Appendix A.3 of RFC 7516 + $plaintext = 'Live long and prosper.'; + $public_set = $this->getPublicKeySet(); + + $stub = $this->getMockBuilder('SimpleJWT\JWE') + ->setConstructorArgs([["alg" => "A128KW","enc" => "A128CBC-HS256"], $plaintext]) + ->setMethods(['generateCEK']) + ->setMethods(['generateIV']) + ->getMock(); + $stub->method('generateCEK')->willReturn(base64_decode('BNMfxVSd/P4LZJ36P6pqzmt81C1vawnbyLEA8I+cLM8=')); + $stub->method('generateIV')->willReturn('AxY8DCtDaGlsbGljb3RoZQ'); + + $token = $stub->encrypt($public_set); + $this->assertEquals('eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.U0m_YmjN04DJvceFICbCVQ', $token); + + $token_json = json_decode($stub->encrypt($public_set, null, JWE::JSON_FORMAT), true); + $this->assertEquals('eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0', $token_json['protected']); + $this->assertEquals('6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ', $token_json['encrypted_key']); + $this->assertEquals('KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY', $token_json['ciphertext']); + $this->assertEquals('AxY8DCtDaGlsbGljb3RoZQ', $token_json['iv']); + $this->assertEquals('U0m_YmjN04DJvceFICbCVQ', $token_json['tag']); + } + public function testDecryptAESKW() { + // From Appendix A.3 of RFC 7516 $plaintext = 'Live long and prosper.'; $token = 'eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.U0m_YmjN04DJvceFICbCVQ'; @@ -127,10 +172,76 @@ public function testDecryptDirectJSON() { $this->assertEquals($plaintext, $test_jwe->getPlaintext()); } + /** + * @expectedException SimpleJWT\InvalidTokenException + */ + public function testEncryptedKeyFailure() { + if (method_exists($this, 'expectException')) { + $this->expectException('SimpleJWT\InvalidTokenException'); + $this->expectExceptionCode(InvalidTokenException::DECRYPTION_ERROR); + } + + $plaintext = 'Live long and prosper.'; + + $token = 'eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOg.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.U0m_YmjN04DJvceFICbCVQ'; + $private_set = $this->getPrivateKeySet(); + $test_jwe = JWE::decrypt($token, $private_set, 'A128KW'); + $this->assertEquals($plaintext, $test_jwe->getPlaintext()); + } + + /** + * @expectedException SimpleJWT\InvalidTokenException + */ + public function testIVFailure() { + if (method_exists($this, 'expectException')) { + $this->expectException('SimpleJWT\InvalidTokenException'); + $this->expectExceptionCode(InvalidTokenException::DECRYPTION_ERROR); + } + + $plaintext = 'Live long and prosper.'; + + $token = 'eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.AxY8DCtDaGlsbGljb3RoZg.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.U0m_YmjN04DJvceFICbCVQ'; + $private_set = $this->getPrivateKeySet(); + $test_jwe = JWE::decrypt($token, $private_set, 'A128KW'); + $this->assertEquals($plaintext, $test_jwe->getPlaintext()); + } + + /** + * @expectedException SimpleJWT\InvalidTokenException + */ + public function testTagFailure() { + if (method_exists($this, 'expectException')) { + $this->expectException('SimpleJWT\InvalidTokenException'); + $this->expectExceptionCode(InvalidTokenException::DECRYPTION_ERROR); + } + + $plaintext = 'Live long and prosper.'; + + $token = 'eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.U0m_YmjN04DJvceFICbCVg'; + $private_set = $this->getPrivateKeySet(); + $test_jwe = JWE::decrypt($token, $private_set, 'A128KW'); + $this->assertEquals($plaintext, $test_jwe->getPlaintext()); + } + + /** + * @expectedException SimpleJWT\InvalidTokenException + */ + public function testCrit() { + if (method_exists($this, 'expectException')) { + $this->expectException('SimpleJWT\InvalidTokenException'); + $this->expectExceptionCode(InvalidTokenException::UNSUPPORTED_ERROR); + } + + $private_set = $this->getPrivateKeySet(); + $token = 'eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiY3JpdCI6WyJ4LXVua25vd24tY3JpdGljYWwiXSwieC11bmtub3duLWNyaXRpY2FsIjp0cnVlfQ.sJFRqh6iiJh2OykXQYQ3GI1NZKC6jDwkc3k9959k6AwIbOMZ41ELjQ.wyDWTBKJiewaNP0YOM8uWQ.obEeoNob7fepPaWGNZqVgh6qEMK9qsIWPQtMf0tI_-U.enkNNlZhspYfLmeWpXA2dg'; + $test_jwe = JWE::decrypt($token, $private_set, 'A128KW'); + } + /** * @expectedException \InvalidArgumentException */ function testInvalidToken() { + if (method_exists($this, 'expectException')) { $this->expectException('\InvalidArgumentException'); } diff --git a/tests/JWTTest.php b/tests/JWTTest.php index fca5ec5..c85e94d 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -320,9 +320,9 @@ function testCrit() { } $set = $this->getPublicKeySet(); - $token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImNyaXQiOlsiaHR0cDovL2V4YW1wbGUuY29tL2lzX3Jvb3QiXX0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.-ZDHC7uzUcCgHJ4s6mMjYBimzUsqg4gWjtusMhK-eaU'; + $token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImNyaXQiOlsieC11bmtub3duLWNyaXRpY2FsIl0sIngtdW5rbm93bi1jcml0aWNhbCI6dHJ1ZX0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODB9.lLajjIbnhRpthOPhbJTaxoQ8JHYSAwSUl1Vxc4eQcIU'; $jwt = JWT::decode($token, $set, 'HS256'); - $this->assertTrue($jwt->getClaim('http://example.com/is_root')); + $this->assertTrue($jwt->getClaim('iss')); } /**