Przejdź do głównej zawartości

Kontrakt dostawcy KMS

HsmSignerInterface to publiczny kontrakt implementowany przez stronę trzecią, aby zapewnić NextPDF powierzenie kluczy. Dostawca zachowuje powiernictwo nad kluczem prywatnym. Silnik buduje strukturę Cryptographic Message Syntax (CMS).

Okno terminala
composer require nextpdf/core:^3

NextPDF oddziela składanie podpisu od powiernictwa nad kluczem. Silnik przygotowuje zakres bajtów i składa strukturę CMS SignedData. Nie przechowuje klucza prywatnego. Zamiast tego deleguje powiernictwo nad kluczem do zaplecza podpisującego za pośrednictwem publicznego kontraktu.

Implementujesz jeden z trzech publicznych kontraktów:

  • SignerInterface. Kontrakt bazowy. Zwraca obiekt SignatureResult dla przekazanych danych, stosuje znacznik czasu i informuje o obsłudze walidacji długoterminowej. Użyj tego kontraktu, gdy logika podpisywania działa w obrębie procesu.
  • HsmSignerInterface. Kontrakt powiernictwa nad kluczem. Implementacja musi podpisywać wewnątrz granicy sprzętowej. Klucz prywatny nie może opuścić tej granicy. Dostawca systemu zarządzania kluczami implementuje ten kontrakt.
  • DeferredSignerInterface. Rozszerzenie kontraktu SignerInterface dla zapleczy asynchronicznych. Wywołujący przesyła dane, otrzymuje identyfikator zadania i później pobiera wynik.

Ta strona określa publiczny kontrakt. Nie opisuje żadnej wewnętrznej implementacji NextPDF Pro ani NextPDF Enterprise. Płatna edycja może dostarczyć wspieraną implementację tego kontraktu. Opierasz się na kontrakcie, a nie na implementacji.

Kontrakt wymaga, aby klucz prywatny nigdy nie opuszczał bezpiecznej granicy. Ugruntowana praktyka zarządzania kluczami wspiera ten wymóg. National Institute of Standards and Technology (NIST) SP 800-57 Part 1 Revision 5 ujmuje zarządzanie kluczami jako obsługę cyklu życia obejmującą bezpieczne generowanie, przechowywanie, dystrybucję, użycie i niszczenie. Public-Key Cryptography Standards #11 (PKCS#11) v3.1 pozwala egzekwować tę granicę. Gdy obiekt klucza prywatnego ma ustawione CKA_SENSITIVE na true lub CKA_EXTRACTABLE na false, token nie może ujawnić wartości klucza w postaci jawnej poza tokenem.

Implementacja odpowiada za przestrzeganie tego wymogu. Silnik nie może go za Ciebie wyegzekwować. Jeśli metoda sign() może odczytać surowe bajty klucza do pamięci procesu, kontrakt traci swoją właściwość bezpieczeństwa.

NextPDF\Contracts\HsmSignerInterface (stabilny, od 1.0.0):

MetodaZwracaCel
sign(string $data, string $algorithm)stringPodpisz dane wewnątrz granicy sprzętowej. Zwróć surowe bajty podpisu. Zgłoś RuntimeException w razie niepowodzenia.
getCertificateDer()stringZwróć certyfikat X.509 podpisującego w formacie Distinguished Encoding Rules (DER).
getCertificateChainDer()array<string>Zwróć certyfikaty pośrednie, od wystawcy do korzenia, z wyłączeniem certyfikatu podpisującego.
getPublicKeyAlgorithm()stringZwróć identyfikator algorytmu klucza publicznego.

NextPDF\Contracts\SignerInterface (stabilny, od 1.0.0):

MetodaZwracaCel
sign(string $data)SignatureResultZwróć zakodowane w DER CMS SignedData.
timestamp(string $signatureValue)stringZwróć zakodowany w DER token znacznika czasu Request for Comments (RFC) 3161.
supportsLtv()boolWskaż, czy można osadzić dane walidacji długoterminowej (LTV).

NextPDF\Contracts\DeferredSignerInterface (eksperymentalny, od 3.0.0) rozszerza SignerInterface o submitForSigning(), retrieveSignature() i isComplete() dla zapleczy asynchronicznych.

Poziomy podpisu tworzone przez silnik są zgodne z profilami PDF Advanced Electronic Signatures (PAdES). European Telecommunications Standards Institute (ETSI) EN 319 142-2 definiuje rozszerzone profile PAdES oparte na podstawowych blokach budulcowych z EN 319 142-1. Silnik mapuje poziomy B-B, B-T, B-LT i B-LTA na te bloki budulcowe. Podpisujący dostarcza operację kryptograficzną oraz materiał certyfikatu potrzebne silnikowi.

Minimalny dostawca w stylu PKCS#11 deleguje podpisywanie do tokena. PHP nigdy nie odczytuje wartości klucza.

<?php
declare(strict_types=1);
use NextPDF\Contracts\HsmSignerInterface;
final class TokenSigner implements HsmSignerInterface
{
public function __construct(private readonly TokenSession $session) {}
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
{
// The token computes the signature. The key stays inside the token.
return $this->session->c_sign($data, $algorithm);
}
public function getCertificateDer(): string
{
return $this->session->readCertificate();
}
/** @return array<string> */
public function getCertificateChainDer(): array
{
return $this->session->readChain();
}
public function getPublicKeyAlgorithm(): string
{
return 'rsaEncryption';
}
}

Produkcyjny dostawca waliduje dane wejściowe, w razie błędu tokena działa w trybie fail-closed i nigdy nie loguje materiału klucza ani podpisu.

<?php
declare(strict_types=1);
use NextPDF\Contracts\HsmSignerInterface;
use Psr\Log\LoggerInterface;
use RuntimeException;
final class KmsSigner implements HsmSignerInterface
{
public function __construct(
private readonly RemoteKmsClient $kms,
private readonly string $keyId,
private readonly LoggerInterface $logger,
) {}
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
{
if ($data === '') {
throw new RuntimeException('Refusing to sign empty data');
}
try {
// The KMS performs the operation. The key never reaches this process.
return $this->kms->sign($this->keyId, $data, $algorithm);
} catch (\Throwable $error) {
// Fail closed. Do not log key material or signature bytes.
$this->logger->error('kms.sign.failed', ['key' => $this->keyId]);
throw new RuntimeException('KMS signing failed', previous: $error);
}
}
public function getCertificateDer(): string
{
return $this->kms->certificate($this->keyId);
}
/** @return array<string> */
public function getCertificateChainDer(): array
{
return $this->kms->chain($this->keyId);
}
public function getPublicKeyAlgorithm(): string
{
return $this->kms->algorithm($this->keyId);
}
}
  • Format bajtów podpisu. Zwróć surowe bajty podpisu. W przypadku Rivest-Shamir-Adleman (RSA) bajty są w formacie DER. W przypadku Elliptic Curve Digital Signature Algorithm (ECDSA) bajty stanowią surową wartość r, po której następuje wartość s.
  • Kolejność łańcucha. getCertificateChainDer() wyklucza certyfikat podpisującego. Uporządkuj certyfikaty pośrednie od wystawcy do korzenia.
  • Identyfikatory algorytmów. sign() używa identyfikatorów w stylu OpenSSL. getPublicKeyAlgorithm() zwraca nazwę algorytmu X.509.
  • Niepowodzenie jest fail-closed. Zgłoś RuntimeException przy każdym błędzie tokena lub systemu KMS. Nie zwracaj częściowego ani pustego podpisu.
  • Niszczenie klucza. Gdy klucz osiągnie koniec okresu kryptograficznego, zniszcz go zgodnie z procedurą zarządzania kluczami. NIST SP 800-57 Part 1 Revision 5 §8.2.1.2 stwierdza, że klucz powinien zostać zniszczony, gdy tylko przestaje być potrzebny. Samo niszczenie przebiega zgodnie z §8.3.4.

Rezydencja danych i ograniczanie ryzyka związanego z PII

Dział zatytułowany „Rezydencja danych i ograniczanie ryzyka związanego z PII”

Kontrakt przekazuje wyłącznie dane do podpisania oraz materiał certyfikatu. Nie przekazuje treści dokumentu ani danych osobowych do zaplecza podpisującego. Ogranicz zakres bajtów do minimum. Nie umieszczaj danych osobowych w polach powodu lub lokalizacji podpisu. Te pola pozostają widoczne w podpisanym pliku.

Nigdy nie loguj danych przekazanych do sign(), zwróconych bajtów podpisu, identyfikatora klucza w odwracalnej postaci ani żadnego prywatnego komponentu certyfikatu. Loguj wyłącznie wynik operacji oraz nieodwracalny odnośnik. Hak SignatureAppliedEvent jest wspieraną kotwicą audytu. Zobacz Wyzwalacze akcji.

ZasóbZagrożenieŚrodek zaradczy
Klucz prywatnyWyciek do pamięci procesuKontrakt wymaga podpisywania w obrębie granicy; PKCS#11 CKA_SENSITIVE / CKA_EXTRACTABLE wymuszają brak możliwości wyodrębnienia
Wyrocznia podpisującaNieograniczone żądania podpisywaniaImplementacja ogranicza częstotliwość żądań i uwierzytelnia wywołujących
Łańcuch certyfikatówPodstawienieImplementacja zwraca łańcuch, który buduje ścieżkę do zaufanego korzenia
Bajty podpisuUjawnienie przez logiŚcieżka błędu fail-closed; brak materiału podpisu w telemetrii
Klucz po okresie kryptograficznymDalsze użycieNiszczenie klucza zgodnie z NIST SP 800-57 Part 1 Revision 5 §8.2.1.2

Poziomy podpisu są zgodne z profilami PAdES. ETSI EN 319 142-2 §5.1 definiuje rozszerzone profile PAdES na podstawowych blokach budulcowych EN 319 142-1. Silnik składa te bloki budulcowe z materiału dostarczonego przez podpisującego. Zarządzanie kluczami jest zgodne z cyklem życia NIST SP 800-57 Part 1 Revision 5, w tym z wymogiem niszczenia z §8.2.1.2. Sprzętowe powierzenie klucza jest zgodne z atrybutami klucza niemożliwego do wyodrębnienia z PKCS#11 v3.1. Cytowania znajdują się w nagłówku front matter strony.

Ta strona obejmuje powierzenie kluczy za pomocą PKCS#11 oraz modułu zabezpieczeń sprzętowych (HSM), dlatego jej front matter ustawia export_control_class: legal-review-required. Zgodnie z polityką przeglądu dokumentacji (plan §17 bramka 6) każda strona, której tryb bezpieczeństwa, ścieżka lub treść pasuje do PAdES, FIPS, HSM lub PKCS#11, wymaga zatwierdzenia przez zespół GitHub @nextpdf-labs/crypto-reviewers, zanim będzie mogła zostać opublikowana. To zatwierdzenie CODEOWNERS jest twardą bramką scalania: strona pozostaje publish: false, dopóki nie zakończą się zarówno prawny przegląd kontroli eksportu, jak i przegląd @nextpdf-labs/crypto-reviewers.

NextPDF Enterprise dostarcza wspieraną implementację tego kontraktu z powierzeniem kluczy w systemie zarządzania kluczami, składaniem łańcucha certyfikatów oraz integracją audytu. Możesz samodzielnie zaimplementować HsmSignerInterface w wersji Core albo korzystać z implementacji Enterprise za pośrednictwem tego samego publicznego kontraktu bez zmian w kodzie.

Słownik definiuje pojęcia system zarządzania kluczami, okres kryptograficzny oraz HSM; zobacz opublikowany słownik, aby sprawdzić ich kanoniczne definicje.