Skip to content

Commit 6f568e2

Browse files
committed
Add support for ECDSA signatures
1 parent 1ccb48d commit 6f568e2

5 files changed

Lines changed: 96 additions & 1 deletion

File tree

‎src/Alg/Signature/ECDSA.php‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\XMLSecurity\Alg\Signature;
6+
7+
use SimpleSAML\XMLSecurity\Constants as C;
8+
use SimpleSAML\XMLSecurity\Key\AsymmetricKey;
9+
10+
/**
11+
* Class implementing the ECDSA signature algorithm.
12+
*
13+
* @package simplesamlphp/xml-security
14+
*/
15+
final class ECDSA extends AbstractSigner implements SignatureAlgorithmInterface
16+
{
17+
/**
18+
* RSA constructor.
19+
*
20+
* @param \SimpleSAML\XMLSecurity\Key\AsymmetricKey $key The asymmetric key (either public or private) to use.
21+
* @param string $algId The identifier of this algorithm.
22+
*/
23+
public function __construct(
24+
#[\SensitiveParameter]
25+
AsymmetricKey $key,
26+
string $algId,
27+
) {
28+
parent::__construct($key, $algId, C::$ECDSA_DIGESTS[$algId]);
29+
}
30+
31+
32+
/**
33+
* @return string[]
34+
*/
35+
public static function getSupportedAlgorithms(): array
36+
{
37+
return array_keys(C::$ECDSA_DIGESTS);
38+
}
39+
}

‎src/Alg/Signature/SignatureAlgorithmFactory.php‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ final class SignatureAlgorithmFactory
2525
/**
2626
* An array of blacklisted algorithms.
2727
*
28-
* Defaults to RSA-SHA1, RSAPSS-SHA1 & HMAC-SHA1 due to the weakness of SHA1.
28+
* Defaults to ECDSA-SHA1, RSA-SHA1, RSAPSS-SHA1 & HMAC-SHA1 due to the weakness of SHA1.
2929
*
3030
* @var string[]
3131
*/
3232
public const array DEFAULT_BLACKLIST = [
33+
C::SIG_ECDSA_SHA1,
3334
C::SIG_RSA_SHA1,
3435
C::SIG_RSA_PSS_SHA1,
3536
C::SIG_HMAC_SHA1,
@@ -41,6 +42,7 @@ final class SignatureAlgorithmFactory
4142
* @var class-string[]
4243
*/
4344
private const array SUPPORTED_DEFAULTS = [
45+
ECDSA::class,
4446
RSA::class,
4547
HMAC::class,
4648
];

‎src/Constants.php‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ class Constants extends \SimpleSAML\XML\Constants
116116

117117
public const string SIG_RSA_RIPEMD160 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160';
118118

119+
/**
120+
* ECDSA Signature algorithms
121+
*/
122+
public const string SIG_ECDSA_SHA1 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1';
123+
public const string SIG_ECDSA_SHA224 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224';
124+
public const string SIG_ECDSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256';
125+
public const string SIG_ECDSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384';
126+
public const string SIG_ECDSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512';
127+
119128
/**
120129
* HMAC Signature algorithms
121130
*/
@@ -240,6 +249,15 @@ class Constants extends \SimpleSAML\XML\Constants
240249
self::BLOCK_ENC_AES256_GCM => 16,
241250
];
242251

252+
/** @var array<string, string> */
253+
public static array $ECDSA_DIGESTS = [
254+
self::SIG_ECDSA_SHA1 => self::DIGEST_SHA1,
255+
self::SIG_ECDSA_SHA224 => self::DIGEST_SHA224,
256+
self::SIG_ECDSA_SHA256 => self::DIGEST_SHA256,
257+
self::SIG_ECDSA_SHA384 => self::DIGEST_SHA384,
258+
self::SIG_ECDSA_SHA512 => self::DIGEST_SHA512,
259+
];
260+
243261
/** @var array<string, string> */
244262
public static array $RSA_DIGESTS = [
245263
self::SIG_RSA_SHA1 => self::DIGEST_SHA1,

‎src/XML/ds/SignatureMethod.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public function __construct(
5151
Assert::oneOf(
5252
$Algorithm->getValue(),
5353
array_merge(
54+
array_keys(C::$ECDSA_DIGESTS),
5455
array_keys(C::$RSA_DIGESTS),
5556
array_keys(C::$HMAC_DIGESTS),
5657
),

‎tests/XML/SignedElementTest.php‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,41 @@ public function testSuccessfulVerifyingRsaPssSignature(): void
328328
}
329329

330330

331+
/**
332+
* Verify an ECDSA signature
333+
*/
334+
public function testSuccessfulVerifyingEcdsaSignature(): void
335+
{
336+
// sign using ECDSA_SHA256
337+
$customSignable = $this->sign(C::SIG_ECDSA_SHA256);
338+
// No-op to _actually_ sign the element and set the signature-property.
339+
$customSignable = CustomSignable::fromXML($customSignable->toXML());
340+
341+
$signature = $customSignable->getSignature();
342+
343+
$this->assertEquals(
344+
C::SIG_ECDSA_SHA256,
345+
$signature
346+
->getSignedInfo()
347+
->getSignatureMethod()
348+
->getAlgorithm()
349+
->getValue(),
350+
);
351+
352+
$certificate = new X509Certificate($this->certificate);
353+
354+
$factory = new SignatureAlgorithmFactory();
355+
$verifier = $factory->getAlgorithm(
356+
C::SIG_ECDSA_SHA256,
357+
$certificate->getPublicKey(),
358+
);
359+
360+
$verified = $customSignable->verify($verifier);
361+
362+
$this->assertInstanceOf(CustomSignable::class, $verified);
363+
}
364+
365+
331366
/**
332367
* Negative: verify a RSA-PSS signature using PKCS#1 v1.5
333368
*/

0 commit comments

Comments
 (0)