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 adbac08c..77134450 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 76fd00f0..50b3cde7 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 947a7c83..3dc61064 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 73cd7579..d268a02c 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 8f4f58cb..daf7230b 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 9685becf..27b4bf30 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 00000000..d7863ad3 --- /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 aa4aac88..f84123ac 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 7b47d5cc..c28fe661 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 8395db17..20395fa0 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 c939df46..0b1bf43f 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 82db172c..37c79d9f 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 909f2a1e..15c408ac 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 9027a8e7..1af2818f 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 d01ec492..b4e2211a 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 a8222fc6..a93f9ee9 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 f753b6cc..96e98e10 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 f4e18bbd..505ae667 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 ba015e8a..4c38ff39 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 6ecf28e3..02ea352e 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 96f23dc0..15b963a3 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 2c003861..081a6b29 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 0e283a5a..35b7157c 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 24051793..1d769106 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 43f0b1f5..9a354c7e 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 2f5ccb9a..43a75fa1 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 bf42b027..1bf4ac45 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 8ee1bfad..6c3f61a7 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 4c8d938b..f72c66b4 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 ff98ea37..fe48e87d 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 6d59ce4d..cd09113e 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 badda987..92436b00 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 84201cc6..3c1a1661 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 187d24d8..1944c4dd 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 3a657a14..03a9c0d7 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 1a8b4cb0..93dae92c 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 1905e645..43acd0e0 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 88774a89..5d9445bb 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 3dc3b425..fb6ecfc1 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 368723dd..b7030e7c 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 c21c4590..f3dc4ad6 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 ef018f35..9ec432be 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 e8e5d589..5cb4ecf2 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 afe6a5dc..62f8c916 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 f8b1175f..840bad6a 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 281d1025..83d3495d 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 a069e51f..826539b2 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 556c4bc9..32bda187 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 6d1324ab..47853e81 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 13649d14..33359e70 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 f07db246..05f1129c 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 de912c4f..8059a308 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 1537fde1..f49f0ef5 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 d9217fb9..541d141a 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 f134d6e2..910e5cf6 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 aadcdf2a..eca351d2 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 f76e9d91..2d37dbf4 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 f2c0c409..31ff5869 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 80a66d07..e24e7a38 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 672642e3..3eab015c 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 f659f745..41c8bbd7 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 40903389..e97a450d 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 3f7117e9..9013745a 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 6f249c9c..5ba32c12 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 51333543..b9f8fff8 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 e09fbd42..f60e21c1 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 40d53ed7..eeaeb47b 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 a6f97b2d..fe138502 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 77ee9baa..b866df5b 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 bcc9c455..a8d5183d 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 bcece142..4964d81e 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 80856a43..92b0e6c0 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 da510cd9..b68b27ee 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 ce253cf0..c11a97f9 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 77134450..d7e10bd9 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 d7863ad3..e6a6b368 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 1ac34b5a..3e979857 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 00000000..273cf142 --- /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 5be74c0e..0e600532 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 fee12b47..5774ba23 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 e6a6b368..1ff209f9 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 53039fc8..e2587cb1 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 6e6dac2a..a748105f 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 a4fe5bdb..ce8d1a0e 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 4f0f2a10..3d81d7cd 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 a93f9ee9..161f8b1c 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 3dc61064..b9a9979f 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 00000000..c8691f53 --- /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 0480e214..7f1f5832 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 e53f85aa..6c404e51 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 00000000..99951e04 --- /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 1944c4dd..d165db26 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 00000000..9ffdf475 --- /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 9f3e5f1d..cd7e3f40 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 e24e7a38..34a0a318 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 1c010166..071593f7 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); } }