Skip to content

Commit 756eed4

Browse files
authored
Merge pull request #192 from web-token/ES256K
ES256K Support added (experimental)
2 parents e5bdabd + 94ceabc commit 756eed4

File tree

4 files changed

+151
-1
lines changed

4 files changed

+151
-1
lines changed

src/Bundle/JoseFramework/Resources/config/Algorithms/signature_experimental.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,8 @@
4040
$container->set(Algorithm\HS256_64::class)
4141
->tag('jose.algorithm', ['alias' => 'HS256/64'])
4242
;
43+
44+
$container->set(Algorithm\ES256K::class)
45+
->tag('jose.algorithm', ['alias' => 'ES256K'])
46+
;
4347
};

src/Component/Core/Util/ECKey.php

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ public static function convertPublicKeyToPEM(JWK $jwk): string
3838
case 'P-256':
3939
$der = self::p256PublicKey();
4040

41+
break;
42+
case 'secp256k1':
43+
$der = self::p256KPublicKey();
44+
4145
break;
4246
case 'P-384':
4347
$der = self::p384PublicKey();
@@ -64,6 +68,10 @@ public static function convertPrivateKeyToPEM(JWK $jwk): string
6468
case 'P-256':
6569
$der = self::p256PrivateKey($jwk);
6670

71+
break;
72+
case 'secp256k1':
73+
$der = self::p256KPrivateKey($jwk);
74+
6775
break;
6876
case 'P-384':
6977
$der = self::p384PrivateKey($jwk);
@@ -102,6 +110,7 @@ private static function getNistCurveSize(string $curve): int
102110
{
103111
switch ($curve) {
104112
case 'P-256':
113+
case 'secp256k1':
105114
return 256;
106115
case 'P-384':
107116
return 384;
@@ -146,6 +155,8 @@ private static function getOpensslCurveName(string $curve): string
146155
switch ($curve) {
147156
case 'P-256':
148157
return 'prime256v1';
158+
case 'secp256k1':
159+
return 'secp256k1';
149160
case 'P-384':
150161
return 'secp384r1';
151162
case 'P-521':
@@ -170,6 +181,21 @@ private static function p256PublicKey(): string
170181
);
171182
}
172183

184+
private static function p256KPublicKey(): string
185+
{
186+
return pack(
187+
'H*',
188+
'3056' // SEQUENCE, length 86
189+
.'3010' // SEQUENCE, length 16
190+
.'0607' // OID, length 7
191+
.'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key
192+
.'0605' // OID, length 8
193+
.'2B8104000A' // 1.3.132.0.10 secp256k1
194+
.'0342' // BIT STRING, length 66
195+
.'00' // prepend with NUL - pubkey will follow
196+
);
197+
}
198+
173199
private static function p384PublicKey(): string
174200
{
175201
return pack(
@@ -212,7 +238,26 @@ private static function p256PrivateKey(JWK $jwk): string
212238
.$d
213239
.'a00a' // TAGGED OBJECT #0, length 10
214240
.'0608' // OID, length 8
215-
.'2a8648ce3d030107' // 1.3.132.0.34 = P-384 Curve
241+
.'2a8648ce3d030107' // 1.3.132.0.34 = P-256 Curve
242+
.'a144' // TAGGED OBJECT #1, length 68
243+
.'0342' // BIT STRING, length 66
244+
.'00' // prepend with NUL - pubkey will follow
245+
);
246+
}
247+
248+
private static function p256KPrivateKey(JWK $jwk): string
249+
{
250+
$d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 32, "\0", STR_PAD_LEFT))[1];
251+
252+
return pack(
253+
'H*',
254+
'3074' // SEQUENCE, length 84+length($d)=32
255+
.'020101' // INTEGER, 1
256+
.'0420' // OCTET STRING, length($d) = 32
257+
.$d
258+
.'a007' // TAGGED OBJECT #0, length 7
259+
.'0605' // OID, length 5
260+
.'2b8104000a' // 1.3.132.0.10 secp256k1
216261
.'a144' // TAGGED OBJECT #1, length 68
217262
.'0342' // BIT STRING, length 66
218263
.'00' // prepend with NUL - pubkey will follow
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* The MIT License (MIT)
7+
*
8+
* Copyright (c) 2014-2019 Spomky-Labs
9+
*
10+
* This software may be modified and distributed under the terms
11+
* of the MIT license. See the LICENSE file for details.
12+
*/
13+
14+
namespace Jose\Component\Signature\Algorithm;
15+
16+
final class ES256K extends ECDSA
17+
{
18+
public function name(): string
19+
{
20+
return 'ES256K';
21+
}
22+
23+
protected function getHashAlgorithm(): string
24+
{
25+
return 'sha256';
26+
}
27+
28+
protected function getSignaturePartLength(): int
29+
{
30+
return 64;
31+
}
32+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* The MIT License (MIT)
7+
*
8+
* Copyright (c) 2014-2019 Spomky-Labs
9+
*
10+
* This software may be modified and distributed under the terms
11+
* of the MIT license. See the LICENSE file for details.
12+
*/
13+
14+
namespace Jose\Component\Signature\Algorithm\Signature;
15+
16+
use Base64Url\Base64Url;
17+
use Jose\Component\Core\JWK;
18+
use Jose\Component\Signature\Algorithm\ES256K;
19+
use PHPUnit\Framework\TestCase;
20+
21+
/**
22+
* @group unit
23+
* @group NewAlgorithm
24+
*
25+
* @covers \Jose\Component\Signature\Algorithm\ES256K
26+
*
27+
* @internal
28+
*/
29+
class P256KSignatureTest extends TestCase
30+
{
31+
/**
32+
* @test
33+
*/
34+
public function es256KVerify()
35+
{
36+
$key = $this->getKey();
37+
$algorithm = new ES256K();
38+
$data = 'Hello';
39+
40+
static::assertTrue($algorithm->verify($key, $data, hex2bin('9c75b9d171d9690a37f2474d4bfab5c234911cb150950ea5cbfc9aedda5ec360725cc47978de95b4efb2a3ed617c7b36b1cd0a26b536662a79d0f3ae873a7924')));
41+
}
42+
43+
/**
44+
* @test
45+
*/
46+
public function es256KSignAndVerify()
47+
{
48+
$key = $this->getKey();
49+
$algorithm = new ES256K();
50+
$data = 'Hello';
51+
52+
static::assertEquals('ES256K', $algorithm->name());
53+
54+
$signature = $algorithm->sign($key, $data);
55+
56+
static::assertTrue($algorithm->verify($key, $data, $signature));
57+
}
58+
59+
private function getKey(): JWK
60+
{
61+
return new JWK([
62+
'kty' => 'EC',
63+
'crv' => 'secp256k1',
64+
'd' => Base64Url::encode(hex2bin('D1592A94BBB9B5D94CDC425FC7DA80B6A47863AE973A9D581FD9D8F29690B659')),
65+
'x' => Base64Url::encode(hex2bin('4B4DF318DE05BB8F3A115BF337F9BCBC55CA14B917B46BCB557D3C9A158D4BE0')),
66+
'y' => Base64Url::encode(hex2bin('627EB75731A8BBEBC7D9A3C57EC4D7DA2CBA6D2A28E7F45134921861FE1CF5D9')),
67+
]);
68+
}
69+
}

0 commit comments

Comments
 (0)