Bezpieczeństwo / Podpisy: CMS, znacznik czasu RFC 3161, LTV, zaufanie
W skrócie
Dział zatytułowany „W skrócie”Ta strona opisuje powierzchnię podpisywania w NextPDF Core: tworzenie podpisu w składni Content Management Syntax (CMS), stosowanie znacznika czasu Request for Comments (RFC) 3161, weryfikowanie łańcucha certyfikatów względem RFC 5280 oraz sprawdzanie unieważnienia za pośrednictwem protokołu Online Certificate Status Protocol (OCSP) i listy unieważnionych certyfikatów (CRL). Opis pozostaje na poziomie zachowania. Klasy implementacyjne Core są wewnętrzne: kod produkcyjny korzysta z kontraktu SignerInterface, a nie z konkretnych typów NextPDF\Security\Signature. O tym, czy utworzony podpis weryfikuje się pomyślnie, decyduje weryfikator wraz ze skonfigurowanymi kotwicami zaufania. Ten wynik pozostaje poza kontrolą wytwórcy; strona zaznacza to wszędzie tam, gdzie ma to znaczenie.
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/core:^3Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”Core buduje strukturę CMS SignedData na podstawie zakresu bajtów, a następnie przechowuje ją jako dane zakodowane w Distinguished Encoding Rules (DER) we wpisie Contents słownika podpisu — ISO 32000-2 §12.8.1. Struktura ta zawiera podpisane atrybuty SignerInfo, w tym content-type oraz message-digest — RFC 5652 §5.3. Weryfikator ponownie oblicza skrót zawartości i porównuje go z atrybutem message-digest. Wynik porównania musi być zgodny, aby podpis był prawidłowy — RFC 5652 §5.4. SignerInfo zawiera również identyfikator algorytmu skrótu oraz blok podpisanych atrybutów — RFC 5652 §5. Core używa biblioteki phpseclib3 w dostarczanych ścieżkach podpisywania programowego: RSA, RSASSA-PSS, ECDSA oraz Ed25519.
Znacznik czasu RFC 3161 to wymiana żądanie–odpowiedź z urzędem znakowania czasem (Time-Stamping Authority, TSA), który zwraca strukturę TSTInfo — RFC 3161 §2.4.1. Każdy token zawiera serialNumber unikatowy dla wystawiającego TSA — RFC 3161 §2.4.2 — oraz genTime wyrażony w czasie uniwersalnym koordynowanym (UTC), czyli moment, w którym token został utworzony — RFC 3161 §2.4.2.
Walidacja zaufania obejmuje dwa sprawdzenia. Walidacja ścieżki przechodzi od certyfikatu podpisującego do kotwicy zaufania, sprawdzając podstawowe ograniczenia oraz dane wejściowe budowy ścieżki — RFC 5280 §6.1. Sprawdzanie unieważnienia odpytuje responder OCSP lub odczytuje CRL: odpowiedź OCSP raportuje good, revoked lub unknown — RFC 6960 §2.2 — a pola thisUpdate i nextUpdate odpowiedzi określają, na ile aktualny jest ten status — RFC 6960 §4.2. Wywołujący dostarcza kotwice zaufania oraz politykę aktualności unieważnienia. Silnik prowadzi walidację względem tych danych wejściowych i nie dostarcza wbudowanej listy zaufania.
Powierzchnia API
Dział zatytułowany „Powierzchnia API”| Typ | Rodzaj | Rola | Stabilność | Od wersji |
|---|---|---|---|---|
SignerInterface | interfejs (NextPDF\Contracts) | Kontrakt podpisywania, od którego zależy kod wywołujący | stabilny | 1.0.0 |
SignatureLevel | enum | Selektor poziomu PDF Advanced Electronic Signatures (PAdES) oraz sonda dostępności | stabilny | 1.0.0 |
Rfc5280PathValidator | interfejs | Punkt wejścia walidacji ścieżki certyfikacji (validate(...)) | stabilny (zamrożony w wersji 3.1.0) | 3.1.0 |
RevocationStatus | enum | Wynik OCSP / CRL: good, revoked, unknown | stabilny | 3.1.0 |
CaTrustAnchorBundle | typ | Zestaw kotwic zaufania dostarczany przez wywołującego | stabilny | 3.1.0 |
TstInfo | typ | Sparsowane pola znacznika czasu RFC 3161 | stabilny | 3.2.0 |
SignerInterface::sign() zwraca obiekt SignatureResult. Jego metoda toHex() zwraca ciąg szesnastkowy /Contents, a właściwość cmsSignedData przechowuje surowe bajty DER. Konkretne klasy NextPDF\Security\Signature, które implementują to zachowanie, są wewnętrzne (stability: internal w manifeście modułu). Nie są częścią publicznego API i mogą się zmienić bez podniesienia wersji głównej. Należy polegać na kontraktach i typach wyliczeniowych wymienionych powyżej.
Przykład kodu — szybki start
Dział zatytułowany „Przykład kodu — szybki start”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\SignerInterface;
/** * Produce the CMS SignedData hex for a PDF /Contents field. * * @param SignerInterface $signer A Core or Premium signer. * @param string $byteRange The PDF byte range to sign. * * @return string Hex-encoded CMS SignedData. */function sign(SignerInterface $signer, string $byteRange): string{ return $signer->sign($byteRange)->toHex();}Kod wywołujący zależy od kontraktu. Programowy podpisujący Core oraz podpisujący Premium oparty na sprzętowym module bezpieczeństwa (Hardware Security Module, HSM) implementują SignerInterface, więc ten kod nie zmienia się między edycjami.
Przykład kodu — produkcja
Dział zatytułowany „Przykład kodu — produkcja”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\SignerInterface;use NextPDF\Contracts\TimestampProviderInterface;use NextPDF\Exception\NextPdfException;use Psr\Log\LoggerInterface;
final readonly class TimestampedSigner{ public function __construct( private SignerInterface $signer, private TimestampProviderInterface $timestamps, private LoggerInterface $logger, ) {}
/** * Sign a byte range, then timestamp the CMS structure. * * The timestamp's trust still depends on the verifier accepting the * Time-Stamping Authority; this method only produces the structure. * * @param string $byteRange The PDF byte range to sign. * * @return array{cms: string, tst: string} */ public function sign(string $byteRange): array { try { $signature = $this->signer->sign($byteRange); $token = $this->timestamps->getTimestamp($signature->cmsSignedData);
return ['cms' => $signature->toHex(), 'tst' => $token]; } catch (NextPdfException $e) { $this->logger->error('Signing failed', ['error' => $e->getMessage()]);
throw $e; } }}Dostawca znaczników czasu jest wstrzykiwany, dzięki czemu wdrożenie może przypiąć własny urząd znakowania czasem. Blok catch rejestruje błąd i ponownie zgłasza wyjątek. Nie ukrywa awarii, więc ścieżka podpisywania pozostaje fail-closed.
Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Utworzony podpis nie jest podpisem zweryfikowanym. Walidacja ścieżki i sprawdzanie unieważnienia odbywają się po stronie weryfikatora, z użyciem kotwic zaufania tego weryfikatora. Wytwórca nie może zagwarantować wyniku.
- Skrót zakresu bajtów wyklucza wartość podpisu. Skrót obejmujący oktety
Contentsnie może się zweryfikować — ISO 32000-2 §12.8.1. - Status unieważnienia ma okno aktualności. Odpowiedź OCSP jest aktualna tylko w przedziale
thisUpdate/nextUpdate— RFC 6960 §4.2. Nieaktualna odpowiedź nie zastępuje świeżego sprawdzenia w momencie walidacji. - Silnik nie dostarcza wbudowanej listy zaufania.
CaTrustAnchorBundlejest dostarczany przez wywołującego; pusty zestaw oznacza, że żaden łańcuch się nie waliduje, zgodnie z założeniem. - OCSP
unknownto nie to samo cogood. Traktujunknownjako brak rozstrzygnięcia, a nie jako domniemane zaliczenie — RFC 6960 §2.2. - Przechowywanie kluczy w HSM, podpisywanie odroczone i w chmurze oraz wytwórca PAdES B-LT / B-LTA nie są dostępne w Core. Wybranie tych ścieżek w dystrybucji Core kończy się niepowodzeniem fail-closed z komunikatem wskazującym brakujący komponent Enterprise.
Wydajność
Dział zatytułowany „Wydajność”Podpis programowy zajmuje pojedyncze milisekundy. Dodanie znacznika czasu dokłada jedną rundę sieciową do TSA. Walidacja ścieżki jest lokalna, gdy certyfikaty znajdują się w pamięci; sprawdzanie unieważnienia dodaje jedno pobranie OCSP lub CRL na każdy certyfikat w łańcuchu. Budżet czasu rzeczywistego 1500 ms obejmuje jeden podpis ze znacznikiem czasu ze zdalnego TSA na rozgrzanym połączeniu. Sprawdzanie unieważnienia względem wolnego punktu końcowego przekracza ten budżet i powinno znajdować się poza ścieżką żądania. Profil odtwarzalności to structural: znacznik czasu osadza moment podpisania, więc dwa uruchomienia różnią się bajtami znacznika czasu, podczas gdy struktura dokumentu jest identyczna.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”To podstawowa granica kryptograficzna silnika, dlatego model zagrożeń jest określony wprost. Silnik sam oblicza zakres bajtów i nigdy nie przyjmuje go od wywołującego. Ścieżka podpisywania jest fail-closed: awaria prymitywu lub brak możliwości skutkuje typowanym wyjątkiem i nigdy po cichu nie przechodzi na słabszy algorytm. Na poziomach wymagających znacznika czasu (B-T, B-LT, B-LTA) urząd znakowania czasem zwracający pusty token stanowi błąd krytyczny: podpis jest odrzucany, a nie emitowany po cichu bez znacznika czasu w obniżonym stanie, chyba że podłączono procedurę obsługi błędu autoryzującą udokumentowaną degradację. Zaufanie jest z założenia kontrolowane przez wywołującego: kotwice i polityka unieważnienia są danymi wejściowymi, a nie wartościami domyślnymi silnika, ponieważ wytwórca zapewniający o własnym zaufaniu twierdziłby o fakcie, który może ustalić wyłącznie weryfikator. Zaufanie do znacznika czasu sprowadza się do zaufania do urzędu znakowania czasem, który można wstrzyknąć, dzięki czemu wdrożenie może przypiąć własny. Ta strona jest oznaczona jako export_control_class: legal-review-required, ponieważ dotyczy podpisywania kryptograficznego; każde źródło normatywne jest parafrazowane i żadne nie jest odtwarzane, zgodnie z higieną cytowania.
Zgodność
Dział zatytułowany „Zgodność”| Twierdzenie | Norma | Klauzula | Dowód |
|---|---|---|---|
Podpis CMS jest przechowywany w postaci zakodowanej w DER we wpisie Contents słownika podpisu. | ISO 32000-2 | §12.8.1 | |
| SignerInfo zawiera podpisane atrybuty content-type i message-digest. | RFC 5652 | §5.3 | |
| Weryfikator ponownie oblicza skrót zawartości i porównuje go z atrybutem message-digest. | RFC 5652 | §5.4 | |
| Token znacznika czasu jest tworzony przez RFC 3161 TSA i zawiera unikatowy serialNumber oraz genTime w UTC. | RFC 3161 | §2.4.1, §2.4.2 | ,, |
| Walidacja ścieżki certyfikacji sprawdza podstawowe ograniczenia oraz dane wejściowe ścieżki od podpisującego do kotwicy zaufania. | RFC 5280 | §6.1 | , |
| OCSP raportuje certStatus jako good, revoked lub unknown, ograniczony przez thisUpdate / nextUpdate. | RFC 6960 | §2.2, §4.2 | , |
Wszystkie klauzule są parafrazowane. NextPDF nie odtwarza tekstu normatywnego. W celu zapoznania się z miarodajnym brzmieniem należy sięgnąć do opublikowanych norm.
Kontekst komercyjny
Dział zatytułowany „Kontekst komercyjny”Core dostarcza programowy podpisujący CMS (RSA, RSASSA-PSS, ECDSA, Ed25519), obsługę znaczników czasu RFC 3161, walidację ścieżki RFC 5280 oraz sprawdzanie unieważnienia OCSP / CRL. Przechowywanie kluczy w HSM i Public-Key Cryptography Standards #11 (PKCS#11), podpisywanie odroczone i w chmurze, wytwórca PAdES B-LT i B-LTA oraz profil polityki kryptograficznej Federal Information Processing Standards (FIPS) 140-3 są dostarczane w edycjach Pro i Enterprise. Core rozwiązuje je w czasie wykonywania względem kontraktu, dzięki czemu silnik open source nie niesie żadnej zależności komercyjnej, a API nie zmienia się po aktualizacji.
Zobacz także
Dział zatytułowany „Zobacz także”- Mapowanie poziomów bazowych PAdES — Core a Premium w zakresie B-B, B-T, B-LT, B-LTA.
- Contracts / Signing — interfejs dostawcy usług (service provider interface, SPI)
SignerInterfaceoraz poziomy stabilności. - Security — szyfrowanie i szersza powierzchnia podpisywania.
- Conformance — egzekwowanie profilu współgrające z podpisaną archiwizacją.
- CMS · znacznik czasu RFC 3161 · Long-Term Validation (LTV) · Document Security Store (DSS) · Validation-Related Information (VRI) · Hardware Security Module (HSM) — terminy ze słownika.