From 1fe7ca8e80500681bbaea683b44c7acafd694326 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Tue, 2 Jul 2024 18:12:18 +0200 Subject: [PATCH 01/14] Add Base64UrlSafe utility and refactor code references (#576) * Add Base64UrlSafe utility and refactor code references This commit adds the utility `Base64UrlSafe` to provide methods for encoding and decoding in Base64UrlSafe format. Simultaneously, the commit also updates multiple files across the library to use this utility instead of the previously used `ParagonIE\ConstantTime\Base64UrlSafe`. This change will ensure consistent use of this utility throughout the project, promoting maintainability and ease of updating in the future, if required. --- phpstan-baseline.neon | 308 +++++++++++++++++- src/Experimental/KeyEncryption/AESCTR.php | 2 +- .../KeyEncryption/Chacha20Poly1305.php | 2 +- src/Experimental/Signature/Blake2b.php | 2 +- src/Library/Console/GeneratorCommand.php | 2 +- src/Library/Core/JWK.php | 2 +- src/Library/Core/Util/Base64UrlSafe.php | 218 +++++++++++++ src/Library/Core/Util/ECKey.php | 1 - src/Library/Core/Util/RSAKey.php | 1 - .../Algorithm/ContentEncryption/AESCBCHS.php | 2 +- .../Algorithm/ContentEncryption/AESGCM.php | 2 +- .../Algorithm/KeyEncryption/AESGCMKW.php | 2 +- .../Algorithm/KeyEncryption/AESKW.php | 2 +- .../Algorithm/KeyEncryption/AbstractECDH.php | 2 +- .../Algorithm/KeyEncryption/Dir.php | 2 +- .../Algorithm/KeyEncryption/PBES2AESKW.php | 2 +- .../KeyEncryption/Util/ConcatKDF.php | 2 +- src/Library/Encryption/JWEBuilder.php | 2 +- .../Serializer/CompactSerializer.php | 2 +- .../Serializer/JSONFlattenedSerializer.php | 2 +- .../Serializer/JSONGeneralSerializer.php | 2 +- .../KeyManagement/Analyzer/ESKeyAnalyzer.php | 2 +- .../KeyManagement/Analyzer/HSKeyAnalyzer.php | 2 +- .../KeyManagement/Analyzer/OctAnalyzer.php | 2 +- .../KeyManagement/Analyzer/RsaAnalyzer.php | 2 +- .../Analyzer/ZxcvbnKeyAnalyzer.php | 2 +- src/Library/KeyManagement/JWKFactory.php | 2 +- .../KeyManagement/KeyConverter/ECKey.php | 2 +- .../KeyConverter/KeyConverter.php | 2 +- .../KeyManagement/KeyConverter/RSAKey.php | 2 +- src/Library/Signature/Algorithm/EdDSA.php | 2 +- src/Library/Signature/Algorithm/HMAC.php | 2 +- src/Library/Signature/JWSBuilder.php | 2 +- src/Library/Signature/JWSVerifier.php | 2 +- .../Serializer/CompactSerializer.php | 2 +- .../Serializer/JSONFlattenedSerializer.php | 2 +- .../Serializer/JSONGeneralSerializer.php | 2 +- .../KeyManagement/JWKLoaderTest.php | 2 +- .../Console/KeyCreationCommandTest.php | 2 +- tests/Component/Encryption/EncrypterTest.php | 2 +- .../Component/Encryption/JWEFlattenedTest.php | 2 +- ...8GCMEncryptionProtectedContentOnlyTest.php | 2 +- .../A128KWAndA128GCMEncryptionTest.php | 2 +- ...ionWithAdditionalAuthenticatedDataTest.php | 2 +- ...ndA128GCMEncryptionWithCompressionTest.php | 2 +- ...nWithSpecificProtectedHeaderValuesTest.php | 2 +- ...256GCMKWAndA128CBC_HS256EncryptionTest.php | 2 +- .../RFC7520/DirAndA128GCMEncryptionTest.php | 2 +- ...ECDH_ES_A128KWAndA128GCMEncryptionTest.php | 2 +- ...ECDH_ES_AndA128CBC_HS256EncryptionTest.php | 2 +- .../MultipleRecipientEncryptionTest.php | 2 +- ...2_A256KWAndA128CBC_HS256EncryptionTest.php | 2 +- .../RSA1_5AndA128CBC_HS256EncryptionTest.php | 2 +- .../RSA_OAEPAndA256GCMEncryptionTest.php | 2 +- .../Encryption/RSAKeyEncryptionTest.php | 2 +- .../KeyManagement/JWKFactoryTest.php | 2 +- tests/Component/KeyManagement/JWKTest.php | 2 +- tests/Component/Signature/JWSTest.php | 2 +- tests/Component/Signature/SignerTest.php | 2 +- .../AESCBC/AESCBC_HSContentEncryptionTest.php | 2 +- .../AESGCM/AESGCMContentEncryptionTest.php | 2 +- .../AESGCMKW/AESGCMKWKeyEncryptionTest.php | 2 +- .../AESKW/AESKWKeyEncryptionTest.php | 2 +- .../KeyEncryption/Direct/DirAlgorithmTest.php | 2 +- .../ECDHES/ECDHESKeyAgreementTest.php | 2 +- .../PBES2/PBES2_HS_AESKWKeyEncryptionTest.php | 2 +- .../ECDSA/ECDSAFromRFC6979Test.php | 2 +- .../ECDSA/ECDSASignatureTest.php | 2 +- .../EdDSA/EdDSASignatureTest.php | 2 +- .../Experimental/Blake2bTest.php | 2 +- .../Experimental/P256KSignatureTest.php | 2 +- .../HMAC/HMACSignatureTest.php | 2 +- .../RSA/RSASignatureTest.php | 2 +- 73 files changed, 581 insertions(+), 85 deletions(-) create mode 100644 src/Library/Core/Util/Base64UrlSafe.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index adbac08c1..771344500 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1006,11 +1006,6 @@ parameters: count: 1 path: src/Bundle/Serializer/JWESerializer.php - - - message: "#^Method Jose\\\\Bundle\\\\JoseFramework\\\\Serializer\\\\JWESerializer\\:\\:getSupportedTypes\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/Bundle/Serializer/JWESerializer.php - - message: "#^Method Jose\\\\Bundle\\\\JoseFramework\\\\Serializer\\\\JWESerializer\\:\\:supportsDenormalization\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#" count: 1 @@ -1046,11 +1041,6 @@ parameters: count: 1 path: src/Bundle/Serializer/JWSSerializer.php - - - message: "#^Method Jose\\\\Bundle\\\\JoseFramework\\\\Serializer\\\\JWSSerializer\\:\\:getSupportedTypes\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/Bundle/Serializer/JWSSerializer.php - - message: "#^Method Jose\\\\Bundle\\\\JoseFramework\\\\Serializer\\\\JWSSerializer\\:\\:supportsDenormalization\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#" count: 1 @@ -1288,16 +1278,86 @@ parameters: count: 1 path: src/Library/Checker/IssuerChecker.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\AddKeyIntoKeysetCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/AddKeyIntoKeysetCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\AddKeyIntoKeysetCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/AddKeyIntoKeysetCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\EcKeyGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/EcKeyGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\EcKeyGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/EcKeyGeneratorCommand.php + - message: "#^Cannot cast mixed to int\\.$#" count: 1 path: src/Library/Console/EcKeysetGeneratorCommand.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\EcKeysetGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/EcKeysetGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\EcKeysetGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/EcKeysetGeneratorCommand.php + - message: "#^Method Jose\\\\Component\\\\Console\\\\GeneratorCommand\\:\\:getOptions\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: src/Library/Console/GeneratorCommand.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\GetThumbprintCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/GetThumbprintCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\GetThumbprintCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/GetThumbprintCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\JKULoaderCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/JKULoaderCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\JKULoaderCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/JKULoaderCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\KeyAnalyzerCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/KeyAnalyzerCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\KeyAnalyzerCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/KeyAnalyzerCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\KeyFileLoaderCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/KeyFileLoaderCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\KeyFileLoaderCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/KeyFileLoaderCommand.php + - message: "#^Parameter \\#1 \\$jwk of method Jose\\\\Component\\\\KeyManagement\\\\Analyzer\\\\KeyAnalyzerManager\\:\\:analyze\\(\\) expects Jose\\\\Component\\\\Core\\\\JWK, mixed given\\.$#" count: 1 @@ -1308,31 +1368,211 @@ parameters: count: 1 path: src/Library/Console/KeysetAnalyzerCommand.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\KeysetAnalyzerCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/KeysetAnalyzerCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\KeysetAnalyzerCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/KeysetAnalyzerCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\MergeKeysetCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/MergeKeysetCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\MergeKeysetCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/MergeKeysetCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\NoneKeyGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/NoneKeyGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\NoneKeyGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/NoneKeyGeneratorCommand.php + - message: "#^Cannot cast mixed to int\\.$#" count: 1 path: src/Library/Console/OctKeyGeneratorCommand.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OctKeyGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/OctKeyGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OctKeyGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/OctKeyGeneratorCommand.php + - message: "#^Cannot cast mixed to int\\.$#" count: 2 path: src/Library/Console/OctKeysetGeneratorCommand.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OctKeysetGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/OctKeysetGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OctKeysetGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/OctKeysetGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OkpKeyGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/OkpKeyGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OkpKeyGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/OkpKeyGeneratorCommand.php + - message: "#^Cannot cast mixed to int\\.$#" count: 1 path: src/Library/Console/OkpKeysetGeneratorCommand.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OkpKeysetGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/OkpKeysetGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OkpKeysetGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/OkpKeysetGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OptimizeRsaKeyCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/OptimizeRsaKeyCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\OptimizeRsaKeyCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/OptimizeRsaKeyCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\P12CertificateLoaderCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/P12CertificateLoaderCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\P12CertificateLoaderCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/P12CertificateLoaderCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\PemConverterCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/PemConverterCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\PemConverterCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/PemConverterCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\PublicKeyCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/PublicKeyCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\PublicKeyCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/PublicKeyCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\PublicKeysetCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/PublicKeysetCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\PublicKeysetCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/PublicKeysetCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\RotateKeysetCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/RotateKeysetCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\RotateKeysetCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/RotateKeysetCommand.php + - message: "#^Cannot cast mixed to int\\.$#" count: 1 path: src/Library/Console/RsaKeyGeneratorCommand.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\RsaKeyGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/RsaKeyGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\RsaKeyGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/RsaKeyGeneratorCommand.php + - message: "#^Cannot cast mixed to int\\.$#" count: 2 path: src/Library/Console/RsaKeysetGeneratorCommand.php + - + message: "#^Property Jose\\\\Component\\\\Console\\\\RsaKeysetGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/RsaKeysetGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\RsaKeysetGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/RsaKeysetGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\SecretKeyGeneratorCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/SecretKeyGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\SecretKeyGeneratorCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/SecretKeyGeneratorCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\X509CertificateLoaderCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/X509CertificateLoaderCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\X509CertificateLoaderCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/X509CertificateLoaderCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\X5ULoaderCommand\\:\\:\\$defaultDescription has no type specified\\.$#" + count: 1 + path: src/Library/Console/X5ULoaderCommand.php + + - + message: "#^Property Jose\\\\Component\\\\Console\\\\X5ULoaderCommand\\:\\:\\$defaultName has no type specified\\.$#" + count: 1 + path: src/Library/Console/X5ULoaderCommand.php + - message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" count: 1 @@ -1413,11 +1653,51 @@ parameters: count: 1 path: src/Library/Core/JWKSet.php + - + message: "#^Parameter \\#2 \\$mode of function count expects 0\\|1, int given\\.$#" + count: 1 + path: src/Library/Core/JWKSet.php + - message: "#^Property Jose\\\\Component\\\\Core\\\\JWKSet\\:\\:\\$keys type has no value type specified in iterable type array\\.$#" count: 1 path: src/Library/Core/JWKSet.php + - + message: "#^Comparison operation \"\\>\" between 0 and 1 is always false\\.$#" + count: 1 + path: src/Library/Core/Util/Base64UrlSafe.php + + - + message: "#^Instantiated class Jose\\\\Component\\\\Core\\\\Util\\\\InvalidArgumentException not found\\.$#" + count: 2 + path: src/Library/Core/Util/Base64UrlSafe.php + + - + message: "#^Instantiated class Jose\\\\Component\\\\Core\\\\Util\\\\RangeException not found\\.$#" + count: 3 + path: src/Library/Core/Util/Base64UrlSafe.php + + - + message: "#^Method Jose\\\\Component\\\\Core\\\\Util\\\\Base64UrlSafe\\:\\:safeSubstr\\(\\) has parameter \\$length with no type specified\\.$#" + count: 1 + path: src/Library/Core/Util/Base64UrlSafe.php + + - + message: "#^Throwing object of an unknown class Jose\\\\Component\\\\Core\\\\Util\\\\InvalidArgumentException\\.$#" + count: 2 + path: src/Library/Core/Util/Base64UrlSafe.php + + - + message: "#^Throwing object of an unknown class Jose\\\\Component\\\\Core\\\\Util\\\\RangeException\\.$#" + count: 3 + path: src/Library/Core/Util/Base64UrlSafe.php + + - + message: "#^Variable \\$i might not be defined\\.$#" + count: 2 + path: src/Library/Core/Util/Base64UrlSafe.php + - message: "#^Method Jose\\\\Component\\\\Core\\\\Util\\\\ECKey\\:\\:createECKey\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" count: 1 @@ -1789,7 +2069,7 @@ parameters: path: src/Library/Encryption/Serializer/JSONFlattenedSerializer.php - - message: "#^Parameter \\#1 \\$encodedString of static method ParagonIE\\\\ConstantTime\\\\Base64\\:\\:decodeNoPadding\\(\\) expects string, mixed given\\.$#" + message: "#^Parameter \\#1 \\$encodedString of static method Jose\\\\Component\\\\Core\\\\Util\\\\Base64UrlSafe\\:\\:decodeNoPadding\\(\\) expects string, mixed given\\.$#" count: 3 path: src/Library/Encryption/Serializer/JSONFlattenedSerializer.php @@ -1819,7 +2099,7 @@ parameters: path: src/Library/Encryption/Serializer/JSONGeneralSerializer.php - - message: "#^Parameter \\#1 \\$encodedString of static method ParagonIE\\\\ConstantTime\\\\Base64\\:\\:decodeNoPadding\\(\\) expects string, mixed given\\.$#" + message: "#^Parameter \\#1 \\$encodedString of static method Jose\\\\Component\\\\Core\\\\Util\\\\Base64UrlSafe\\:\\:decodeNoPadding\\(\\) expects string, mixed given\\.$#" count: 3 path: src/Library/Encryption/Serializer/JSONGeneralSerializer.php @@ -2149,7 +2429,7 @@ parameters: path: src/Library/Signature/Serializer/CompactSerializer.php - - message: "#^Parameter \\#1 \\$encodedString of static method ParagonIE\\\\ConstantTime\\\\Base64\\:\\:decodeNoPadding\\(\\) expects string, mixed given\\.$#" + message: "#^Parameter \\#1 \\$encodedString of static method Jose\\\\Component\\\\Core\\\\Util\\\\Base64UrlSafe\\:\\:decodeNoPadding\\(\\) expects string, mixed given\\.$#" count: 1 path: src/Library/Signature/Serializer/JSONFlattenedSerializer.php @@ -2174,7 +2454,7 @@ parameters: path: src/Library/Signature/Serializer/JSONGeneralSerializer.php - - message: "#^Parameter \\#1 \\$encodedString of static method ParagonIE\\\\ConstantTime\\\\Base64\\:\\:decodeNoPadding\\(\\) expects string, mixed given\\.$#" + message: "#^Parameter \\#1 \\$encodedString of static method Jose\\\\Component\\\\Core\\\\Util\\\\Base64UrlSafe\\:\\:decodeNoPadding\\(\\) expects string, mixed given\\.$#" count: 1 path: src/Library/Signature/Serializer/JSONGeneralSerializer.php diff --git a/src/Experimental/KeyEncryption/AESCTR.php b/src/Experimental/KeyEncryption/AESCTR.php index 76fd00f07..50b3cde76 100644 --- a/src/Experimental/KeyEncryption/AESCTR.php +++ b/src/Experimental/KeyEncryption/AESCTR.php @@ -6,8 +6,8 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\KeyEncryption\KeyEncryption; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function in_array; use function is_string; diff --git a/src/Experimental/KeyEncryption/Chacha20Poly1305.php b/src/Experimental/KeyEncryption/Chacha20Poly1305.php index 947a7c834..3dc610642 100644 --- a/src/Experimental/KeyEncryption/Chacha20Poly1305.php +++ b/src/Experimental/KeyEncryption/Chacha20Poly1305.php @@ -6,9 +6,9 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\KeyEncryption\KeyEncryption; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function in_array; use function is_string; diff --git a/src/Experimental/Signature/Blake2b.php b/src/Experimental/Signature/Blake2b.php index 73cd75792..d268a02cf 100644 --- a/src/Experimental/Signature/Blake2b.php +++ b/src/Experimental/Signature/Blake2b.php @@ -6,8 +6,8 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Signature\Algorithm\MacAlgorithm; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function extension_loaded; use function in_array; diff --git a/src/Library/Console/GeneratorCommand.php b/src/Library/Console/GeneratorCommand.php index 8f4f58cb4..daf7230b3 100644 --- a/src/Library/Console/GeneratorCommand.php +++ b/src/Library/Console/GeneratorCommand.php @@ -5,8 +5,8 @@ namespace Jose\Component\Console; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\KeyManagement\JWKFactory; -use ParagonIE\ConstantTime\Base64UrlSafe; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use function is_bool; diff --git a/src/Library/Core/JWK.php b/src/Library/Core/JWK.php index 9685becf5..27b4bf309 100644 --- a/src/Library/Core/JWK.php +++ b/src/Library/Core/JWK.php @@ -5,8 +5,8 @@ namespace Jose\Component\Core; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use JsonSerializable; -use ParagonIE\ConstantTime\Base64UrlSafe; use function array_key_exists; use function in_array; use function is_array; diff --git a/src/Library/Core/Util/Base64UrlSafe.php b/src/Library/Core/Util/Base64UrlSafe.php new file mode 100644 index 000000000..d7863ad3a --- /dev/null +++ b/src/Library/Core/Util/Base64UrlSafe.php @@ -0,0 +1,218 @@ + $chunk */ + $chunk = unpack('C*', self::safeSubstr($encodedString, $i, 4)); + $c0 = static::decode6Bits($chunk[1]); + $c1 = static::decode6Bits($chunk[2]); + $c2 = static::decode6Bits($chunk[3]); + $c3 = static::decode6Bits($chunk[4]); + + $dest .= pack( + 'CCC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff), + ((($c2 << 6) | $c3) & 0xff) + ); + $err |= ($c0 | $c1 | $c2 | $c3) >> 8; + } + + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', self::safeSubstr($encodedString, $i, $srcLen - $i)); + $c0 = static::decode6Bits($chunk[1]); + + if ($i + 2 < $srcLen) { + $c1 = static::decode6Bits($chunk[2]); + $c2 = static::decode6Bits($chunk[3]); + $dest .= pack('CC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff)); + $err |= ($c0 | $c1 | $c2) >> 8; + if ($strictPadding) { + $err |= ($c2 << 6) & 0xff; + } + } elseif ($i + 1 < $srcLen) { + $c1 = static::decode6Bits($chunk[2]); + $dest .= pack('C', ((($c0 << 2) | ($c1 >> 4)) & 0xff)); + $err |= ($c0 | $c1) >> 8; + if ($strictPadding) { + $err |= ($c1 << 4) & 0xff; + } + } elseif ($strictPadding) { + $err |= 1; + } + } + $check = ($err === 0); + if (! $check) { + throw new RangeException('Base64::decode() only expects characters in the correct base64 alphabet'); + } + return $dest; + } + + public static function decodeNoPadding(string $encodedString): string + { + $srcLen = self::safeStrlen($encodedString); + if ($srcLen === 0) { + return ''; + } + if (($srcLen & 3) === 0) { + if ($encodedString[$srcLen - 1] === '=') { + throw new InvalidArgumentException("decodeNoPadding() doesn't tolerate padding"); + } + if (($srcLen & 3) > 1) { + if ($encodedString[$srcLen - 2] === '=') { + throw new InvalidArgumentException("decodeNoPadding() doesn't tolerate padding"); + } + } + } + return static::decode($encodedString, true); + } + + private static function doEncode(string $src, bool $pad = true): string + { + $dest = ''; + $srcLen = self::safeStrlen($src); + for ($i = 0; $i + 3 <= $srcLen; $i += 3) { + /** @var array $chunk */ + $chunk = unpack('C*', self::safeSubstr($src, $i, 3)); + $b0 = $chunk[1]; + $b1 = $chunk[2]; + $b2 = $chunk[3]; + + $dest .= + static::encode6Bits($b0 >> 2) . + static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + static::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . + static::encode6Bits($b2 & 63); + } + + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', self::safeSubstr($src, $i, $srcLen - $i)); + $b0 = $chunk[1]; + if ($i + 1 < $srcLen) { + $b1 = $chunk[2]; + $dest .= + static::encode6Bits($b0 >> 2) . + static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + static::encode6Bits(($b1 << 2) & 63); + if ($pad) { + $dest .= '='; + } + } else { + $dest .= + static::encode6Bits($b0 >> 2) . + static::encode6Bits(($b0 << 4) & 63); + if ($pad) { + $dest .= '=='; + } + } + } + return $dest; + } + + private static function decode6Bits(int $src): int + { + $ret = -1; + $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); + $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); + $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); + $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63; + + return $ret + ((((0x5e - $src) & ($src - 0x60)) >> 8) & 64); + } + + private static function encode6Bits(int $src): string + { + $diff = 0x41; + $diff += ((25 - $src) >> 8) & 6; + $diff -= ((51 - $src) >> 8) & 75; + $diff -= ((61 - $src) >> 8) & 13; + $diff += ((62 - $src) >> 8) & 49; + + return pack('C', $src + $diff); + } + + private static function safeStrlen(string $str): int + { + return mb_strlen($str, '8bit'); + } + + private static function safeSubstr(string $str, int $start = 0, $length = null): string + { + if ($length === 0) { + return ''; + } + return mb_substr($str, $start, $length, '8bit'); + } +} diff --git a/src/Library/Core/Util/ECKey.php b/src/Library/Core/Util/ECKey.php index aa4aac88c..f84123acc 100644 --- a/src/Library/Core/Util/ECKey.php +++ b/src/Library/Core/Util/ECKey.php @@ -6,7 +6,6 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function extension_loaded; use function is_array; diff --git a/src/Library/Core/Util/RSAKey.php b/src/Library/Core/Util/RSAKey.php index 7b47d5cc5..c28fe661e 100644 --- a/src/Library/Core/Util/RSAKey.php +++ b/src/Library/Core/Util/RSAKey.php @@ -6,7 +6,6 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence; use SpomkyLabs\Pki\ASN1\Type\Primitive\BitString; diff --git a/src/Library/Encryption/Algorithm/ContentEncryption/AESCBCHS.php b/src/Library/Encryption/Algorithm/ContentEncryption/AESCBCHS.php index 8395db17e..20395fa08 100644 --- a/src/Library/Encryption/Algorithm/ContentEncryption/AESCBCHS.php +++ b/src/Library/Encryption/Algorithm/ContentEncryption/AESCBCHS.php @@ -4,8 +4,8 @@ namespace Jose\Component\Encryption\Algorithm\ContentEncryption; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\ContentEncryptionAlgorithm; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function extension_loaded; use const OPENSSL_RAW_DATA; diff --git a/src/Library/Encryption/Algorithm/ContentEncryption/AESGCM.php b/src/Library/Encryption/Algorithm/ContentEncryption/AESGCM.php index c939df464..0b1bf43f8 100644 --- a/src/Library/Encryption/Algorithm/ContentEncryption/AESGCM.php +++ b/src/Library/Encryption/Algorithm/ContentEncryption/AESGCM.php @@ -4,8 +4,8 @@ namespace Jose\Component\Encryption\Algorithm\ContentEncryption; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\ContentEncryptionAlgorithm; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function extension_loaded; use const OPENSSL_RAW_DATA; diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/AESGCMKW.php b/src/Library/Encryption/Algorithm/KeyEncryption/AESGCMKW.php index 82db172ca..37c79d9f0 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/AESGCMKW.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/AESGCMKW.php @@ -7,7 +7,7 @@ use AESKW\Wrapper as WrapperInterface; use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use RuntimeException; use function extension_loaded; use function in_array; diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/AESKW.php b/src/Library/Encryption/Algorithm/KeyEncryption/AESKW.php index 909f2a1e1..15c408acc 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/AESKW.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/AESKW.php @@ -7,7 +7,7 @@ use AESKW\Wrapper as WrapperInterface; use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use RuntimeException; use function in_array; use function is_string; diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/AbstractECDH.php b/src/Library/Encryption/Algorithm/KeyEncryption/AbstractECDH.php index 9027a8e74..1af2818fd 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/AbstractECDH.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/AbstractECDH.php @@ -7,13 +7,13 @@ use Brick\Math\BigInteger; use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\Ecc\Curve; use Jose\Component\Core\Util\Ecc\EcDH; use Jose\Component\Core\Util\Ecc\NistCurve; use Jose\Component\Core\Util\Ecc\PrivateKey; use Jose\Component\Core\Util\ECKey; use Jose\Component\Encryption\Algorithm\KeyEncryption\Util\ConcatKDF; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use Throwable; use function array_key_exists; diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/Dir.php b/src/Library/Encryption/Algorithm/KeyEncryption/Dir.php index d01ec4921..b4e2211a3 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/Dir.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/Dir.php @@ -6,7 +6,7 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use function in_array; use function is_string; diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php b/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php index a8222fc65..a93f9ee97 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php @@ -10,7 +10,7 @@ use AESKW\Wrapper as WrapperInterface; use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use RuntimeException; use function in_array; use function is_int; diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/Util/ConcatKDF.php b/src/Library/Encryption/Algorithm/KeyEncryption/Util/ConcatKDF.php index f753b6cc3..96e98e100 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/Util/ConcatKDF.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/Util/ConcatKDF.php @@ -5,7 +5,7 @@ namespace Jose\Component\Encryption\Algorithm\KeyEncryption\Util; use InvalidArgumentException; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use const STR_PAD_LEFT; /** diff --git a/src/Library/Encryption/JWEBuilder.php b/src/Library/Encryption/JWEBuilder.php index f4e18bbdd..505ae6672 100644 --- a/src/Library/Encryption/JWEBuilder.php +++ b/src/Library/Encryption/JWEBuilder.php @@ -7,6 +7,7 @@ use InvalidArgumentException; use Jose\Component\Core\AlgorithmManager; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\JsonConverter; use Jose\Component\Core\Util\KeyChecker; use Jose\Component\Encryption\Algorithm\ContentEncryptionAlgorithm; @@ -19,7 +20,6 @@ use Jose\Component\Encryption\Compression\CompressionMethod; use Jose\Component\Encryption\Compression\CompressionMethodManager; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function array_key_exists; use function count; diff --git a/src/Library/Encryption/Serializer/CompactSerializer.php b/src/Library/Encryption/Serializer/CompactSerializer.php index ba015e8a1..4c38ff39b 100644 --- a/src/Library/Encryption/Serializer/CompactSerializer.php +++ b/src/Library/Encryption/Serializer/CompactSerializer.php @@ -5,11 +5,11 @@ namespace Jose\Component\Encryption\Serializer; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\JsonConverter; use Jose\Component\Encryption\JWE; use Jose\Component\Encryption\Recipient; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use Throwable; use function count; use function is_array; diff --git a/src/Library/Encryption/Serializer/JSONFlattenedSerializer.php b/src/Library/Encryption/Serializer/JSONFlattenedSerializer.php index 6ecf28e3e..02ea352ee 100644 --- a/src/Library/Encryption/Serializer/JSONFlattenedSerializer.php +++ b/src/Library/Encryption/Serializer/JSONFlattenedSerializer.php @@ -5,10 +5,10 @@ namespace Jose\Component\Encryption\Serializer; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\JsonConverter; use Jose\Component\Encryption\JWE; use Jose\Component\Encryption\Recipient; -use ParagonIE\ConstantTime\Base64UrlSafe; use function array_key_exists; use function count; use function is_array; diff --git a/src/Library/Encryption/Serializer/JSONGeneralSerializer.php b/src/Library/Encryption/Serializer/JSONGeneralSerializer.php index 96f23dc0a..15b963a34 100644 --- a/src/Library/Encryption/Serializer/JSONGeneralSerializer.php +++ b/src/Library/Encryption/Serializer/JSONGeneralSerializer.php @@ -5,11 +5,11 @@ namespace Jose\Component\Encryption\Serializer; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\JsonConverter; use Jose\Component\Encryption\JWE; use Jose\Component\Encryption\Recipient; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use function array_key_exists; use function count; use function is_array; diff --git a/src/Library/KeyManagement/Analyzer/ESKeyAnalyzer.php b/src/Library/KeyManagement/Analyzer/ESKeyAnalyzer.php index 2c0038618..081a6b292 100644 --- a/src/Library/KeyManagement/Analyzer/ESKeyAnalyzer.php +++ b/src/Library/KeyManagement/Analyzer/ESKeyAnalyzer.php @@ -6,8 +6,8 @@ use Brick\Math\BigInteger; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\Ecc\Curve; -use ParagonIE\ConstantTime\Base64UrlSafe; use function is_string; abstract class ESKeyAnalyzer implements KeyAnalyzer diff --git a/src/Library/KeyManagement/Analyzer/HSKeyAnalyzer.php b/src/Library/KeyManagement/Analyzer/HSKeyAnalyzer.php index 0e283a5a0..35b7157c7 100644 --- a/src/Library/KeyManagement/Analyzer/HSKeyAnalyzer.php +++ b/src/Library/KeyManagement/Analyzer/HSKeyAnalyzer.php @@ -5,7 +5,7 @@ namespace Jose\Component\KeyManagement\Analyzer; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use function is_string; abstract class HSKeyAnalyzer implements KeyAnalyzer diff --git a/src/Library/KeyManagement/Analyzer/OctAnalyzer.php b/src/Library/KeyManagement/Analyzer/OctAnalyzer.php index 240517933..1d7691065 100644 --- a/src/Library/KeyManagement/Analyzer/OctAnalyzer.php +++ b/src/Library/KeyManagement/Analyzer/OctAnalyzer.php @@ -5,7 +5,7 @@ namespace Jose\Component\KeyManagement\Analyzer; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use function is_string; final class OctAnalyzer implements KeyAnalyzer diff --git a/src/Library/KeyManagement/Analyzer/RsaAnalyzer.php b/src/Library/KeyManagement/Analyzer/RsaAnalyzer.php index 43f0b1f58..9a354c7e0 100644 --- a/src/Library/KeyManagement/Analyzer/RsaAnalyzer.php +++ b/src/Library/KeyManagement/Analyzer/RsaAnalyzer.php @@ -6,7 +6,7 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use function is_array; use function is_string; diff --git a/src/Library/KeyManagement/Analyzer/ZxcvbnKeyAnalyzer.php b/src/Library/KeyManagement/Analyzer/ZxcvbnKeyAnalyzer.php index 2f5ccb9ab..43a75fa19 100644 --- a/src/Library/KeyManagement/Analyzer/ZxcvbnKeyAnalyzer.php +++ b/src/Library/KeyManagement/Analyzer/ZxcvbnKeyAnalyzer.php @@ -5,7 +5,7 @@ namespace Jose\Component\KeyManagement\Analyzer; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use Throwable; use ZxcvbnPhp\Zxcvbn; use function is_string; diff --git a/src/Library/KeyManagement/JWKFactory.php b/src/Library/KeyManagement/JWKFactory.php index bf42b0277..1bf4ac45c 100644 --- a/src/Library/KeyManagement/JWKFactory.php +++ b/src/Library/KeyManagement/JWKFactory.php @@ -7,11 +7,11 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; use Jose\Component\Core\JWKSet; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\ECKey; use Jose\Component\KeyManagement\KeyConverter\KeyConverter; use Jose\Component\KeyManagement\KeyConverter\RSAKey; use OpenSSLCertificate; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use Throwable; use function array_key_exists; diff --git a/src/Library/KeyManagement/KeyConverter/ECKey.php b/src/Library/KeyManagement/KeyConverter/ECKey.php index 8ee1bfad4..6c3f61a73 100644 --- a/src/Library/KeyManagement/KeyConverter/ECKey.php +++ b/src/Library/KeyManagement/KeyConverter/ECKey.php @@ -5,7 +5,7 @@ namespace Jose\Component\KeyManagement\KeyConverter; use InvalidArgumentException; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use SpomkyLabs\Pki\CryptoEncoding\PEM; use SpomkyLabs\Pki\CryptoTypes\Asymmetric\EC\ECPrivateKey; use SpomkyLabs\Pki\CryptoTypes\Asymmetric\EC\ECPublicKey; diff --git a/src/Library/KeyManagement/KeyConverter/KeyConverter.php b/src/Library/KeyManagement/KeyConverter/KeyConverter.php index 4c8d938b7..f72c66b49 100644 --- a/src/Library/KeyManagement/KeyConverter/KeyConverter.php +++ b/src/Library/KeyManagement/KeyConverter/KeyConverter.php @@ -6,8 +6,8 @@ use Brick\Math\BigInteger; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use OpenSSLCertificate; -use ParagonIE\ConstantTime\Base64UrlSafe; use ParagonIE\Sodium\Core\Ed25519; use RuntimeException; use SpomkyLabs\Pki\CryptoEncoding\PEM; diff --git a/src/Library/KeyManagement/KeyConverter/RSAKey.php b/src/Library/KeyManagement/KeyConverter/RSAKey.php index ff98ea376..fe48e87dd 100644 --- a/src/Library/KeyManagement/KeyConverter/RSAKey.php +++ b/src/Library/KeyManagement/KeyConverter/RSAKey.php @@ -6,8 +6,8 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\BigInteger; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function array_key_exists; use function extension_loaded; diff --git a/src/Library/Signature/Algorithm/EdDSA.php b/src/Library/Signature/Algorithm/EdDSA.php index 6d59ce4d4..cd09113e3 100644 --- a/src/Library/Signature/Algorithm/EdDSA.php +++ b/src/Library/Signature/Algorithm/EdDSA.php @@ -6,7 +6,7 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use ParagonIE\Sodium\Core\Ed25519; use RuntimeException; use function assert; diff --git a/src/Library/Signature/Algorithm/HMAC.php b/src/Library/Signature/Algorithm/HMAC.php index badda9871..92436b007 100644 --- a/src/Library/Signature/Algorithm/HMAC.php +++ b/src/Library/Signature/Algorithm/HMAC.php @@ -6,7 +6,7 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use function in_array; use function is_string; diff --git a/src/Library/Signature/JWSBuilder.php b/src/Library/Signature/JWSBuilder.php index 84201cc6c..3c1a1661d 100644 --- a/src/Library/Signature/JWSBuilder.php +++ b/src/Library/Signature/JWSBuilder.php @@ -8,12 +8,12 @@ use Jose\Component\Core\Algorithm; use Jose\Component\Core\AlgorithmManager; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\JsonConverter; use Jose\Component\Core\Util\KeyChecker; use Jose\Component\Signature\Algorithm\MacAlgorithm; use Jose\Component\Signature\Algorithm\SignatureAlgorithm; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use RuntimeException; use function array_key_exists; use function count; diff --git a/src/Library/Signature/JWSVerifier.php b/src/Library/Signature/JWSVerifier.php index 187d24d80..1944c4ddf 100644 --- a/src/Library/Signature/JWSVerifier.php +++ b/src/Library/Signature/JWSVerifier.php @@ -9,10 +9,10 @@ use Jose\Component\Core\AlgorithmManager; use Jose\Component\Core\JWK; use Jose\Component\Core\JWKSet; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\KeyChecker; use Jose\Component\Signature\Algorithm\MacAlgorithm; use Jose\Component\Signature\Algorithm\SignatureAlgorithm; -use ParagonIE\ConstantTime\Base64UrlSafe; use Throwable; class JWSVerifier diff --git a/src/Library/Signature/Serializer/CompactSerializer.php b/src/Library/Signature/Serializer/CompactSerializer.php index 3a657a147..03a9c0d78 100644 --- a/src/Library/Signature/Serializer/CompactSerializer.php +++ b/src/Library/Signature/Serializer/CompactSerializer.php @@ -5,10 +5,10 @@ namespace Jose\Component\Signature\Serializer; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\JsonConverter; use Jose\Component\Signature\JWS; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use Throwable; use function count; use function is_array; diff --git a/src/Library/Signature/Serializer/JSONFlattenedSerializer.php b/src/Library/Signature/Serializer/JSONFlattenedSerializer.php index 1a8b4cb00..93dae92c3 100644 --- a/src/Library/Signature/Serializer/JSONFlattenedSerializer.php +++ b/src/Library/Signature/Serializer/JSONFlattenedSerializer.php @@ -5,9 +5,9 @@ namespace Jose\Component\Signature\Serializer; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\JsonConverter; use Jose\Component\Signature\JWS; -use ParagonIE\ConstantTime\Base64UrlSafe; use function count; use function is_array; diff --git a/src/Library/Signature/Serializer/JSONGeneralSerializer.php b/src/Library/Signature/Serializer/JSONGeneralSerializer.php index 1905e645e..43acd0e0a 100644 --- a/src/Library/Signature/Serializer/JSONGeneralSerializer.php +++ b/src/Library/Signature/Serializer/JSONGeneralSerializer.php @@ -5,10 +5,10 @@ namespace Jose\Component\Signature\Serializer; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\JsonConverter; use Jose\Component\Signature\JWS; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use function array_key_exists; use function count; use function is_array; diff --git a/tests/Bundle/JoseFramework/Functional/KeyManagement/JWKLoaderTest.php b/tests/Bundle/JoseFramework/Functional/KeyManagement/JWKLoaderTest.php index 88774a89b..5d9445bbe 100644 --- a/tests/Bundle/JoseFramework/Functional/KeyManagement/JWKLoaderTest.php +++ b/tests/Bundle/JoseFramework/Functional/KeyManagement/JWKLoaderTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Bundle\JoseFramework\Functional\KeyManagement; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\KeyManagement\JWKFactory; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\DependencyInjection\ContainerInterface; diff --git a/tests/Component/Console/KeyCreationCommandTest.php b/tests/Component/Console/KeyCreationCommandTest.php index 3dc3b4251..fb6ecfc1f 100644 --- a/tests/Component/Console/KeyCreationCommandTest.php +++ b/tests/Component/Console/KeyCreationCommandTest.php @@ -12,7 +12,7 @@ use Jose\Component\Console\RsaKeyGeneratorCommand; use Jose\Component\Console\SecretKeyGeneratorCommand; use Jose\Component\Core\JWK; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/Component/Encryption/EncrypterTest.php b/tests/Component/Encryption/EncrypterTest.php index 368723ddf..b7030e7cf 100644 --- a/tests/Component/Encryption/EncrypterTest.php +++ b/tests/Component/Encryption/EncrypterTest.php @@ -7,7 +7,7 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; use Jose\Component\Core\JWKSet; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use const JSON_THROW_ON_ERROR; diff --git a/tests/Component/Encryption/JWEFlattenedTest.php b/tests/Component/Encryption/JWEFlattenedTest.php index c21c45909..f3dc4ad68 100644 --- a/tests/Component/Encryption/JWEFlattenedTest.php +++ b/tests/Component/Encryption/JWEFlattenedTest.php @@ -5,7 +5,7 @@ namespace Jose\Tests\Component\Encryption; use Jose\Component\Core\JWKSet; -use ParagonIE\ConstantTime\Base64UrlSafe; +use Jose\Component\Core\Util\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionProtectedContentOnlyTest.php b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionProtectedContentOnlyTest.php index ef018f35f..9ec432be0 100644 --- a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionProtectedContentOnlyTest.php +++ b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionProtectedContentOnlyTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionTest.php b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionTest.php index e8e5d5894..5cb4ecf29 100644 --- a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithAdditionalAuthenticatedDataTest.php b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithAdditionalAuthenticatedDataTest.php index afe6a5dc9..62f8c916b 100644 --- a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithAdditionalAuthenticatedDataTest.php +++ b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithAdditionalAuthenticatedDataTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithCompressionTest.php b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithCompressionTest.php index f8b1175f9..840bad6ad 100644 --- a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithCompressionTest.php +++ b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithCompressionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithSpecificProtectedHeaderValuesTest.php b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithSpecificProtectedHeaderValuesTest.php index 281d10259..83d3495db 100644 --- a/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithSpecificProtectedHeaderValuesTest.php +++ b/tests/Component/Encryption/RFC7520/A128KWAndA128GCMEncryptionWithSpecificProtectedHeaderValuesTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/A256GCMKWAndA128CBC_HS256EncryptionTest.php b/tests/Component/Encryption/RFC7520/A256GCMKWAndA128CBC_HS256EncryptionTest.php index a069e51f2..826539b23 100644 --- a/tests/Component/Encryption/RFC7520/A256GCMKWAndA128CBC_HS256EncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/A256GCMKWAndA128CBC_HS256EncryptionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/DirAndA128GCMEncryptionTest.php b/tests/Component/Encryption/RFC7520/DirAndA128GCMEncryptionTest.php index 556c4bc9b..32bda1879 100644 --- a/tests/Component/Encryption/RFC7520/DirAndA128GCMEncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/DirAndA128GCMEncryptionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/ECDH_ES_A128KWAndA128GCMEncryptionTest.php b/tests/Component/Encryption/RFC7520/ECDH_ES_A128KWAndA128GCMEncryptionTest.php index 6d1324ab3..47853e81f 100644 --- a/tests/Component/Encryption/RFC7520/ECDH_ES_A128KWAndA128GCMEncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/ECDH_ES_A128KWAndA128GCMEncryptionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/ECDH_ES_AndA128CBC_HS256EncryptionTest.php b/tests/Component/Encryption/RFC7520/ECDH_ES_AndA128CBC_HS256EncryptionTest.php index 13649d14e..33359e70f 100644 --- a/tests/Component/Encryption/RFC7520/ECDH_ES_AndA128CBC_HS256EncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/ECDH_ES_AndA128CBC_HS256EncryptionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/MultipleRecipientEncryptionTest.php b/tests/Component/Encryption/RFC7520/MultipleRecipientEncryptionTest.php index f07db246d..05f1129c2 100644 --- a/tests/Component/Encryption/RFC7520/MultipleRecipientEncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/MultipleRecipientEncryptionTest.php @@ -6,8 +6,8 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/PBES2_HS512_A256KWAndA128CBC_HS256EncryptionTest.php b/tests/Component/Encryption/RFC7520/PBES2_HS512_A256KWAndA128CBC_HS256EncryptionTest.php index de912c4f7..8059a3087 100644 --- a/tests/Component/Encryption/RFC7520/PBES2_HS512_A256KWAndA128CBC_HS256EncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/PBES2_HS512_A256KWAndA128CBC_HS256EncryptionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use const JSON_THROW_ON_ERROR; diff --git a/tests/Component/Encryption/RFC7520/RSA1_5AndA128CBC_HS256EncryptionTest.php b/tests/Component/Encryption/RFC7520/RSA1_5AndA128CBC_HS256EncryptionTest.php index 1537fde18..f49f0ef56 100644 --- a/tests/Component/Encryption/RFC7520/RSA1_5AndA128CBC_HS256EncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/RSA1_5AndA128CBC_HS256EncryptionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RFC7520/RSA_OAEPAndA256GCMEncryptionTest.php b/tests/Component/Encryption/RFC7520/RSA_OAEPAndA256GCMEncryptionTest.php index d9217fb97..541d141a4 100644 --- a/tests/Component/Encryption/RFC7520/RSA_OAEPAndA256GCMEncryptionTest.php +++ b/tests/Component/Encryption/RFC7520/RSA_OAEPAndA256GCMEncryptionTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\Component\Encryption\RFC7520; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Tests\Component\Encryption\EncryptionTestCase; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; /** diff --git a/tests/Component/Encryption/RSAKeyEncryptionTest.php b/tests/Component/Encryption/RSAKeyEncryptionTest.php index f134d6e2e..910e5cf68 100644 --- a/tests/Component/Encryption/RSAKeyEncryptionTest.php +++ b/tests/Component/Encryption/RSAKeyEncryptionTest.php @@ -7,10 +7,10 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; use Jose\Component\Core\JWKSet; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\KeyEncryption\RSA15; use Jose\Component\Encryption\Algorithm\KeyEncryption\RSAOAEP; use Jose\Component\Encryption\Algorithm\KeyEncryption\RSAOAEP256; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use const STR_PAD_LEFT; diff --git a/tests/Component/KeyManagement/JWKFactoryTest.php b/tests/Component/KeyManagement/JWKFactoryTest.php index aadcdf2a1..eca351d21 100644 --- a/tests/Component/KeyManagement/JWKFactoryTest.php +++ b/tests/Component/KeyManagement/JWKFactoryTest.php @@ -4,9 +4,9 @@ namespace Jose\Tests\Component\KeyManagement; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\ECKey; use Jose\Component\KeyManagement\JWKFactory; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/Component/KeyManagement/JWKTest.php b/tests/Component/KeyManagement/JWKTest.php index f76e9d917..2d37dbf42 100644 --- a/tests/Component/KeyManagement/JWKTest.php +++ b/tests/Component/KeyManagement/JWKTest.php @@ -7,9 +7,9 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; use Jose\Component\Core\JWKSet; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Core\Util\RSAKey; use Jose\Component\KeyManagement\JWKFactory; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use const JSON_THROW_ON_ERROR; diff --git a/tests/Component/Signature/JWSTest.php b/tests/Component/Signature/JWSTest.php index f2c0c409a..31ff5869c 100644 --- a/tests/Component/Signature/JWSTest.php +++ b/tests/Component/Signature/JWSTest.php @@ -5,9 +5,9 @@ namespace Jose\Tests\Component\Signature; use InvalidArgumentException; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Signature\JWS; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use const JSON_THROW_ON_ERROR; diff --git a/tests/Component/Signature/SignerTest.php b/tests/Component/Signature/SignerTest.php index 80a66d07c..e24e7a38b 100644 --- a/tests/Component/Signature/SignerTest.php +++ b/tests/Component/Signature/SignerTest.php @@ -7,9 +7,9 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; use Jose\Component\Core\JWKSet; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Signature\Serializer\CompactSerializer; use LogicException; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use const JSON_THROW_ON_ERROR; diff --git a/tests/EncryptionAlgorithm/ContentEncryption/AESCBC/AESCBC_HSContentEncryptionTest.php b/tests/EncryptionAlgorithm/ContentEncryption/AESCBC/AESCBC_HSContentEncryptionTest.php index 672642e3a..3eab015cc 100644 --- a/tests/EncryptionAlgorithm/ContentEncryption/AESCBC/AESCBC_HSContentEncryptionTest.php +++ b/tests/EncryptionAlgorithm/ContentEncryption/AESCBC/AESCBC_HSContentEncryptionTest.php @@ -4,10 +4,10 @@ namespace Jose\Tests\EncryptionAlgorithm\ContentEncryption\AESCBC; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\ContentEncryption\A128CBCHS256; use Jose\Component\Encryption\Algorithm\ContentEncryption\A192CBCHS384; use Jose\Component\Encryption\Algorithm\ContentEncryption\A256CBCHS512; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use ReflectionClass; diff --git a/tests/EncryptionAlgorithm/ContentEncryption/AESGCM/AESGCMContentEncryptionTest.php b/tests/EncryptionAlgorithm/ContentEncryption/AESGCM/AESGCMContentEncryptionTest.php index f659f745c..41c8bbd75 100644 --- a/tests/EncryptionAlgorithm/ContentEncryption/AESGCM/AESGCMContentEncryptionTest.php +++ b/tests/EncryptionAlgorithm/ContentEncryption/AESGCM/AESGCMContentEncryptionTest.php @@ -4,10 +4,10 @@ namespace Jose\Tests\EncryptionAlgorithm\ContentEncryption\AESGCM; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\ContentEncryption\A128GCM; use Jose\Component\Encryption\Algorithm\ContentEncryption\A192GCM; use Jose\Component\Encryption\Algorithm\ContentEncryption\A256GCM; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use const STR_PAD_LEFT; diff --git a/tests/EncryptionAlgorithm/KeyEncryption/AESGCMKW/AESGCMKWKeyEncryptionTest.php b/tests/EncryptionAlgorithm/KeyEncryption/AESGCMKW/AESGCMKWKeyEncryptionTest.php index 409033898..e97a450da 100644 --- a/tests/EncryptionAlgorithm/KeyEncryption/AESGCMKW/AESGCMKWKeyEncryptionTest.php +++ b/tests/EncryptionAlgorithm/KeyEncryption/AESGCMKW/AESGCMKWKeyEncryptionTest.php @@ -6,10 +6,10 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\KeyEncryption\A128GCMKW; use Jose\Component\Encryption\Algorithm\KeyEncryption\A192GCMKW; use Jose\Component\Encryption\Algorithm\KeyEncryption\A256GCMKW; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/EncryptionAlgorithm/KeyEncryption/AESKW/AESKWKeyEncryptionTest.php b/tests/EncryptionAlgorithm/KeyEncryption/AESKW/AESKWKeyEncryptionTest.php index 3f7117e90..9013745a6 100644 --- a/tests/EncryptionAlgorithm/KeyEncryption/AESKW/AESKWKeyEncryptionTest.php +++ b/tests/EncryptionAlgorithm/KeyEncryption/AESKW/AESKWKeyEncryptionTest.php @@ -6,10 +6,10 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\KeyEncryption\A128KW; use Jose\Component\Encryption\Algorithm\KeyEncryption\A192KW; use Jose\Component\Encryption\Algorithm\KeyEncryption\A256KW; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/EncryptionAlgorithm/KeyEncryption/Direct/DirAlgorithmTest.php b/tests/EncryptionAlgorithm/KeyEncryption/Direct/DirAlgorithmTest.php index 6f249c9c6..5ba32c12a 100644 --- a/tests/EncryptionAlgorithm/KeyEncryption/Direct/DirAlgorithmTest.php +++ b/tests/EncryptionAlgorithm/KeyEncryption/Direct/DirAlgorithmTest.php @@ -6,8 +6,8 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\KeyEncryption\Dir; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/EncryptionAlgorithm/KeyEncryption/ECDHES/ECDHESKeyAgreementTest.php b/tests/EncryptionAlgorithm/KeyEncryption/ECDHES/ECDHESKeyAgreementTest.php index 513335437..b9f8fff8c 100644 --- a/tests/EncryptionAlgorithm/KeyEncryption/ECDHES/ECDHESKeyAgreementTest.php +++ b/tests/EncryptionAlgorithm/KeyEncryption/ECDHES/ECDHESKeyAgreementTest.php @@ -6,11 +6,11 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\KeyEncryption\ECDHES; use Jose\Component\Encryption\Algorithm\KeyEncryption\ECDHESA128KW; use Jose\Component\Encryption\Algorithm\KeyEncryption\ECDHESA192KW; use Jose\Component\Encryption\Algorithm\KeyEncryption\ECDHESA256KW; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use const STR_PAD_LEFT; diff --git a/tests/EncryptionAlgorithm/KeyEncryption/PBES2/PBES2_HS_AESKWKeyEncryptionTest.php b/tests/EncryptionAlgorithm/KeyEncryption/PBES2/PBES2_HS_AESKWKeyEncryptionTest.php index e09fbd422..f60e21c19 100644 --- a/tests/EncryptionAlgorithm/KeyEncryption/PBES2/PBES2_HS_AESKWKeyEncryptionTest.php +++ b/tests/EncryptionAlgorithm/KeyEncryption/PBES2/PBES2_HS_AESKWKeyEncryptionTest.php @@ -6,10 +6,10 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Encryption\Algorithm\KeyEncryption\PBES2HS256A128KW; use Jose\Component\Encryption\Algorithm\KeyEncryption\PBES2HS384A192KW; use Jose\Component\Encryption\Algorithm\KeyEncryption\PBES2HS512A256KW; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use const STR_PAD_LEFT; diff --git a/tests/SignatureAlgorithm/ECDSA/ECDSAFromRFC6979Test.php b/tests/SignatureAlgorithm/ECDSA/ECDSAFromRFC6979Test.php index 40d53ed7a..eeaeb47b9 100644 --- a/tests/SignatureAlgorithm/ECDSA/ECDSAFromRFC6979Test.php +++ b/tests/SignatureAlgorithm/ECDSA/ECDSAFromRFC6979Test.php @@ -5,11 +5,11 @@ namespace Jose\Tests\SignatureAlgorithm\ECDSA; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Signature\Algorithm\ES256; use Jose\Component\Signature\Algorithm\ES384; use Jose\Component\Signature\Algorithm\ES512; use Jose\Component\Signature\Algorithm\SignatureAlgorithm; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/SignatureAlgorithm/ECDSA/ECDSASignatureTest.php b/tests/SignatureAlgorithm/ECDSA/ECDSASignatureTest.php index a6f97b2d6..fe138502a 100644 --- a/tests/SignatureAlgorithm/ECDSA/ECDSASignatureTest.php +++ b/tests/SignatureAlgorithm/ECDSA/ECDSASignatureTest.php @@ -6,10 +6,10 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Signature\Algorithm\ES256; use Jose\Component\Signature\Algorithm\ES384; use Jose\Component\Signature\Algorithm\ES512; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/SignatureAlgorithm/EdDSA/EdDSASignatureTest.php b/tests/SignatureAlgorithm/EdDSA/EdDSASignatureTest.php index 77ee9baad..b866df5b3 100644 --- a/tests/SignatureAlgorithm/EdDSA/EdDSASignatureTest.php +++ b/tests/SignatureAlgorithm/EdDSA/EdDSASignatureTest.php @@ -6,10 +6,10 @@ use Jose\Component\Core\AlgorithmManager; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Signature\Algorithm\EdDSA; use Jose\Component\Signature\JWSBuilder; use Jose\Component\Signature\JWSVerifier; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/SignatureAlgorithm/Experimental/Blake2bTest.php b/tests/SignatureAlgorithm/Experimental/Blake2bTest.php index bcc9c455d..a8d5183d2 100644 --- a/tests/SignatureAlgorithm/Experimental/Blake2bTest.php +++ b/tests/SignatureAlgorithm/Experimental/Blake2bTest.php @@ -6,8 +6,8 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Experimental\Signature\Blake2b; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Before; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/SignatureAlgorithm/Experimental/P256KSignatureTest.php b/tests/SignatureAlgorithm/Experimental/P256KSignatureTest.php index bcece1422..4964d81e7 100644 --- a/tests/SignatureAlgorithm/Experimental/P256KSignatureTest.php +++ b/tests/SignatureAlgorithm/Experimental/P256KSignatureTest.php @@ -5,8 +5,8 @@ namespace Jose\Tests\SignatureAlgorithm\Experimental; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Experimental\Signature\ES256K; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/SignatureAlgorithm/HMAC/HMACSignatureTest.php b/tests/SignatureAlgorithm/HMAC/HMACSignatureTest.php index 80856a43e..92b0e6c0f 100644 --- a/tests/SignatureAlgorithm/HMAC/HMACSignatureTest.php +++ b/tests/SignatureAlgorithm/HMAC/HMACSignatureTest.php @@ -6,10 +6,10 @@ use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Signature\Algorithm\HS256; use Jose\Component\Signature\Algorithm\HS384; use Jose\Component\Signature\Algorithm\HS512; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; diff --git a/tests/SignatureAlgorithm/RSA/RSASignatureTest.php b/tests/SignatureAlgorithm/RSA/RSASignatureTest.php index da510cd90..b68b27eeb 100644 --- a/tests/SignatureAlgorithm/RSA/RSASignatureTest.php +++ b/tests/SignatureAlgorithm/RSA/RSASignatureTest.php @@ -8,6 +8,7 @@ use Jose\Component\Core\AlgorithmManager; use Jose\Component\Core\JWK; use Jose\Component\Core\JWKSet; +use Jose\Component\Core\Util\Base64UrlSafe; use Jose\Component\Signature\Algorithm\PS256; use Jose\Component\Signature\Algorithm\PS384; use Jose\Component\Signature\Algorithm\PS512; @@ -18,7 +19,6 @@ use Jose\Component\Signature\JWSVerifier; use Jose\Component\Signature\Serializer\CompactSerializer; use Jose\Component\Signature\Serializer\JSONGeneralSerializer; -use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use const JSON_THROW_ON_ERROR; From 1e9f8bf0c3f5c60e65c11e096832dec7a2c70cde Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Tue, 2 Jul 2024 18:35:11 +0200 Subject: [PATCH 02/14] Add RangeException to Base64UrlSafe (#577) * Add RangeException to Base64UrlSafe The code in src/Library/Core/Util/Base64UrlSafe.php has been updated to include the use of RangeException. This will further expand its capability in terms of handling exceptional scenarios. --- .gitsplit.yml | 4 ++-- phpstan-baseline.neon | 10 ---------- src/Library/Core/Util/Base64UrlSafe.php | 2 ++ 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.gitsplit.yml b/.gitsplit.yml index ce253cf04..c11a97f9f 100644 --- a/.gitsplit.yml +++ b/.gitsplit.yml @@ -57,5 +57,5 @@ splits: target: "https://${GH_TOKEN}@github.com/web-token/signature-pack.git" origins: - - ^\d+\.\d+\.x$ - - ^\d+\.\d+\.\d+$ + - ^(1|2|3)\.\d+\.x$ + - ^(1|2|3)\.\d+\.\d+$ diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 771344500..d7e10bd9f 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1673,11 +1673,6 @@ parameters: count: 2 path: src/Library/Core/Util/Base64UrlSafe.php - - - message: "#^Instantiated class Jose\\\\Component\\\\Core\\\\Util\\\\RangeException not found\\.$#" - count: 3 - path: src/Library/Core/Util/Base64UrlSafe.php - - message: "#^Method Jose\\\\Component\\\\Core\\\\Util\\\\Base64UrlSafe\\:\\:safeSubstr\\(\\) has parameter \\$length with no type specified\\.$#" count: 1 @@ -1688,11 +1683,6 @@ parameters: count: 2 path: src/Library/Core/Util/Base64UrlSafe.php - - - message: "#^Throwing object of an unknown class Jose\\\\Component\\\\Core\\\\Util\\\\RangeException\\.$#" - count: 3 - path: src/Library/Core/Util/Base64UrlSafe.php - - message: "#^Variable \\$i might not be defined\\.$#" count: 2 diff --git a/src/Library/Core/Util/Base64UrlSafe.php b/src/Library/Core/Util/Base64UrlSafe.php index d7863ad3a..e6a6b3682 100644 --- a/src/Library/Core/Util/Base64UrlSafe.php +++ b/src/Library/Core/Util/Base64UrlSafe.php @@ -27,6 +27,8 @@ * SOFTWARE. */ +use RangeException; + /** * @readonly */ From d7ba8efd5bfab0ef88af600a2a69e5e1e75e8f68 Mon Sep 17 00:00:00 2001 From: Peter Mead Date: Thu, 12 Dec 2024 18:06:31 +0000 Subject: [PATCH 03/14] Fix call function on null (#596) * Add failing tests for JWECollector without compression * Fix call function on null error --------- Co-authored-by: Peter Mead --- src/Bundle/DataCollector/JWECollector.php | 6 +- .../Encryption/JWECollectorTest.php | 100 ++++++++++++++++++ 2 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 tests/Bundle/JoseFramework/Functional/Encryption/JWECollectorTest.php diff --git a/src/Bundle/DataCollector/JWECollector.php b/src/Bundle/DataCollector/JWECollector.php index 1ac34b5ae..3e9798572 100644 --- a/src/Bundle/DataCollector/JWECollector.php +++ b/src/Bundle/DataCollector/JWECollector.php @@ -169,7 +169,7 @@ private function collectSupportedJWEBuilders(array &$data): void 'content_encryption_algorithms' => $jweBuilder->getContentEncryptionAlgorithmManager() ->list(), 'compression_methods' => $jweBuilder->getCompressionMethodManager() - ->list(), + ?->list(), ]; } } @@ -187,7 +187,7 @@ private function collectSupportedJWEDecrypters(array &$data): void 'content_encryption_algorithms' => $jweDecrypter->getContentEncryptionAlgorithmManager() ->list(), 'compression_methods' => $jweDecrypter->getCompressionMethodManager() - ->list(), + ?->list(), ]; } } @@ -210,7 +210,7 @@ private function collectSupportedJWELoaders(array &$data): void ->list(), 'compression_methods' => $jweLoader->getJweDecrypter() ->getCompressionMethodManager() - ->list(), + ?->list(), ]; } } diff --git a/tests/Bundle/JoseFramework/Functional/Encryption/JWECollectorTest.php b/tests/Bundle/JoseFramework/Functional/Encryption/JWECollectorTest.php new file mode 100644 index 000000000..273cf1425 --- /dev/null +++ b/tests/Bundle/JoseFramework/Functional/Encryption/JWECollectorTest.php @@ -0,0 +1,100 @@ +getContainer(); + static::assertInstanceOf(ContainerInterface::class, $container); + + $jweFactory = $container->get(JWEBuilderFactoryService::class); + static::assertInstanceOf(JWEBuilderFactoryService::class, $jweFactory); + + $jweBuilder = $jweFactory->create(['RSA1_5', 'A256GCM']); + + $jweCollector = new JWECollector(); + $jweCollector->addJWEBuilder('builder2', $jweBuilder); + + $data = []; + $jweCollector->collect($data, new Request(), new Response()); + + static::assertArrayHasKey('jwe', $data); + static::assertArrayHasKey('compression_methods', $data['jwe']); + static::assertSame([], $data['jwe']['compression_methods']); + static::assertArrayHasKey('jwe_builders', $data['jwe']); + static::assertArrayHasKey('builder2', $data['jwe']['jwe_builders']); + } + + + #[Test] + public function aJWEDecrypterCanBeCollectedWithoutACompressionMethodManager(): void + { + static::ensureKernelShutdown(); + $client = static::createClient(); + $container = $client->getContainer(); + static::assertInstanceOf(ContainerInterface::class, $container); + + $jweDecrypterFactory = $container->get(JWEDecrypterFactoryService::class); + static::assertInstanceOf(JWEDecrypterFactoryService::class, $jweDecrypterFactory); + + $jweDecrypter = $jweDecrypterFactory->create(['RSA1_5', 'A256GCM']); + + $jweCollector = new JWECollector(); + $jweCollector->addJWEDecrypter('decrypter2', $jweDecrypter); + + $data = []; + $jweCollector->collect($data, new Request(), new Response()); + + static::assertArrayHasKey('jwe', $data); + static::assertArrayHasKey('compression_methods', $data['jwe']); + static::assertSame([], $data['jwe']['compression_methods']); + static::assertArrayHasKey('jwe_decrypters', $data['jwe']); + static::assertArrayHasKey('decrypter2', $data['jwe']['jwe_decrypters']); + } + + #[Test] + public function aJWELoaderCanBeCollectedWithoutACompressionMethodManager(): void + { + static::ensureKernelShutdown(); + $client = static::createClient(); + $container = $client->getContainer(); + static::assertInstanceOf(ContainerInterface::class, $container); + + $jweLoaderFactory = $container->get(JWELoaderFactoryAlias::class); + static::assertInstanceOf(JWELoaderFactoryAlias::class, $jweLoaderFactory); + + $jweLoader = $jweLoaderFactory->create(['jwe_compact'], ['RSA1_5'], ['A256GCM']); + + $jweCollector = new JWECollector(); + $jweCollector->addJWELoader('loader2', $jweLoader); + + $data = []; + $jweCollector->collect($data, new Request(), new Response()); + + static::assertArrayHasKey('jwe', $data); + static::assertArrayHasKey('compression_methods', $data['jwe']); + static::assertSame([], $data['jwe']['compression_methods']); + static::assertArrayHasKey('jwe_loaders', $data['jwe']); + static::assertArrayHasKey('loader2', $data['jwe']['jwe_loaders']); + } +} From 788267095b0b0c3ba42559eb2ec955f416628ec0 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Wed, 7 May 2025 11:11:18 +0200 Subject: [PATCH 04/14] Allow `psr/cache` v2 (#620) * Allow `psr/cache` v2 * Update composer.json --- composer.json | 2 +- src/Library/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 5be74c0ee..0e6005321 100644 --- a/composer.json +++ b/composer.json @@ -55,7 +55,7 @@ "brick/math": "^0.9|^0.10|^0.11|^0.12", "paragonie/constant_time_encoding": "^2.6|^3.0", "paragonie/sodium_compat": "^1.20|^2.0", - "psr/cache": "^3.0", + "psr/cache": "^2.0|^3.0", "psr/clock": "^1.0", "psr/event-dispatcher": "^1.0", "psr/http-client": "^1.0", diff --git a/src/Library/composer.json b/src/Library/composer.json index fee12b478..5774ba238 100644 --- a/src/Library/composer.json +++ b/src/Library/composer.json @@ -44,7 +44,7 @@ "brick/math": "^0.9|^0.10|^0.11|^0.12", "paragonie/constant_time_encoding": "^2.6|^3.0", "paragonie/sodium_compat": "^1.20|^2.0", - "psr/cache": "^3.0", + "psr/cache": "^2.0|^3.0", "psr/clock": "^1.0", "psr/http-factory": "^1.0", "psr/http-client": "^1.0", From 112045db98dc78f10611647cab49e0b3d8a59057 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 17 Nov 2025 21:20:37 +0100 Subject: [PATCH 05/14] Add sodium support for Base64 URL safe encoding/decoding (#644) --- src/Library/Core/Util/Base64UrlSafe.php | 33 ++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Library/Core/Util/Base64UrlSafe.php b/src/Library/Core/Util/Base64UrlSafe.php index e6a6b3682..1ff209f99 100644 --- a/src/Library/Core/Util/Base64UrlSafe.php +++ b/src/Library/Core/Util/Base64UrlSafe.php @@ -27,7 +27,9 @@ * SOFTWARE. */ +use InvalidArgumentException; use RangeException; +use SodiumException; /** * @readonly @@ -36,11 +38,25 @@ final class Base64UrlSafe { public static function encode(string $binString): string { + if (extension_loaded('sodium')) { + try { + return sodium_bin2base64($binString, SODIUM_BASE64_VARIANT_URLSAFE); + } catch (SodiumException $ex) { + throw new RangeException($ex->getMessage(), $ex->getCode(), $ex); + } + } return static::doEncode($binString, true); } public static function encodeUnpadded(string $src): string { + if (extension_loaded('sodium')) { + try { + return sodium_bin2base64($src, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); + } catch (SodiumException $ex) { + throw new RangeException($ex->getMessage(), $ex->getCode(), $ex); + } + } return static::doEncode($src, false); } @@ -66,6 +82,16 @@ public static function decode(string $encodedString, bool $strictPadding = false if ($encodedString[$srcLen - 1] === '=') { throw new RangeException('Incorrect padding'); } + if (extension_loaded('sodium')) { + try { + return sodium_base642bin( + self::safeSubstr($encodedString, 0, $srcLen), + SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING + ); + } catch (SodiumException $ex) { + throw new RangeException($ex->getMessage(), $ex->getCode(), $ex); + } + } } else { $encodedString = rtrim($encodedString, '='); $srcLen = self::safeStrlen($encodedString); @@ -128,14 +154,9 @@ public static function decodeNoPadding(string $encodedString): string return ''; } if (($srcLen & 3) === 0) { - if ($encodedString[$srcLen - 1] === '=') { + if ($encodedString[$srcLen - 1] === '=' || $encodedString[$srcLen - 2] === '=') { throw new InvalidArgumentException("decodeNoPadding() doesn't tolerate padding"); } - if (($srcLen & 3) > 1) { - if ($encodedString[$srcLen - 2] === '=') { - throw new InvalidArgumentException("decodeNoPadding() doesn't tolerate padding"); - } - } } return static::decode($encodedString, true); } From 52b0c9b87423cdab3c20a3c274d12b051ca02bd6 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Thu, 18 Dec 2025 14:48:58 +0100 Subject: [PATCH 06/14] Remove deprecated generic type warnings from PHPStan baseline --- .ci-tools/phpstan-baseline.neon | 222 -------------------------------- 1 file changed, 222 deletions(-) diff --git a/.ci-tools/phpstan-baseline.neon b/.ci-tools/phpstan-baseline.neon index 53039fc88..e2587cb1e 100644 --- a/.ci-tools/phpstan-baseline.neon +++ b/.ci-tools/phpstan-baseline.neon @@ -588,12 +588,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Compiler/SymfonySerializerCompilerPass.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Configuration::getConfigTreeBuilder() return type with generic class Symfony\Component\Config\Definition\Builder\TreeBuilder does not specify its types: T' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Configuration.php - - rawMessage: Class "Jose\Bundle\JoseFramework\DependencyInjection\JoseFrameworkExtension" is not allowed to extend "Symfony\Component\DependencyInjection\Extension\Extension". identifier: ergebnis.noExtends @@ -690,12 +684,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/AbstractSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\AbstractSource::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/AbstractSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\AbstractSource::addConfiguration() is not final, but since the containing class is abstract, it should be.' identifier: ergebnis.finalInAbstractClass @@ -786,12 +774,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Checker/CheckerSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Checker\CheckerSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Checker/CheckerSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Checker\CheckerSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -954,12 +936,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Checker/ClaimChecker.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Checker\ClaimChecker::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Checker/ClaimChecker.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Checker\ClaimChecker::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -1128,12 +1104,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Checker/HeaderChecker.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Checker\HeaderChecker::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Checker/HeaderChecker.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Checker\HeaderChecker::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -1188,12 +1158,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Checker/HeaderChecker.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Console\ConsoleSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Console/ConsoleSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Console\ConsoleSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -1224,12 +1188,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Console/ConsoleSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Core\CoreSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Core/CoreSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Core\CoreSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -1350,12 +1308,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Encryption/AbstractEncryptionSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Encryption\AbstractEncryptionSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Encryption/AbstractEncryptionSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Encryption\AbstractEncryptionSource::getNodeDefinition() is not final, but since the containing class is abstract, it should be.' identifier: ergebnis.finalInAbstractClass @@ -1434,12 +1386,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Encryption/EncryptionSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Encryption\EncryptionSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Encryption/EncryptionSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Encryption\EncryptionSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -1758,12 +1704,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Encryption/JWELoader.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Encryption\JWELoader::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Encryption/JWELoader.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Encryption\JWELoader::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -1938,12 +1878,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Encryption/JWESerializer.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Encryption\JWESerializer::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Encryption/JWESerializer.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Encryption\JWESerializer::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2058,12 +1992,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JKUSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JKUSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JKUSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JKUSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2178,12 +2106,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2316,12 +2238,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource/JKU.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource\JKU::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource/JKU.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource\JKU::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2364,24 +2280,12 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource/JWKSet.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource\JWKSet::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource/JWKSet.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource\JWKSet::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource/JWKSet.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource\JWKSetSource::addConfiguration() has parameter $builder with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource/JWKSetSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource\JWKSetSource::create() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2454,12 +2358,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource/X5U.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource\X5U::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSetSource/X5U.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSetSource\X5U::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2544,12 +2442,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2676,12 +2568,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/CertificateFile.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\CertificateFile::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/CertificateFile.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\CertificateFile::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2724,12 +2610,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/JWK.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\JWK::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/JWK.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\JWK::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2796,12 +2676,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/JWKSet.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\JWKSet::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/JWKSet.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\JWKSet::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2814,12 +2688,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/JWKSet.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\JWKSource::addConfiguration() has parameter $builder with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/JWKSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\JWKSource::create() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2892,12 +2760,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/KeyFile.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\KeyFile::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/KeyFile.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\KeyFile::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -2970,12 +2832,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/P12.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\P12::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/P12.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\P12::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3042,12 +2898,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/Secret.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\Secret::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/Secret.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\Secret::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3102,12 +2952,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/Values.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\Values::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/Values.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\Values::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3174,12 +3018,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/X5C.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\X5C::addConfiguration() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKSource/X5C.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKSource\X5C::createDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3306,12 +3144,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKUriSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKUriSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKUriSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\JWKUriSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3372,12 +3204,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/KeyManagement/JWKUriSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\KeyManagementSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/KeyManagement/KeyManagementSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\KeyManagement\KeyManagementSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3432,12 +3258,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/NestedToken/NestedToken.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\NestedToken\NestedToken::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/NestedToken/NestedToken.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\NestedToken\NestedToken::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3618,12 +3438,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/NestedToken/NestedTokenBuilder.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\NestedToken\NestedTokenBuilder::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/NestedToken/NestedTokenBuilder.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\NestedToken\NestedTokenBuilder::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3828,12 +3642,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/NestedToken/NestedTokenLoader.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\NestedToken\NestedTokenLoader::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/NestedToken/NestedTokenLoader.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\NestedToken\NestedTokenLoader::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -3978,12 +3786,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Signature/AbstractSignatureSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Signature\AbstractSignatureSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Signature/AbstractSignatureSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Signature\AbstractSignatureSource::getNodeDefinition() is not final, but since the containing class is abstract, it should be.' identifier: ergebnis.finalInAbstractClass @@ -4218,12 +4020,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Signature/JWSLoader.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Signature\JWSLoader::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Signature/JWSLoader.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Signature\JWSLoader::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -4398,12 +4194,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Signature/JWSSerializer.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Signature\JWSSerializer::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Signature/JWSSerializer.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Signature\JWSSerializer::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -4572,12 +4362,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Signature/SignatureSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Signature\SignatureSource::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Signature/SignatureSource.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Signature\SignatureSource::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration @@ -4620,12 +4404,6 @@ parameters: count: 1 path: ../src/Bundle/DependencyInjection/Source/Signature/SignatureSource.php - - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Source::getNodeDefinition() has parameter $node with generic class Symfony\Component\Config\Definition\Builder\NodeDefinition but does not specify its types: TParent' - identifier: missingType.generics - count: 1 - path: ../src/Bundle/DependencyInjection/Source/Source.php - - rawMessage: 'Method Jose\Bundle\JoseFramework\DependencyInjection\Source\Source::load() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.' identifier: ergebnis.noParameterWithContainerTypeDeclaration From 5a581014d9dbe519755eb7c27fc8864ff99c9a9b Mon Sep 17 00:00:00 2001 From: sandesh-as Date: Thu, 18 Dec 2025 19:57:35 +0530 Subject: [PATCH 07/14] Fix PHP 8.5 deprecation (#648) --- src/Library/Signature/Algorithm/Util/RSA.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Library/Signature/Algorithm/Util/RSA.php b/src/Library/Signature/Algorithm/Util/RSA.php index 6e6dac2ac..a748105fd 100644 --- a/src/Library/Signature/Algorithm/Util/RSA.php +++ b/src/Library/Signature/Algorithm/Util/RSA.php @@ -147,7 +147,9 @@ private static function encodeEMSAPSS(string $message, int $modulusLength, Hash $db = $ps . chr(1) . $salt; $dbMask = self::getMGF1($h, $emLen - $hash->getLength() - 1, $hash); $maskedDB = $db ^ $dbMask; - $maskedDB[0] = ~chr(0xFF << ($modulusLength & 7)) & $maskedDB[0]; + // PHP 8.5 Compatibility: Constrain value to 0-255 before passing to chr() + $shiftBits = $modulusLength & 7; + $maskedDB[0] = ~chr((0xFF << $shiftBits) & 0xFF) & $maskedDB[0]; return $maskedDB . $h . chr(0xBC); } @@ -168,13 +170,15 @@ private static function verifyEMSAPSS(string $m, string $em, int $emBits, Hash $ } $maskedDB = substr($em, 0, -$hash->getLength() - 1); $h = substr($em, -$hash->getLength() - 1, $hash->getLength()); - $temp = chr(0xFF << ($emBits & 7)); + // PHP 8.5 Compatibility: Constrain value to 0-255 before passing to chr() + $shiftBits = $emBits & 7; + $temp = chr((0xFF << $shiftBits) & 0xFF); if ((~$maskedDB[0] & $temp) !== $temp) { throw new InvalidArgumentException(); } $dbMask = self::getMGF1($h, $emLen - $hash->getLength() - 1, $hash/*MGF*/); $db = $maskedDB ^ $dbMask; - $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; + $db[0] = ~chr((0xFF << $shiftBits) & 0xFF) & $db[0]; $temp = $emLen - $hash->getLength() - $sLen - 2; if (substr($db, 0, $temp) !== str_repeat(chr(0), $temp)) { throw new InvalidArgumentException(); From 46b7f7e634b669a24803b8c3e757a6b785c8386a Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Mon, 30 Mar 2026 09:43:04 +0200 Subject: [PATCH 08/14] Update brick/math version constraint and remove dev minimum stability (#649) Extend brick/math support to ^0.15|^0.16|^0.17 and remove minimum-stability: dev. Co-authored-by: Claude Opus 4.6 (1M context) --- composer.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index a4fe5bdb2..ce8d1a0e9 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ "require": { "php": ">=8.2", "ext-openssl": "*", - "brick/math": "^0.12|^0.13|^0.14", + "brick/math": "^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", "psr/clock": "^1.0", "psr/event-dispatcher": "^1.0", "spomky-labs/pki-framework": "^1.2.1", @@ -92,6 +92,5 @@ }, "config": { "sort-packages": true - }, - "minimum-stability": "dev" + } } From d126963451857602ae23032a0e29b0e18c2e9920 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Tue, 14 Apr 2026 09:44:20 +0200 Subject: [PATCH 09/14] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20la=20contrain?= =?UTF-8?q?te=20de=20version=20de=20brick/math=20pour=20inclure=20les=20ve?= =?UTF-8?q?rsions=200.15=20=C3=A0=200.17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Library/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Library/composer.json b/src/Library/composer.json index 4f0f2a102..3d81d7cd6 100644 --- a/src/Library/composer.json +++ b/src/Library/composer.json @@ -39,7 +39,7 @@ }, "require": { "php": ">=8.2", - "brick/math": "^0.12|^0.13|^0.14", + "brick/math": "^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", "psr/clock": "^1.0", "spomky-labs/pki-framework": "^1.2.1" }, From f8ff367a3b048de9c25ea655c20409655c319117 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sat, 6 Jun 2026 18:26:43 +0200 Subject: [PATCH 10/14] Merge commit from fork PBES2AESKW::unwrapKey read the "p2c" (iteration count) parameter directly from the attacker-controlled JOSE header and fed it to hash_pbkdf2() with no upper bound (the only check was is_int && > 0). A single crafted JWE with a large "p2c" (e.g. 100_000_000) could pin a worker for minutes, enabling an unauthenticated denial-of-service. This adds a configurable maximum iteration count (DEFAULT_MAX_COUNT = 1_000_000, generous vs. realistic legitimate values which are a few thousand) enforced in checkHeaderAdditionalParameters() before any PBKDF2 work. The bound is the third constructor argument so operators can tune it. Co-authored-by: Claude Opus 4.8 (1M context) --- .../Algorithm/KeyEncryption/PBES2AESKW.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php b/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php index a93f9ee97..161f8b1cb 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php @@ -15,12 +15,16 @@ use function in_array; use function is_int; use function is_string; +use function sprintf; abstract class PBES2AESKW implements KeyWrapping { + public const DEFAULT_MAX_COUNT = 1_000_000; + public function __construct( private readonly int $salt_size = 64, - private readonly int $nb_count = 4096 + private readonly int $nb_count = 4096, + private readonly int $max_count = self::DEFAULT_MAX_COUNT ) { if (! interface_exists(WrapperInterface::class)) { throw new RuntimeException('Please install "spomky-labs/aes-key-wrap" to use AES-KW algorithms'); @@ -134,6 +138,12 @@ protected function checkHeaderAdditionalParameters(array $header): void if (! is_int($header['p2c']) || $header['p2c'] <= 0) { throw new InvalidArgumentException('The header parameter "p2c" is not valid.'); } + if ($header['p2c'] > $this->max_count) { + throw new InvalidArgumentException(sprintf( + 'The header parameter "p2c" is too large. The maximum allowed value is %d.', + $this->max_count + )); + } } abstract protected function getWrapper(): A256KW|A128KW|A192KW; From ed9f84b40f589f1efde8b2d580915810c0582892 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sat, 6 Jun 2026 18:27:05 +0200 Subject: [PATCH 11/14] Merge commit from fork The Chacha20Poly1305 key-encryption algorithm generated the 16-byte Poly1305 authentication tag during encryptKey() but discarded it: it was never written to the header, so it never reached the wire. decryptKey() then called openssl_decrypt() without the tag argument, which makes OpenSSL skip authentication entirely. The AEAD was therefore degraded to unauthenticated ChaCha20: a tampered encrypted CEK was accepted and a single-byte change in the ciphertext propagated unchecked into the CEK. encryptKey() now publishes the tag as the base64url "tag" header parameter (and verifies it is 16 bytes). decryptKey() requires the "tag" header, validates its length, and passes it to openssl_decrypt() so the Poly1305 tag is actually verified; tampering now yields a decryption failure. Co-authored-by: Claude Opus 4.8 (1M context) --- .../KeyEncryption/Chacha20Poly1305.php | 16 ++- .../Chacha20Poly1305KeyEncryptionTest.php | 104 ++++++++++++++++++ 2 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 tests/EncryptionAlgorithm/Experimental/Chacha20Poly1305KeyEncryptionTest.php diff --git a/src/Experimental/KeyEncryption/Chacha20Poly1305.php b/src/Experimental/KeyEncryption/Chacha20Poly1305.php index 3dc610642..b9a9979f7 100644 --- a/src/Experimental/KeyEncryption/Chacha20Poly1305.php +++ b/src/Experimental/KeyEncryption/Chacha20Poly1305.php @@ -42,15 +42,15 @@ public function encryptKey(JWK $key, string $cek, array $completeHeader, array & $k = $this->getKey($key); $nonce = random_bytes(12); - // We set header parameters - $additionalHeader['nonce'] = Base64UrlSafe::encodeUnpadded($nonce); - $tag = null; $result = openssl_encrypt($cek, 'chacha20-poly1305', $k, OPENSSL_RAW_DATA, $nonce, $tag); - if ($result === false || ! is_string($tag)) { + if ($result === false || ! is_string($tag) || mb_strlen($tag, '8bit') !== 16) { throw new RuntimeException('Unable to encrypt the CEK'); } + $additionalHeader['nonce'] = Base64UrlSafe::encodeUnpadded($nonce); + $additionalHeader['tag'] = Base64UrlSafe::encodeUnpadded($tag); + return $result; } @@ -66,8 +66,14 @@ public function decryptKey(JWK $key, string $encrypted_cek, array $header): stri if (mb_strlen($nonce, '8bit') !== 12) { throw new InvalidArgumentException('The header parameter "nonce" is not valid.'); } + isset($header['tag']) || throw new InvalidArgumentException('The header parameter "tag" is missing.'); + is_string($header['tag']) || throw new InvalidArgumentException('The header parameter "tag" is not valid.'); + $tag = Base64UrlSafe::decodeNoPadding($header['tag']); + if (mb_strlen($tag, '8bit') !== 16) { + throw new InvalidArgumentException('The header parameter "tag" is not valid.'); + } - $result = openssl_decrypt($encrypted_cek, 'chacha20-poly1305', $k, OPENSSL_RAW_DATA, $nonce); + $result = openssl_decrypt($encrypted_cek, 'chacha20-poly1305', $k, OPENSSL_RAW_DATA, $nonce, $tag); if ($result === false) { throw new RuntimeException('Unable to decrypt the CEK'); } diff --git a/tests/EncryptionAlgorithm/Experimental/Chacha20Poly1305KeyEncryptionTest.php b/tests/EncryptionAlgorithm/Experimental/Chacha20Poly1305KeyEncryptionTest.php new file mode 100644 index 000000000..c8691f53b --- /dev/null +++ b/tests/EncryptionAlgorithm/Experimental/Chacha20Poly1305KeyEncryptionTest.php @@ -0,0 +1,104 @@ +key(); + $cek = random_bytes(32); + $algorithm = new Chacha20Poly1305(); + + $additionalHeader = []; + $encrypted = $algorithm->encryptKey($key, $cek, [], $additionalHeader); + + static::assertArrayHasKey('nonce', $additionalHeader); + static::assertArrayHasKey('tag', $additionalHeader); + + $decrypted = $algorithm->decryptKey($key, $encrypted, $additionalHeader); + static::assertSame($cek, $decrypted); + } + + #[Test] + public function tamperedCiphertextIsRejected(): void + { + $key = $this->key(); + $cek = random_bytes(32); + $algorithm = new Chacha20Poly1305(); + + $additionalHeader = []; + $encrypted = $algorithm->encryptKey($key, $cek, [], $additionalHeader); + + $encrypted[0] = $encrypted[0] ^ "\xff"; + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Unable to decrypt the CEK'); + $algorithm->decryptKey($key, $encrypted, $additionalHeader); + } + + #[Test] + public function tamperedTagIsRejected(): void + { + $key = $this->key(); + $cek = random_bytes(32); + $algorithm = new Chacha20Poly1305(); + + $additionalHeader = []; + $encrypted = $algorithm->encryptKey($key, $cek, [], $additionalHeader); + + $tag = Base64UrlSafe::decodeNoPadding($additionalHeader['tag']); + $tag[0] = $tag[0] ^ "\xff"; + $additionalHeader['tag'] = Base64UrlSafe::encodeUnpadded($tag); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Unable to decrypt the CEK'); + $algorithm->decryptKey($key, $encrypted, $additionalHeader); + } + + #[Test] + public function missingTagIsRejected(): void + { + $key = $this->key(); + $cek = random_bytes(32); + $algorithm = new Chacha20Poly1305(); + + $additionalHeader = []; + $encrypted = $algorithm->encryptKey($key, $cek, [], $additionalHeader); + unset($additionalHeader['tag']); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The header parameter "tag" is missing.'); + $algorithm->decryptKey($key, $encrypted, $additionalHeader); + } + + private function key(): JWK + { + return new JWK([ + 'kty' => 'oct', + 'k' => Base64UrlSafe::encodeUnpadded(random_bytes(32)), + ]); + } +} From 944d30b0db8e620a8abb8471cb24a9e42b2dcde6 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sat, 6 Jun 2026 18:27:24 +0200 Subject: [PATCH 12/14] Merge commit from fork RSACrypt::decryptWithRSA15() validated the PKCS#1 v1.5 padding after RSADP and threw InvalidArgumentException as soon as it was malformed, with no implicit-rejection countermeasure. From a JWE caller this exposed a Bleichenbacher/Marvin padding oracle: padding-rejected, padding-valid- wrong-length and padding-valid-full-AEAD ciphertexts all return the same false from JWEDecrypter but perform measurably different amounts of work (amplifiable by enlarging the ciphertext), leaking the PKCS#1 conformance bit through timing. RSACrypt::decrypt()/decryptWithRSA15() now accept an expected key length. When provided, PKCS#1 v1.5 decryption validates the padding in constant time and selects, also in constant time, either the recovered message (valid padding AND expected length) or a freshly generated random key of the expected length. No exception is thrown for padding failures, so the downstream content decryption (AEAD) always runs and fails uniformly. RSA15::decryptKey() supplies the expected CEK length derived from the "enc" header (mirroring the content encryption algorithms' CEK sizes). The legacy throwing behaviour is preserved when no expected length is given, for direct (non-JWE) callers. RSA-OAEP is unaffected. Co-authored-by: Claude Opus 4.8 (1M context) --- .../Algorithm/KeyEncryption/RSA15.php | 49 +++++++++ .../Algorithm/KeyEncryption/Util/RSACrypt.php | 83 ++++++++++++-- .../Encryption/RSA15ImplicitRejectionTest.php | 102 ++++++++++++++++++ 3 files changed, 223 insertions(+), 11 deletions(-) create mode 100644 tests/Component/Encryption/RSA15ImplicitRejectionTest.php diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/RSA15.php b/src/Library/Encryption/Algorithm/KeyEncryption/RSA15.php index 0480e2148..7f1f5832f 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/RSA15.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/RSA15.php @@ -4,15 +4,51 @@ namespace Jose\Component\Encryption\Algorithm\KeyEncryption; +use InvalidArgumentException; +use Jose\Component\Core\JWK; +use Jose\Component\Core\Util\RSAKey; use Jose\Component\Encryption\Algorithm\KeyEncryption\Util\RSACrypt; +use function is_string; final class RSA15 extends RSA { + /** + * @var array + */ + private const CEK_LENGTHS = [ + 'A128GCM' => 16, + 'A192GCM' => 24, + 'A256GCM' => 32, + 'A128CBC-HS256' => 32, + 'A192CBC-HS384' => 48, + 'A256CBC-HS512' => 64, + ]; + public function name(): string { return 'RSA1_5'; } + /** + * @param array $header + */ + public function decryptKey(JWK $key, string $encrypted_cek, array $header): string + { + $this->checkKey($key); + if (! $key->has('d')) { + throw new InvalidArgumentException('The key is not a private key'); + } + $priv = RSAKey::createFromJWK($key); + + return RSACrypt::decrypt( + $priv, + $encrypted_cek, + RSACrypt::ENCRYPTION_PKCS1, + null, + $this->getExpectedCekLength($header) + ); + } + protected function getEncryptionMode(): int { return RSACrypt::ENCRYPTION_PKCS1; @@ -22,4 +58,17 @@ protected function getHashAlgorithm(): ?string { return null; } + + /** + * @param array $header + */ + private function getExpectedCekLength(array $header): ?int + { + $enc = $header['enc'] ?? null; + if (! is_string($enc)) { + return null; + } + + return self::CEK_LENGTHS[$enc] ?? null; + } } diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/Util/RSACrypt.php b/src/Library/Encryption/Algorithm/KeyEncryption/Util/RSACrypt.php index e53f85aa1..6c404e513 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/Util/RSACrypt.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/Util/RSACrypt.php @@ -46,8 +46,13 @@ public static function encrypt(RSAKey $key, string $data, int $mode, ?string $ha } } - public static function decrypt(RSAKey $key, string $plaintext, int $mode, ?string $hash = null): string - { + public static function decrypt( + RSAKey $key, + string $plaintext, + int $mode, + ?string $hash = null, + ?int $expectedKeyLength = null + ): string { switch ($mode) { case self::ENCRYPTION_OAEP: if ($hash === null) { @@ -56,7 +61,7 @@ public static function decrypt(RSAKey $key, string $plaintext, int $mode, ?strin return self::decryptWithRSAOAEP($key, $plaintext, $hash); case self::ENCRYPTION_PKCS1: - return self::decryptWithRSA15($key, $plaintext); + return self::decryptWithRSA15($key, $plaintext, $expectedKeyLength); default: throw new InvalidArgumentException('Unsupported mode.'); } @@ -85,7 +90,7 @@ public static function encryptWithRSA15(RSAKey $key, string $data): string return self::convertIntegerToOctetString($c, $key->getModulusLength()); } - public static function decryptWithRSA15(RSAKey $key, string $c): string + public static function decryptWithRSA15(RSAKey $key, string $c, ?int $expectedKeyLength = null): string { if (mb_strlen($c, '8bit') !== $key->getModulusLength()) { throw new InvalidArgumentException('Unable to decrypt'); @@ -93,16 +98,72 @@ public static function decryptWithRSA15(RSAKey $key, string $c): string $c = BigInteger::createFromBinaryString($c); $m = self::getRSADP($key, $c); $em = self::convertIntegerToOctetString($m, $key->getModulusLength()); - if (ord($em[0]) !== 0 || ord($em[1]) > 2) { - throw new InvalidArgumentException('Unable to decrypt'); + + if ($expectedKeyLength === null) { + if (ord($em[0]) !== 0 || ord($em[1]) > 2) { + throw new InvalidArgumentException('Unable to decrypt'); + } + $ps = mb_substr($em, 2, (int) mb_strpos($em, chr(0), 2, '8bit') - 2, '8bit'); + $m = mb_substr($em, mb_strlen($ps, '8bit') + 3, null, '8bit'); + if (mb_strlen($ps, '8bit') < 8) { + throw new InvalidArgumentException('Unable to decrypt'); + } + + return $m; } - $ps = mb_substr($em, 2, (int) mb_strpos($em, chr(0), 2, '8bit') - 2, '8bit'); - $m = mb_substr($em, mb_strlen($ps, '8bit') + 3, null, '8bit'); - if (mb_strlen($ps, '8bit') < 8) { - throw new InvalidArgumentException('Unable to decrypt'); + + return self::extractRSA15KeyOrRandom($em, $expectedKeyLength); + } + + private static function extractRSA15KeyOrRandom(string $em, int $expectedKeyLength): string + { + $k = mb_strlen($em, '8bit'); + $random = random_bytes($expectedKeyLength); + + if ($k < $expectedKeyLength + 11) { + return $random; } + $candidate = mb_substr($em, $k - $expectedKeyLength, null, '8bit'); + + $valid = self::ctEq(ord($em[0]), 0x00) & self::ctEq(ord($em[1]), 0x02); + + $seenSeparator = 0; + $separatorIndex = 0; + $psLength = 0; + for ($i = 2; $i < $k; ++$i) { + $isZero = self::ctEq(ord($em[$i]), 0x00); + $firstZero = $isZero & (1 - $seenSeparator); + $separatorIndex |= $firstZero * $i; + $psLength += (1 - $seenSeparator) & (1 - $isZero); + $seenSeparator |= $isZero; + } + + $valid &= $seenSeparator; + $valid &= self::ctGe($psLength, 8); + + $messageLength = $k - $separatorIndex - 1; + $valid &= self::ctEq($messageLength, $expectedKeyLength); + + return self::ctSelect($valid, $candidate, $random); + } + + private static function ctEq(int $a, int $b): int + { + $diff = $a ^ $b; + + return (($diff - 1) >> 63) & 1; + } + + private static function ctGe(int $a, int $b): int + { + return (($b - $a - 1) >> 63) & 1; + } + + private static function ctSelect(int $condition, string $a, string $b): string + { + $mask = str_repeat(chr(($condition * 0xFF) & 0xFF), mb_strlen($a, '8bit')); - return $m; + return ($a & $mask) | ($b & ~$mask); } /** diff --git a/tests/Component/Encryption/RSA15ImplicitRejectionTest.php b/tests/Component/Encryption/RSA15ImplicitRejectionTest.php new file mode 100644 index 000000000..99951e041 --- /dev/null +++ b/tests/Component/Encryption/RSA15ImplicitRejectionTest.php @@ -0,0 +1,102 @@ + 'RSA1_5', + 'use' => 'enc', + ]); + $algorithm = new RSA15(); + $cek = random_bytes(16); // A128GCM CEK + $header = [ + 'alg' => 'RSA1_5', + 'enc' => 'A128GCM', + ]; + + $additionalHeader = []; + $encrypted = $algorithm->encryptKey($jwk, $cek, $header, $additionalHeader); + $decrypted = $algorithm->decryptKey($jwk, $encrypted, $header); + + static::assertSame($cek, $decrypted); + } + + #[Test] + public function malformedCiphertextDoesNotThrowAndReturnsExpectedLength(): void + { + $jwk = JWKFactory::createRSAKey(2048, [ + 'alg' => 'RSA1_5', + 'use' => 'enc', + ]); + $algorithm = new RSA15(); + $key = RSAKey::createFromJWK($jwk); + $garbage = "\x00" . random_bytes($key->getModulusLength() - 1); + $header = [ + 'alg' => 'RSA1_5', + 'enc' => 'A128GCM', + ]; + + $result = $algorithm->decryptKey($jwk, $garbage, $header); + + // 16 bytes for A128GCM, and (overwhelmingly) not a valid recovery. + static::assertSame(16, mb_strlen($result, '8bit')); + } + + #[Test] + public function implicitRejectionRespectsEncCekLength(): void + { + $jwk = JWKFactory::createRSAKey(2048, [ + 'alg' => 'RSA1_5', + 'use' => 'enc', + ]); + $algorithm = new RSA15(); + $key = RSAKey::createFromJWK($jwk); + $garbage = "\x00" . random_bytes($key->getModulusLength() - 1); + + $lengths = [ + 'A128GCM' => 16, + 'A192GCM' => 24, + 'A256GCM' => 32, + 'A128CBC-HS256' => 32, + 'A192CBC-HS384' => 48, + 'A256CBC-HS512' => 64, + ]; + foreach ($lengths as $enc => $expected) { + $result = $algorithm->decryptKey($jwk, $garbage, ['alg' => 'RSA1_5', 'enc' => $enc]); + static::assertSame($expected, mb_strlen($result, '8bit'), $enc); + } + } + + #[Test] + public function legacyDirectDecryptStillThrowsOnGarbage(): void + { + $jwk = JWKFactory::createRSAKey(2048, [ + 'alg' => 'RSA1_5', + 'use' => 'enc', + ]); + $key = RSAKey::createFromJWK($jwk); + $garbage = "\x00" . random_bytes($key->getModulusLength() - 1); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Unable to decrypt'); + RSACrypt::decrypt($key, $garbage, RSACrypt::ENCRYPTION_PKCS1); + } +} From 1e231cb4c2630c154be38e6010ff8c0b965bd487 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sat, 6 Jun 2026 18:30:13 +0200 Subject: [PATCH 13/14] Merge commit from fork MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JWSVerifier::getAlgorithm() merged the protected and unprotected headers with [...$protected, ...$unprotected]; with duplicate keys PHP keeps the LAST value, so the attacker-controlled unprotected header could override the integrity-protected "alg". Combined with HeaderCheckerManager (which validates "alg" from the protected header), this is a TOCTOU algorithm-confusion / downgrade vector (e.g. forcing HS256 against an RSA public key, or HS512 -> HS256), and "alg" placed only in the unprotected header bypassed the duplicate-parameter check entirely. Per RFC 7515 §4.1.1 "alg" MUST be integrity protected. getAlgorithm() now reads "alg" exclusively from the protected header and rejects a JWS whose "alg" is absent from (or present only outside) the protected header. Co-authored-by: Claude Opus 4.8 (1M context) --- src/Library/Signature/JWSVerifier.php | 11 +-- .../Signature/AlgorithmConfusionTest.php | 89 +++++++++++++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 tests/Component/Signature/AlgorithmConfusionTest.php diff --git a/src/Library/Signature/JWSVerifier.php b/src/Library/Signature/JWSVerifier.php index 1944c4ddf..d165db26e 100644 --- a/src/Library/Signature/JWSVerifier.php +++ b/src/Library/Signature/JWSVerifier.php @@ -140,16 +140,17 @@ private function checkPayload(JWS $jws, ?string $detachedPayload = null): void */ private function getAlgorithm(Signature $signature): Algorithm { - $completeHeader = [...$signature->getProtectedHeader(), ...$signature->getHeader()]; - if (! isset($completeHeader['alg'])) { - throw new InvalidArgumentException('No "alg" parameter set in the header.'); + $protectedHeader = $signature->getProtectedHeader(); + if (! isset($protectedHeader['alg'])) { + throw new InvalidArgumentException('No "alg" parameter set in the protected header.'); } + $alg = $protectedHeader['alg']; - $algorithm = $this->signatureAlgorithmManager->get($completeHeader['alg']); + $algorithm = $this->signatureAlgorithmManager->get($alg); if (! $algorithm instanceof SignatureAlgorithm && ! $algorithm instanceof MacAlgorithm) { throw new InvalidArgumentException(sprintf( 'The algorithm "%s" is not supported or is not a signature or MAC algorithm.', - $completeHeader['alg'] + $alg )); } diff --git a/tests/Component/Signature/AlgorithmConfusionTest.php b/tests/Component/Signature/AlgorithmConfusionTest.php new file mode 100644 index 000000000..9ffdf4754 --- /dev/null +++ b/tests/Component/Signature/AlgorithmConfusionTest.php @@ -0,0 +1,89 @@ +key(); + $algorithmManager = new AlgorithmManager([new HS256(), new HS512()]); + $jws = (new JWSBuilder($algorithmManager)) + ->create() + ->withPayload('payload') + ->addSignature($key, ['alg' => 'HS256']) + ->build(); + + $verifier = new JWSVerifier($algorithmManager); + static::assertTrue($verifier->verifyWithKey($jws, $key, 0)); + } + + #[Test] + public function unprotectedAlgDoesNotOverrideProtected(): void + { + $key = $this->key(); + $algorithmManager = new AlgorithmManager([new HS256(), new HS512()]); + + $jws = (new JWSBuilder($algorithmManager)) + ->create() + ->withPayload('payload') + ->addSignature($key, ['alg' => 'HS256']) + ->build(); + $serializer = new JSONFlattenedSerializer(); + $data = json_decode($serializer->serialize($jws, 0), true); + $data['header'] = ['alg' => 'HS512']; + $tamperedJws = $serializer->unserialize(json_encode($data)); + + $verifier = new JWSVerifier($algorithmManager); + + static::assertTrue($verifier->verifyWithKey($tamperedJws, $key, 0)); + } + + #[Test] + public function algOnlyInUnprotectedHeaderIsRejected(): void + { + $key = $this->key(); + $algorithmManager = new AlgorithmManager([new HS256(), new HS512()]); + + $jws = (new JWSBuilder($algorithmManager)) + ->create() + ->withPayload('payload') + ->addSignature($key, ['alg' => 'HS256']) + ->build(); + $serializer = new JSONFlattenedSerializer(); + $data = json_decode($serializer->serialize($jws, 0), true); + unset($data['protected']); + $data['header'] = ['alg' => 'HS256']; + $tamperedJws = $serializer->unserialize(json_encode($data)); + + $verifier = new JWSVerifier($algorithmManager); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('No "alg" parameter set in the protected header.'); + $verifier->verifyWithKey($tamperedJws, $key, 0); + } + + private function key(): JWK + { + return new JWK([ + 'kty' => 'oct', + 'k' => 'dKaQUMb3qDMRdfg6qLqsGgG-aWdh6cd1F6tXrXddzpc', + ]); + } +} From fb6d52487d4e836dc8e9a5df4446a0b2ebcb6a92 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sat, 6 Jun 2026 19:41:20 +0200 Subject: [PATCH 14/14] Update signature tests for the protected-header "alg" requirement (#651) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following the algorithm-confusion fix (GHSA-jc38-x7x8-2xc8), JWSVerifier reads "alg" only from the integrity-protected header and rejects a JWS whose "alg" is absent from it. Three existing tests asserted the previous behaviour where "alg" could come from the unprotected header (RFC 7520 §4.7 / §4.8 examples); they now assert that such tokens are rejected, and the expected exception message is updated accordingly. Co-authored-by: Claude Opus 4.8 (1M context) --- .../RFC7520/MultipleSignaturesTest.php | 21 +++++++++++++++++-- tests/Component/Signature/SignerTest.php | 2 +- .../HMAC/HMACFromRFC7520Test.php | 8 ++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/Component/Signature/RFC7520/MultipleSignaturesTest.php b/tests/Component/Signature/RFC7520/MultipleSignaturesTest.php index 9f3e5f1d9..cd7e3f40c 100644 --- a/tests/Component/Signature/RFC7520/MultipleSignaturesTest.php +++ b/tests/Component/Signature/RFC7520/MultipleSignaturesTest.php @@ -4,7 +4,10 @@ namespace Jose\Tests\Component\Signature\RFC7520; +use InvalidArgumentException; use Jose\Component\Core\JWK; +use Jose\Component\Signature\JWS; +use Jose\Component\Signature\JWSVerifier; use Jose\Tests\Component\Signature\SignatureTestCase; use PHPUnit\Framework\Attributes\Test; @@ -81,9 +84,9 @@ public function multipleSignatures(): void static::assertSame(3, $jws->countSignatures()); - static::assertTrue($jwsVerifier->verifyWithKey($jws, $ecdsa_private_key, 0)); static::assertTrue($jwsVerifier->verifyWithKey($jws, $rsa_private_key, 1)); static::assertTrue($jwsVerifier->verifyWithKey($jws, $symmetric_key, 2)); + $this->assertUnprotectedAlgIsRejected($jwsVerifier, $jws, $ecdsa_private_key, 0); /** @see https://tools.ietf.org/html/rfc7520#section-4.8.5 */ $expected_json = '{"payload":"SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4","signatures":[{"protected":"eyJhbGciOiJSUzI1NiJ9","header":{"kid":"bilbo.baggins@hobbiton.example"},"signature":"MIsjqtVlOpa71KE-Mss8_Nq2YH4FGhiocsqrgi5NvyG53uoimic1tcMdSg-qptrzZc7CG6Svw2Y13TDIqHzTUrL_lR2ZFcryNFiHkSw129EghGpwkpxaTn_THJTCglNbADko1MZBCdwzJxwqZc-1RlpO2HibUYyXSwO97BSe0_evZKdjvvKSgsIqjytKSeAMbhMBdMma622_BG5t4sdbuCHtFjp9iJmkio47AIwqkZV1aIZsv33uPUqBBCXbYoQJwt7mxPftHmNlGoOSMxR_3thmXTCm4US-xiNOyhbm8afKK64jU6_TPtQHiJeQJxz9G3Tx-083B745_AfYOnlC9w"},{"header":{"alg":"ES512","kid":"bilbo.baggins@hobbiton.example"},"signature":"ARcVLnaJJaUWG8fG-8t5BREVAuTY8n8YHjwDO1muhcdCoFZFFjfISu0Cdkn9Ybdlmi54ho0x924DUz8sK7ZXkhc7AFM8ObLfTvNCrqcI3Jkl2U5IX3utNhODH6v7xgy1Qahsn0fyb4zSAkje8bAWz4vIfj5pCMYxxm4fgV3q7ZYhm5eD"},{"protected":"eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LWVlZjMxNGJjNzAzNyJ9","signature":"s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0"}]}'; @@ -94,7 +97,21 @@ public function multipleSignatures(): void static::assertSame($payload, $loaded_json->getPayload()); static::assertTrue($jwsVerifier->verifyWithKey($loaded_json, $rsa_private_key, 0)); - static::assertTrue($jwsVerifier->verifyWithKey($loaded_json, $ecdsa_private_key, 1)); static::assertTrue($jwsVerifier->verifyWithKey($loaded_json, $symmetric_key, 2)); + $this->assertUnprotectedAlgIsRejected($jwsVerifier, $loaded_json, $ecdsa_private_key, 1); + } + + private function assertUnprotectedAlgIsRejected( + JWSVerifier $jwsVerifier, + JWS $jws, + JWK $key, + int $signature + ): void { + try { + $jwsVerifier->verifyWithKey($jws, $key, $signature); + static::fail('A signature whose "alg" is not in the protected header must be rejected.'); + } catch (InvalidArgumentException $e) { + static::assertSame('No "alg" parameter set in the protected header.', $e->getMessage()); + } } } diff --git a/tests/Component/Signature/SignerTest.php b/tests/Component/Signature/SignerTest.php index e24e7a38b..34a0a318f 100644 --- a/tests/Component/Signature/SignerTest.php +++ b/tests/Component/Signature/SignerTest.php @@ -930,7 +930,7 @@ public function flattenedJSONWithUnencodedDetachedPayload(): void public function signAndLoadWithoutAlgParameterInTheHeader(): void { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No "alg" parameter set in the header.'); + $this->expectExceptionMessage('No "alg" parameter set in the protected header.'); $payload = "It\xe2\x80\x99s a dangerous business, Frodo, going out your door. You step onto the road, and if you don't keep your feet, there\xe2\x80\x99s no knowing where you might be swept off to."; $jws = 'eyJraWQiOiJiaWxiby5iYWdnaW5zQGhvYmJpdG9uLmV4YW1wbGUifQ.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4.MRjdkly7_-oTPTS3AXP41iQIGKa80A0ZmTuV5MEaHoxnW2e5CZ5NlKtainoFmKZopdHM1O2U4mwzJdQx996ivp83xuglII7PNDi84wnB-BDkoBwA78185hX-Es4JIwmDLJK3lfWRa-XtL0RnltuYv746iYTh_qHRD68BNt1uSNCrUCTJDt5aAE6x8wW1Kt9eRo4QPocSadnHXFxnt8Is9UzpERV0ePPQdLuW3IS_de3xyIrDaLGdjluPxUAhb6L2aXic1U12podGU0KLUQSE_oI-ZnmKJ3F4uOZDnd6QZWJushZ41Axf_fcIe8u9ipH84ogoree7vjbU5y18kDquDg'; diff --git a/tests/SignatureAlgorithm/HMAC/HMACFromRFC7520Test.php b/tests/SignatureAlgorithm/HMAC/HMACFromRFC7520Test.php index 1c0101661..071593f76 100644 --- a/tests/SignatureAlgorithm/HMAC/HMACFromRFC7520Test.php +++ b/tests/SignatureAlgorithm/HMAC/HMACFromRFC7520Test.php @@ -4,6 +4,7 @@ namespace Jose\Tests\SignatureAlgorithm\HMAC; +use InvalidArgumentException; use Jose\Component\Core\AlgorithmManager; use Jose\Component\Core\JWK; use Jose\Component\Signature\Algorithm\HS256; @@ -302,9 +303,10 @@ public function hS256WithoutProtectedHeader(): void ); $loaded_flattened_json = $jsonFlattenedSerializer->unserialize($expected_flattened_json); - static::assertTrue($jwsVerifier->verifyWithKey($loaded_flattened_json, $key, 0)); - $loaded_json = $jsonGeneralSerializer->unserialize($expected_json); - static::assertTrue($jwsVerifier->verifyWithKey($loaded_json, $key, 0)); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('No "alg" parameter set in the protected header.'); + $jwsVerifier->verifyWithKey($loaded_flattened_json, $key, 0); } }