Skip to content

Commit f619e57

Browse files
authored
Fix authtoken signature validation (#10)
* Transcode signature only if it isn't in ASN1 format already + add unit test * Throw exception when openssl_verify returned -1 (error) * Reverse formatting * Use internal values for test
1 parent 8ba57d7 commit f619e57

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

src/util/AsnUtil.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@ public function __construct()
3434
throw new BadFunctionCallException("Utility class");
3535
}
3636

37+
public static function isSignatureInAsn1Format(string $signature): bool
38+
{
39+
$sigByteArray = unpack('C*', $signature);
40+
41+
// ASN.1 format: 0x30 b1 0x02 b2 r 0x02 b3 s.
42+
// Note: unpack() returns an array indexed from 1, not 0.
43+
$b1 = $sigByteArray[2];
44+
$b2 = $sigByteArray[4];
45+
$b3 = $sigByteArray[6 + $b2];
46+
47+
return $sigByteArray[1] == 0x30 // Sequence tag
48+
&& $sigByteArray[3] == 0x02 // First integer tag
49+
&& $sigByteArray[5 + $b2] == 0x02 // Second integer tag
50+
&& count($sigByteArray) == 2 + $b1 // Length of contents
51+
&& count($sigByteArray) == 6 + $b2 + $b3; // Total length
52+
}
53+
3754
public static function transcodeSignatureToDER(string $p1363): string
3855
{
3956
// P1363 format: r followed by s.

src/validator/AuthTokenSignatureValidator.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public function validate(string $algorithm, string $signature, $publicKey, strin
7272
$decodedSignature = base64_decode($signature);
7373

7474
// Note that in case of ECDSA, some eID cards output raw R||S, so we need to trascode it to DER
75-
if (in_array($algorithm, ["ES256", "ES384", "ES512"])) {
75+
if (in_array($algorithm, ["ES256", "ES384", "ES512"]) && !AsnUtil::isSignatureInAsn1Format($decodedSignature)) {
7676
$decodedSignature = AsnUtil::transcodeSignatureToDER($decodedSignature);
7777
}
7878

@@ -83,8 +83,8 @@ public function validate(string $algorithm, string $signature, $publicKey, strin
8383
$concatSignedFields = $originHash . $nonceHash;
8484

8585
$result = openssl_verify($concatSignedFields, $decodedSignature, $publicKey, $hashAlgorithm);
86-
if (!$result) {
87-
throw new AuthTokenSignatureValidationException();
86+
if ($result !== 1) {
87+
throw new AuthTokenSignatureValidationException($result === -1 ? openssl_error_string() : "Signature is invalid");
8888
}
8989
}
9090

tests/validator/AuthTokenSignatureValidatorTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
use GuzzleHttp\Psr7\Uri;
3131
use web_eid\web_eid_authtoken_validation_php\authtoken\WebEidAuthToken;
3232
use web_eid\web_eid_authtoken_validation_php\testutil\AbstractTestWithValidator;
33+
use phpseclib3\Crypt\EC;
3334
use phpseclib3\File\X509;
35+
use web_eid\web_eid_authtoken_validation_php\util\AsnUtil;
3436

3537
class AuthTokenSignatureValidatorTest extends TestCase
3638
{
@@ -63,4 +65,19 @@ public function testWhenValidRS256SignatureThenSucceeds(): void
6365

6466
$signatureValidator->validate("RS256", $authToken->getSignature(), $x509Certificate->getPublicKey(), AbstractTestWithValidator::VALID_CHALLENGE_NONCE);
6567
}
68+
69+
public function testESSignatureDecoding(): void
70+
{
71+
$this->expectNotToPerformAssertions();
72+
$signatureValidator = new AuthTokenSignatureValidator(new Uri("https://ria.ee"));
73+
74+
$authToken = new WebEidAuthToken(AbstractTestWithValidator::VALID_AUTH_TOKEN);
75+
$x509Certificate = new X509();
76+
$x509Certificate->loadX509($authToken->getUnverifiedCertificate());
77+
78+
$asn1Signature = base64_encode(AsnUtil::transcodeSignatureToDER(base64_decode($authToken->getSignature())));
79+
80+
$signatureValidator->validate("ES384", $authToken->getSignature(), $x509Certificate->getPublicKey(), AbstractTestWithValidator::VALID_CHALLENGE_NONCE);
81+
$signatureValidator->validate("ES384", $asn1Signature, $x509Certificate->getPublicKey(), AbstractTestWithValidator::VALID_CHALLENGE_NONCE);
82+
}
6683
}

0 commit comments

Comments
 (0)