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 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" + } } diff --git a/src/Experimental/KeyEncryption/Chacha20Poly1305.php b/src/Experimental/KeyEncryption/Chacha20Poly1305.php index 5e9126a3..6345609a 100644 --- a/src/Experimental/KeyEncryption/Chacha20Poly1305.php +++ b/src/Experimental/KeyEncryption/Chacha20Poly1305.php @@ -47,15 +47,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) || strlen($tag) !== 16) { throw new RuntimeException('Unable to encrypt the CEK'); } + $additionalHeader['nonce'] = Base64UrlSafe::encodeUnpadded($nonce); + $additionalHeader['tag'] = Base64UrlSafe::encodeUnpadded($tag); + return $result; } @@ -72,8 +72,14 @@ public function decryptKey(JWK $key, string $encrypted_cek, array $header): stri if (strlen($nonce) !== 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 (strlen($tag) !== 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/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php b/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php index eb9c0ad3..1faaac91 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/PBES2AESKW.php @@ -16,12 +16,16 @@ use function in_array; use function is_int; use function is_string; +use function sprintf; abstract readonly 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'); @@ -139,6 +143,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; diff --git a/src/Library/Encryption/Algorithm/KeyEncryption/RSA15.php b/src/Library/Encryption/Algorithm/KeyEncryption/RSA15.php index 8e7ad55c..5f65b2b7 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/RSA15.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/RSA15.php @@ -4,17 +4,54 @@ 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 Override; +use function is_string; final readonly 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, + ]; + #[Override] public function name(): string { return 'RSA1_5'; } + /** + * @param array $header + */ + #[Override] + 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) + ); + } + #[Override] protected function getEncryptionMode(): int { @@ -26,4 +63,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 b36d1738..453630e3 100644 --- a/src/Library/Encryption/Algorithm/KeyEncryption/Util/RSACrypt.php +++ b/src/Library/Encryption/Algorithm/KeyEncryption/Util/RSACrypt.php @@ -47,8 +47,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) { @@ -57,7 +62,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.'); } @@ -86,7 +91,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 (strlen($c) !== $key->getModulusLength()) { throw new InvalidArgumentException('Unable to decrypt'); @@ -94,16 +99,71 @@ 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 = substr($em, 2, (int) strpos($em, chr(0), 2) - 2); + $m = substr($em, strlen($ps) + 3); + if (strlen($ps) < 8) { + throw new InvalidArgumentException('Unable to decrypt'); + } + + return $m; } - $ps = substr($em, 2, (int) strpos($em, chr(0), 2) - 2); - $m = substr($em, strlen($ps) + 3); - if (strlen($ps) < 8) { - throw new InvalidArgumentException('Unable to decrypt'); + + return self::extractRSA15KeyOrRandom($em, $expectedKeyLength); + } + + private static function extractRSA15KeyOrRandom(string $em, int $expectedKeyLength): string + { + $k = strlen($em); + $random = random_bytes($expectedKeyLength); + + if ($k < $expectedKeyLength + 11) { + return $random; + } + $candidate = substr($em, $k - $expectedKeyLength); + + $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; } - return $m; + $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), strlen($a)); + + return ($a & $mask) | ($b & ~$mask); } /** 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(); diff --git a/src/Library/Signature/JWSVerifier.php b/src/Library/Signature/JWSVerifier.php index 6be08e72..97349e61 100644 --- a/src/Library/Signature/JWSVerifier.php +++ b/src/Library/Signature/JWSVerifier.php @@ -141,16 +141,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/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" }, 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); + } +} 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', + ]); + } +} 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/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)), + ]); + } +} 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); } }