Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .ci-tools/phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3778,6 +3778,16 @@ parameters:
count: 1
path: ../src/Bundle/Resources/config/Algorithms/signature_eddsa.php

-
rawMessage: '''
Access to constant on deprecated class Jose\Experimental\Signature\ES256K:
since 4.3.0, will be removed in 5.0.0. "ES256K" is a standard algorithm (RFC 8812) and moved to the
library: use Jose\Component\Signature\Algorithm\ES256K instead.
'''
identifier: classConstant.deprecatedClass
count: 1
path: ../src/Bundle/Resources/config/Algorithms/signature_experimental.php

-
rawMessage: Access to constant on internal class Jose\Component\Core\Util\Ecc\NistCurve.
identifier: classConstant.internalClass
Expand Down
6 changes: 6 additions & 0 deletions src/Bundle/Resources/config/Algorithms/signature_ecdsa.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Jose\Component\Signature\Algorithm\ES256;
use Jose\Component\Signature\Algorithm\ES256K;
use Jose\Component\Signature\Algorithm\ES384;
use Jose\Component\Signature\Algorithm\ES512;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
Expand All @@ -28,4 +29,9 @@
->tag('jose.algorithm', [
'alias' => 'ES512',
]);

$container->set(ES256K::class)
->tag('jose.algorithm', [
'alias' => 'ES256K',
]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Jose\Component\Signature\Algorithm\ES256K as StandardES256K;
use Jose\Experimental\Signature\Blake2b;
use Jose\Experimental\Signature\ES256K;
use Jose\Experimental\Signature\HS1;
Expand Down Expand Up @@ -40,9 +41,11 @@
]);

$container->set(ES256K::class)
->tag('jose.algorithm', [
'alias' => 'ES256K',
]);
->deprecate(
'web-token/jwt-framework',
'4.3.0',
'The "%service_id%" service is deprecated: the "ES256K" algorithm moved to the library and is registered as "' . StandardES256K::class . '", under the same "ES256K" alias.'
);

$container->set(Blake2b::class)
->tag('jose.algorithm', [
Expand Down
2 changes: 2 additions & 0 deletions src/Bundle/Resources/config/analyzers.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Jose\Component\Core\Util\Ecc\NistCurve;
use Jose\Component\KeyManagement\Analyzer\AlgorithmAnalyzer;
use Jose\Component\KeyManagement\Analyzer\ES256KeyAnalyzer;
use Jose\Component\KeyManagement\Analyzer\ES256KKeyAnalyzer;
use Jose\Component\KeyManagement\Analyzer\ES384KeyAnalyzer;
use Jose\Component\KeyManagement\Analyzer\ES512KeyAnalyzer;
use Jose\Component\KeyManagement\Analyzer\HS256KeyAnalyzer;
Expand Down Expand Up @@ -51,6 +52,7 @@

if (class_exists(NistCurve::class)) {
$container->set(ES256KeyAnalyzer::class);
$container->set(ES256KKeyAnalyzer::class);
$container->set(ES384KeyAnalyzer::class);
$container->set(ES512KeyAnalyzer::class);
}
Expand Down
34 changes: 16 additions & 18 deletions src/Experimental/Signature/ES256K.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,24 @@

namespace Jose\Experimental\Signature;

use Jose\Component\Signature\Algorithm\ECDSA;
use Override;
use Jose\Component\Signature\Algorithm\ES256K as StandardES256K;
use function trigger_deprecation;

final readonly class ES256K extends ECDSA
/**
* @deprecated since 4.3.0, will be removed in 5.0.0. "ES256K" is a standard algorithm (RFC 8812) and moved to the
* library: use Jose\Component\Signature\Algorithm\ES256K instead.
*/
final readonly class ES256K extends StandardES256K
{
#[Override]
public function name(): string
public function __construct()
{
return 'ES256K';
}

#[Override]
protected function getHashAlgorithm(): string
{
return 'sha256';
}

#[Override]
protected function getSignaturePartLength(): int
{
return 64;
parent::__construct();
trigger_deprecation(
'web-token/jwt-framework',
'4.3.0',
'The class "%s" is deprecated and will be removed in 5.0.0. The "ES256K" algorithm is a standard one and moved to the library: use "%s" instead.',
self::class,
StandardES256K::class
);
}
}
29 changes: 29 additions & 0 deletions src/Library/Core/Util/Ecc/KoblitzCurve.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Jose\Component\Core\Util\Ecc;

use Brick\Math\BigInteger;

/**
* The Koblitz curve secp256k1 (SEC 2 section 2.4.1), registered for JOSE by RFC 8812 section 4 under the "crv" value
* "secp256k1" and used by the "ES256K" signature algorithm.
*
* @internal
*/
final readonly class KoblitzCurve
{
public static function secp256k1(): Curve
{
$p = BigInteger::fromBase('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16);
$a = BigInteger::zero();
$b = BigInteger::of(7);
$x = BigInteger::fromBase('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
$y = BigInteger::fromBase('483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 16);
$n = BigInteger::fromBase('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 16);
$generator = Point::create($x, $y, $n);

return new Curve(256, $p, $a, $b, $generator);
}
}
39 changes: 39 additions & 0 deletions src/Library/KeyManagement/Analyzer/ES256KKeyAnalyzer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Jose\Component\KeyManagement\Analyzer;

use Jose\Component\Core\Util\Ecc\Curve;
use Jose\Component\Core\Util\Ecc\KoblitzCurve;
use Override;

/**
* Checks the keys on the secp256k1 curve used by the "ES256K" algorithm (RFC 8812).
*/
final readonly class ES256KKeyAnalyzer extends ESKeyAnalyzer
{
#[Override]
protected function getAlgorithmName(): string
{
return 'ES256K';
}

#[Override]
protected function getCurveName(): string
{
return 'secp256k1';
}

#[Override]
protected function getCurve(): Curve
{
return KoblitzCurve::secp256k1();
}

#[Override]
protected function getKeySize(): int
{
return 256;
}
}
34 changes: 34 additions & 0 deletions src/Library/Signature/Algorithm/ES256K.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Jose\Component\Signature\Algorithm;

use Override;

/**
* The "ES256K" algorithm of RFC 8812 section 3: ECDSA over the secp256k1 curve with SHA-256.
*
* The algorithm lived in the experimental package until 4.3, although RFC 8812 has registered it since 2020. The
* class is not final because the deprecated Jose\Experimental\Signature\ES256K extends it until 5.0.0.
*/
readonly class ES256K extends ECDSA
{
#[Override]
public function name(): string
{
return 'ES256K';
}

#[Override]
protected function getHashAlgorithm(): string
{
return 'sha256';
}

#[Override]
protected function getSignaturePartLength(): int
{
return 64;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Jose\Component\Core\AlgorithmManagerFactory;
use Jose\Component\Encryption\Algorithm\ContentEncryptionAlgorithm;
use Jose\Component\Signature\Algorithm\ES256K as StandardES256K;
use Jose\Experimental\ContentEncryption\A128CCM_16_128;
use Jose\Experimental\ContentEncryption\A128CCM_16_64;
use Jose\Experimental\ContentEncryption\A128CCM_64_128;
Expand All @@ -17,8 +18,10 @@
use Jose\Experimental\KeyEncryption\A128CTR;
use Jose\Experimental\Signature\ES256K;
use Jose\Experimental\Signature\HS1;
use Jose\Tests\Bundle\JoseFramework\TestBundle\Service\DeprecatedES256KConsumer;
use Jose\Tests\Bundle\JoseFramework\WebTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
use PHPUnit\Framework\Attributes\Test;
use function extension_loaded;

Expand Down Expand Up @@ -49,11 +52,33 @@ public function theExperimentalAlgorithmIsRegistered(string $alias): void
public function theExperimentalClassesAreTheOnesOfTheExperimentalPackage(): void
{
static::assertTrue(class_exists(HS1::class));
static::assertTrue(class_exists(ES256K::class));
static::assertTrue(class_exists(A128CTR::class));
static::assertTrue(class_exists(A128CCM_16_128::class));
}

/**
* "ES256K" is a standard algorithm (RFC 8812) and moved to the library in 4.3: the "ES256K" alias is served by
* the library class, and the experimental class survives as a deprecated service until 5.0.0.
*/
#[Test]
#[IgnoreDeprecations]
public function es256kIsServedByTheLibraryClassAndTheExperimentalServiceIsDeprecated(): void
{
static::ensureKernelShutdown();
$container = static::createClient()
->getContainer();

/** @var AlgorithmManagerFactory $factory */
$factory = $container->get(AlgorithmManagerFactory::class);
$algorithm = $factory->create(['ES256K'])->get('ES256K');
static::assertSame(StandardES256K::class, $algorithm::class);

$consumer = $container->get(DeprecatedES256KConsumer::class);
static::assertInstanceOf(DeprecatedES256KConsumer::class, $consumer);
static::assertInstanceOf(ES256K::class, $consumer->algorithm);
static::assertSame('ES256K', $consumer->algorithm->name());
}

/**
* Two of them reported the name of another one, so they replaced it in the manager and were unreachable.
*/
Expand Down Expand Up @@ -87,7 +112,6 @@ public static function aliases(): iterable
yield 'RS1' => ['RS1'];
yield 'HS1' => ['HS1'];
yield 'HS256/64' => ['HS256/64'];
yield 'ES256K' => ['ES256K'];
yield 'BLAKE2B' => ['BLAKE2B'];
yield 'A128CTR' => ['A128CTR'];
yield 'A192CTR' => ['A192CTR'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Jose\Tests\Bundle\JoseFramework\TestBundle\Checker\CustomChecker;
use Jose\Tests\Bundle\JoseFramework\TestBundle\Service\DeprecatedES256KConsumer;
use Jose\Tests\Bundle\JoseFramework\TestBundle\Service\NestedTokenServiceConsumer;
use Psr\Clock\ClockInterface;
use Symfony\Component\Clock\NativeClock;
Expand Down Expand Up @@ -30,4 +31,8 @@
$container->set(NestedTokenServiceConsumer::class)
->public()
;

$container->set(DeprecatedES256KConsumer::class)
->public()
;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Jose\Tests\Bundle\JoseFramework\TestBundle\Service;

use Jose\Experimental\Signature\ES256K;

/**
* A service autowired with the deprecated experimental "ES256K" class, which the bundle keeps until 5.0.0.
*/
final readonly class DeprecatedES256KConsumer
{
public function __construct(
public ES256K $algorithm
) {
}
}
Loading
Loading