Skip to content

Commit 8288a46

Browse files
authored
feat: add machine-readable validation reason codes (#7)
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent f062333 commit 8288a46

5 files changed

Lines changed: 28 additions & 0 deletions

File tree

src/Model/ValidationReason.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
// SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
4+
// SPDX-License-Identifier: AGPL-3.0-or-later
5+
6+
declare(strict_types=1);
7+
8+
namespace LibreSign\PdfSignatureValidator\Model;
9+
10+
enum ValidationReason: string
11+
{
12+
case DIGEST_MISMATCH = 'digest_mismatch';
13+
case NO_BYTE_RANGE = 'no_byte_range';
14+
case NO_BINARY_SIGNATURE = 'no_binary_signature';
15+
case SIGNATURE_CERTIFICATE_MISMATCH = 'signature_certificate_mismatch';
16+
}

src/Model/ValidationResult.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ final class ValidationResult
1212
public function __construct(
1313
public readonly ValidationState $state,
1414
public readonly ?string $reason = null,
15+
public readonly ?ValidationReason $reasonCode = null,
1516
) {
1617
$this->isValid = $state->isValid();
1718
}

src/Parser/PdfSignatureValidator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use LibreSign\PdfSignatureValidator\Exception\UnsignedPdfException;
1111
use LibreSign\PdfSignatureValidator\Model\ExtractedSignature;
12+
use LibreSign\PdfSignatureValidator\Model\ValidationReason;
1213
use LibreSign\PdfSignatureValidator\Model\ValidationResult;
1314
use LibreSign\PdfSignatureValidator\Model\ValidationState;
1415

@@ -101,11 +102,13 @@ public function validateFromString(string $pdfContent, ?array $trustedRoots = nu
101102
'signatureValidation' => new ValidationResult(
102103
ValidationState::NOT_VERIFIED,
103104
'No binary signature',
105+
ValidationReason::NO_BINARY_SIGNATURE,
104106
),
105107
'certificates' => [],
106108
'certificateValidation' => new ValidationResult(
107109
ValidationState::CERT_NOT_VERIFIED,
108110
'No binary signature',
111+
ValidationReason::NO_BINARY_SIGNATURE,
109112
),
110113
];
111114
continue;

src/Parser/SignatureValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace LibreSign\PdfSignatureValidator\Parser;
99

10+
use LibreSign\PdfSignatureValidator\Model\ValidationReason;
1011
use LibreSign\PdfSignatureValidator\Model\ValidationResult;
1112
use LibreSign\PdfSignatureValidator\Model\ValidationState;
1213

@@ -33,6 +34,7 @@ public function verifyDigest(
3334
return new ValidationResult(
3435
ValidationState::NOT_VERIFIED,
3536
'No ByteRange in signature',
37+
ValidationReason::NO_BYTE_RANGE,
3638
);
3739
}
3840

@@ -47,6 +49,7 @@ public function verifyDigest(
4749
return new ValidationResult(
4850
ValidationState::DIGEST_MISMATCH,
4951
'PDF content hash does not match signed digest',
52+
ValidationReason::DIGEST_MISMATCH,
5053
);
5154
}
5255

@@ -66,6 +69,7 @@ public function verifySignature(
6669
return new ValidationResult(
6770
ValidationState::SIGNATURE_INVALID,
6871
'Signature does not match certificate',
72+
ValidationReason::SIGNATURE_CERTIFICATE_MISMATCH,
6973
);
7074
}
7175

tests/Unit/Parser/SignatureValidatorTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace LibreSign\PdfSignatureValidator\Tests\Unit\Parser;
99

10+
use LibreSign\PdfSignatureValidator\Model\ValidationReason;
1011
use LibreSign\PdfSignatureValidator\Parser\CertificateExtractor;
1112
use LibreSign\PdfSignatureValidator\Parser\SignatureValidator;
1213
use PHPUnit\Framework\TestCase;
@@ -67,6 +68,7 @@ public function testVerifyDigestWithMismatchedContent(): void
6768

6869
$this->assertFalse($result->isValid);
6970
$this->assertSame('Digest Mismatch.', $result->state->value);
71+
$this->assertSame(ValidationReason::DIGEST_MISMATCH, $result->reasonCode);
7072
}
7173

7274
public function testVerifyDigestWithoutByteRange(): void
@@ -79,6 +81,7 @@ public function testVerifyDigestWithoutByteRange(): void
7981
);
8082

8183
$this->assertFalse($result->isValid);
84+
$this->assertSame(ValidationReason::NO_BYTE_RANGE, $result->reasonCode);
8285
}
8386

8487
public function testVerifySignatureWithValidOpenSslSignature(): void
@@ -128,5 +131,6 @@ public function testVerifySignatureWithInvalidSignatureBytes(): void
128131
);
129132

130133
$this->assertFalse($result->isValid);
134+
$this->assertSame(ValidationReason::SIGNATURE_CERTIFICATE_MISMATCH, $result->reasonCode);
131135
}
132136
}

0 commit comments

Comments
 (0)