Salta ai contenuti
getnextpdf.com

Enterprise edizione

Security — Riferimento approfondito (HSM, PKCS#11, modalità FIPS)

Questa pagina è il riferimento approfondito combinato per la superficie di sicurezza di NextPDF Enterprise. Copre la firma con token hardware tramite PKCS#11, la firma in sottoprocesso attraverso l’interfaccia a riga di comando (CLI) di OpenSSL, i preset di crypto-policy FIPS, la guardia FIPS in fase di esecuzione e la guardia di self-test all’accensione (power-on). Esistono due complementi mirati: HSM — Riferimento approfondito per il dettaglio del firmatario e FIPS 140 — Riferimento approfondito per il dettaglio del modulo FIPS. Il percorso di firma post-quantistico è un’anteprima priva di rivendicazioni di conformità. NextPDF non detiene alcuna certificazione e non ne concede alcuna; il supporto non equivale alla conformità e la conformità non equivale alla certificazione.

Questa funzionalità è distribuita in NextPDF Enterprise (nextpdf/enterprise) e si attiva con un envelope di licenza di tier Enterprise. Una distribuzione priva di tale entitlement non carica le classi della funzionalità. Confronta le edizioni e ottieni una licenza.

Terminal window
composer require nextpdf/enterprise:^3

I tipi di firma risiedono in NextPDF\Enterprise\Security\Signature\Hsm; i tipi FIPS risiedono in NextPDF\Enterprise\Security\Fips; la composition root risiede in NextPDF\Enterprise\Bootstrap. Entrambi i firmatari implementano il contratto di Core NextPDF\Contracts\HsmSignerInterface. La policy implementa i contratti di Core NextPDF\Contracts\CryptoPolicyInterface e NextPDF\Contracts\PreOperationalSelfTestInterface.

SimboloParametriComportamento predefinitoRestituisceSolleva o fallisce conNote
Pkcs11Signer::__construct()string $libraryPath, int $slotId, string $pin, string $certLabel, ?string $keyLabel = null, array $chainDer = [], bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = nullApre la libreria del fornitore, effettua il login nello slot, carica il certificato e i metadati dell’algoritmo di chiaveHsmOperationException quando ext-pkcs11 è assente o l’accesso al token falliscePIN e label sono #[SensitiveParameter]; un handle di modulo viene messo in cache per percorso di libreria per processo
Pkcs11Signer::isAvailable()NessunoIndica se ext-pkcs11 è caricatoboolNessunoStatico; verificare prima della costruzione
Pkcs11Signer::sign()string $data, string $algorithm = 'sha256WithRSAEncryption'Firma sul token; l’output ECDSA raw viene convertito in DER ECDSA-Sig-Valuestring byte di firma rawHsmOperationException (chiave non trovata, errore del token); InvalidArgumentException (algoritmo non mappato); FipsViolationException / FipsModuleErrorStateException prima della firma quando è collegato un enforcerInsieme di algoritmi chiuso; vedere Contratto di comportamento
Pkcs11Signer::signPqs()string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = trueRifiutato a meno che $enablePostQuantum non sia stato impostato; invoca il meccanismo post-quantistico PKCS#11 provvisoriostring byte di firma rawHsmOperationException (disabilitato, errore del token, lunghezza della firma non corrispondente); InvalidArgumentException (contesto oltre 255 byte)Anteprima; nessuna rivendicazione di conformità
Superficie di accessor di Pkcs11SignerNessunoRisultati di costruzione in sola letturabool / string / array<string>NessunoisPostQuantumEnabled, getCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm
OpenSslCliSigner::__construct()string $keyUri, string $certPath, string $pin, array $extraCertPaths = [], OpenSslCliBackend $backend = OpenSslCliBackend::Auto, string $opensslBinary = 'openssl', int $timeoutSeconds = 30, ?string $modulePath = null, ?string $configPath = null, bool $legacyPinDelivery = false, ?FipsSignatureEnforcer $fipsEnforcer = nullVerifica proc_open, sonda il binario, risolve il backend, carica i certificatiHsmOperationException (proc_open disabilitato, file di modulo/config/certificato mancante, nessun backend); InvalidArgumentException (pin-value all’interno di $keyUri)Auto preferisce il provider OpenSSL 3.x, poi l’engine
OpenSslCliSigner::sign()string $data, string $algorithm = 'sha256WithRSAEncryption'Firma in un sottoprocesso openssl; per impostazione predefinita il PIN transita attraverso un file pin-source effimero 0600string byte di firma rawHsmOperationException (timeout, PIN rifiutato, chiave non trovata, output vuoto); InvalidArgumentException (algoritmo non mappato); eccezioni del gate FIPS prima della firmaIl sottoprocesso viene terminato dopo $timeoutSeconds; stderr è redatto
Superficie di accessor di OpenSslCliSignerNessunoRisultati di costruzione in sola letturastring / array<string> / OpenSslCliBackendNessunogetCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm, getCertificatePem, getResolvedBackend, getOpensslVersion
OpenSslCliBackendEnum: Provider, Engine, AutoNessunoSelezione del backend per il firmatario CLI
Pkcs11PqsAlgorithmEnum di set di parametri ML-DSA e SLH-DSANessunoHelper: isMlDsa, isSlhDsa, mechanismId, parameterSetId, signatureLength, nistCategory
PqsCapabilityStatus::current()NessunoCostruisce la postura post-quantistica onesta per il processoPqsCapabilityStatusNessunoOgni booleano di rivendicazione di conformità è impostato in modo fisso a false; nessun flag può attivarne uno
HsmSignerProviderAdapterHsmSignerInterface $hsm, string $providerId, SignatureAlgorithm $algorithm = SignatureAlgorithm::Pkcs1v15Espone una concreta HSM come SignerProviderInterface unificataSecondo lo SPIKeyManagementException (versione di chiave non nulla); SignatureFailedException (errore del driver, firma vuota)Id dei provider: pkcs11-{module-id}, openssl-cli
HsmOperationExceptionErrore tipizzato per ogni percorso di firma HSMEstende NextPdfException di Core
FipsCryptoPolicy::strict() / ::standard()?FipsSelfTest $selfTest = nullPreset di factory; strict è il profilo FIPS 140-3, standard aggiunge AES-128-CBCFipsCryptoPolicyNessunoAllow-list immutabili; vedere Comportamento in modalità FIPS
Superficie di predicati di FipsCryptoPolicyinput string / intVerifiche di appartenenza all’allow-listbool / stringNessunoisHashAlgorithmAllowed, isSignatureAlgorithmAllowed, isEncryptionAlgorithmAllowed, isKeyStrengthAllowed, getPreferredHashAlgorithm, getName
FipsCryptoPolicy::assertPreOperational()NessunoEsegue (o riproduce) il self-test all’accensionevoidFipsModuleErrorStateExceptionGuidato dalla giuntura (seam) di enforcement di Core alla prima operazione crittografica
FipsModeGuard::__construct()CryptoPolicyInterface $policy, ?FipsBootGuard $bootGuard = null, ?FipsAuditLogger $auditLogger = nullAvvolge una policy con confini in stile assertNessunoSenza una boot guard il gate di self-test è assente (solo policy)
Superficie di assert di FipsModeGuardinput string / intPrima il catalogo di deny, poi l’allow-list; record di audit prima di qualsiasi eccezionevoidFipsViolationException; FipsModuleErrorStateException (boot guard collegata)assertHashAllowed, assertSignatureAlgorithmAllowed, assertEncryptionAllowed, assertKeyStrengthAllowed, più getPolicy
FipsBootGuard::report() / ::rerun()NessunoEsegue la batteria di self-test (in cache / forzata)FipsSelfTestReportNessunoUn report ERROR blocca (latch) il processo; una riesecuzione superata non rimuove mai il latch
FipsBootGuard::assertOperational()NessunoAsserisce che il modulo sia OPERATIONALvoidFipsModuleErrorStateExceptionPersistente (sticky): un ERROR bloccato a livello di processo rifiuta anche un’istanza pulita
FipsBootGuard::status()NessunoRiferisce lo stato in cacheFipsSelfTestStatusNessunoPRE_OPERATIONAL, OPERATIONAL o ERROR
FipsSelfTest::run()NessunoEsegue l’intera batteria di test a risposta nota (known-answer-test); non va mai in corto circuitoFipsSelfTestReportNessunoIl costruttore accetta provider di hash e di byte casuali iniettabili per test deterministici
FipsSelfTestReport / FipsSelfTestResult / FipsSelfTestStatusValue object di report ed enum di statoFipsSelfTestReport::assertOperational() solleva FipsModuleErrorStateExceptionresults elenca sempre ogni esito come evidenza di audit
FipsSignatureEnforcer::assertSignatureGenerationAllowed()string $algorithm, string $certificatePemRisolve l’OID di firma e la robustezza della chiave, poi delega alla guardiavoidFipsViolationException (non consentito o non classificabile, fail-closed)Il punto di strozzatura (chokepoint) che entrambi i firmatari chiamano all’inizio di sign() in modalità FIPS
FipsAuditLoggerCryptoPolicyInterface $policy, LoggerInterface $loggerEmette record ALLOW (INFO) / DENY (WARNING) per ogni decisionebool per chiamata di logNessunologHashOperation, logSignatureOperation, logEncryptionOperation, logKeyStrengthCheck
FipsTransitioningAlgorithmsinput string / intCatalogo di deny statico NIST SP 800-131Abool / arrayNessunoIl livello di deny esplicito sotto ogni confine di guardia
FipsBootstrap::boot() / ::lazy()?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = nullCompone boot guard, policy e mode guard; boot() esegue subito il self-test, lazy() lo rinvia al primo confineFipsModeGuardboot(): FipsModuleErrorStateException in caso di test fallitoPer impostazione predefinita usa la policy strict
FipsBootstrap::signatureEnforcer()?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = nullAvvia il modulo e restituisce il gate al momento della generazione per i firmatariFipsSignatureEnforcerFipsModuleErrorStateExceptionPassare il risultato al parametro $fipsEnforcer di un firmatario
FipsBootstrap::selfTestReport()?FipsSelfTest $selfTest = nullEsegue la batteria on-demand e la riepilogaarray{status, operational, failed}NessunoPensato per endpoint di health e per il sottocomando CLI
FipsViolationException / FipsModuleErrorStateExceptionErrori FIPS tipizzatiEspongono rispettivamente policyName / violatingItem / reason e failedResults
public function __construct(private readonly string $libraryPath, private readonly int $slotId, #[SensitiveParameter] private readonly string $pin, #[SensitiveParameter] private readonly string $certLabel, #[SensitiveParameter] private readonly ?string $keyLabel = null, array $chainDer = [], private readonly bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = null)
public static function isAvailable(): bool
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
public function signPqs(string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = true): string
public function __construct(private string $keyUri, string $certPath, #[SensitiveParameter] private string $pin, array $extraCertPaths = [], private OpenSslCliBackend $backend = OpenSslCliBackend::Auto, private string $opensslBinary = 'openssl', private int $timeoutSeconds = 30, private ?string $modulePath = null, private ?string $configPath = null, private bool $legacyPinDelivery = false, private ?FipsSignatureEnforcer $fipsEnforcer = null)
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
public static function strict(?FipsSelfTest $selfTest = null): self
public static function standard(?FipsSelfTest $selfTest = null): self
public function assertPreOperational(): void
public function __construct(private CryptoPolicyInterface $policy, private ?FipsBootGuard $bootGuard = null, private ?FipsAuditLogger $auditLogger = null)
public function assertHashAllowed(string $algorithm): void
public function assertSignatureAlgorithmAllowed(string $oid): void
public function assertEncryptionAllowed(string $algorithm): void
public function assertKeyStrengthAllowed(string $keyType, int $bitLength): void
public function getPolicy(): CryptoPolicyInterface
public static function boot(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuard
public static function lazy(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuard
public static function signatureEnforcer(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null): FipsSignatureEnforcer
public static function selfTestReport(?FipsSelfTest $selfTest = null): array
  • Risoluzione dei contratti. Entrambi i firmatari implementano HsmSignerInterface di Core; la policy implementa CryptoPolicyInterface di Core. Il codice chiamante dipende dai contratti, quindi un upgrade di edizione cambia la composizione, non i punti di chiamata.
  • Custodia della chiave. La chiave privata non lascia mai il confine del token. Pkcs11Signer delega l’operazione al token; OpenSslCliSigner passa al sottoprocesso un riferimento di chiave tramite URI PKCS#11. NextPDF non archivia, genera né garantisce la sicurezza della chiave di firma. La protezione della chiave è responsabilità di custodia dell’operatore (NIST SP 800-57 Part 1 Rev.5 §5.5.2).
  • Sessione e login. L’operazione di firma del token, la sessione e il login dell’utente seguono PKCS#11 v3.1 §5. La label del certificato e la label della chiave privata possono differire; il costruttore accetta una label di chiave separata per tali token.
  • Insieme di algoritmi chiuso. I firmatari accettano esattamente: RSA PKCS#1 v1.5 con SHA-256/384/512, RSASSA-PSS con SHA-256/384/512 ed ECDSA con SHA-256/384/512 (Pkcs11Signer accetta anche ecdsa-raw). Qualsiasi altro identificatore solleva InvalidArgumentException; nessun algoritmo sostitutivo viene mai firmato.
  • Vincolo del salt PSS. Per ogni variante PSS la lunghezza del salt è pari alla lunghezza del digest — 32, 48 o 64 byte — e i parametri di hash e di generazione della maschera corrispondono al digest scelto (PKCS#11 v3.1 §5).
  • Conversione ECDSA. I meccanismi ECDSA del token restituiscono una firma raw; sign() la converte nella forma ECDSA-Sig-Value codificata in DER per l’interoperabilità con PDF e OpenSSL. La generazione della firma segue FIPS 186-5 §6.3.2.
  • Contenuto dei preset. Il preset strict consente SHA-256/384/512; gli OID di firma RSA ed ECDSA con tali hash; RSASSA-PSS; AES-256-CBC e AES-256-GCM; minimo RSA 2048 ed EC 256. Il preset standard consente inoltre AES-128-CBC per l’interoperabilità legacy. Qualsiasi uso di AES-GCM richiede un vettore di inizializzazione univoco per chiave (NIST SP 800-38D §5).
  • Enforcement a due livelli. Ogni confine di guardia consulta prima il catalogo di deny esplicito NIST SP 800-131A, poi l’allow-list della policy. Il livello di deny produce il segnale «non consentito» chiaro per l’audit; l’allow-list rimane autoritativa.
  • Self-test all’accensione. La batteria copre SHA-256/384/512, HMAC-SHA-256, AES-256-CBC, AES-256-GCM, un test di coerenza a coppie (pairwise-consistency) ECDSA P-256 e un controllo di integrità dei bit casuali. La prima operazione crittografica sotto la policy sul percorso di Core la esegue una volta per processo, fail-closed. Un fallimento pone il modulo nello stato ERROR; i servizi crittografici sono rifiutati fino al reset. Questo segue ISO/IEC 19790:2025 §7.10, §7.10.2, §7.10.3 e §7.10.3.p3.
  • Stato ERROR persistente. Un ERROR osservato si blocca (latch) per l’intero processo. Costruire una nuova policy o boot guard non lo può ripulire; una riesecuzione superata non lo azzera. Solo un riavvio del processo — un vero ciclo di alimentazione — ripristina lo stato.
  • Solo gate di generazione. FipsSignatureEnforcer governa la produzione di nuove firme. La convalida di firme preesistenti è un uso legacy e non passa mai attraverso l’enforcer.
  • Traccia di audit. Quando una guardia è composta con un audit logger, ogni confine emette un record ALLOW o DENY prima di consentire o rifiutare l’operazione. Il logger consulta la stessa policy che la guardia applica, quindi la decisione registrata non può divergere.
  • Costruire Pkcs11Signer senza ext-pkcs11 solleva immediatamente HsmOperationException; l’estensione non è inclusa nelle distribuzioni PHP standard.
  • Una label di certificato o di chiave privata che non corrisponde ad alcun oggetto del token solleva HsmOperationException indicando la classe di oggetto mancante.
  • OpenSslCliSigner rifiuta in costruzione, fail-closed, un $keyUri contenente pin-value; il PIN transita invece attraverso il percorso pin-source sicuro.
  • In modalità FIPS, un identificatore di algoritmo che non può essere mappato a un OID di firma noto viene negato fail-closed; lo stesso vale per un certificato la cui robustezza di chiave pubblica non può essere determinata.
  • Un tipo di chiave sconosciuto viene negato per impostazione predefinita; la policy non ricade mai su un algoritmo più debole.
  • Un test a risposta nota fallito solleva FipsModuleErrorStateException che trasporta i risultati falliti; ogni confine successivo nel processo ripete il fallimento fino al riavvio.
  • Una guardia costruita senza una boot guard applica le allow-list ma non fornisce alcun gate di self-test; la composizione FIPS di produzione ne fornisce uno tramite il bootstrap.
  • signPqs() rifiuta di essere eseguito a meno che non sia stato impostato l’opt-in nel costruttore. Una stringa di contesto oltre 255 byte solleva InvalidArgumentException (FIPS 204 §5.4). Una firma restituita la cui lunghezza in byte non corrisponde al set di parametri selezionato viene rifiutata prima di raggiungere la codifica.

Consentito da FIPS in modalità strict: SHA-256/384/512; RSA PKCS#1 v1.5 e RSA-PSS con tali hash; ECDSA con tali hash; AES-256-CBC e AES-256-GCM; RSA almeno 2048 bit, EC almeno 256 bit. Rifiutato da FIPS in modalità strict: hash più deboli o legacy, OID di firma non approvati, AES-128 (consentito solo nel preset standard) e qualsiasi chiave al di sotto della robustezza minima. La lunghezza minima della chiave RSA e lo stato di transizione seguono NIST SP 800-131A Rev.2 §3. L’accoppiamento di curva e hash ECDSA segue FIPS 186-5 §6.1.1. Il percorso è fail-closed e non sostituisce mai un algoritmo più debole.

NextPDF Enterprise non è un modulo crittografico convalidato FIPS e non avanza alcuna rivendicazione di certificazione FIPS. NextPDF Enterprise opera in modalità FIPS-compatibile solo quando è configurato con un provider crittografico convalidato FIPS — per esempio un provider OpenSSL convalidato FIPS — o con un HSM convalidato FIPS. La policy in modalità FIPS assiste la conformità; non è una certificazione. In questo repository non esiste alcun artefatto di certificazione FIPS.

RivendicazioneStandardClausola
Semantica dell’operazione di firma del token, della sessione e del login dell’utentePKCS#11 v3.1§5 (sign)
La lunghezza del salt PSS è pari alla lunghezza del digestPKCS#11 v3.1§5 (PSS sLen)
Generazione della firma ECDSA; accoppiamento di curva e hashFIPS 186-5§6.3.2; §6.1.1
Lunghezza minima della chiave RSA e stato di transizione della generazione delle firmeNIST SP 800-131A Rev.2§3
Categoria di self-test, documentazione, trigger condizionale, insieme disgiuntoISO/IEC 19790:2025§7.10, §7.10.2, §7.10.3, §7.10.3.p3
Univocità del vettore di inizializzazione AES-GCMNIST SP 800-38D§5
Responsabilità di protezione e custodia delle chiaviNIST SP 800-57 Part 1 Rev.5§5.5.2
Stringa di contesto per la firma post-quantistica limitata a 255 byteFIPS 204§5.4

Tutte le clausole sono parafrasate; nessun testo normativo viene riprodotto. Si tratta di rivendicazioni di capacità sul codice di NextPDF, non di certificazioni. Se una firma prodotta risulti valida è una decisione del verificatore rispetto alla propria configurazione di fiducia. La policy in modalità FIPS è una funzionalità di assistenza alla conformità, non un parere legale; consultare i propri consulenti legali e di conformità. Questo modulo riguarda funzionalità crittografiche; trattarlo come sensibile dal punto di vista della sicurezza nella propria revisione.

  • Comporre la modalità FIPS tramite il bootstrap: boot() per un gate all’avvio, lazy() per rinviare la batteria al primo confine e la factory dell’enforcer per il parametro $fipsEnforcer dei firmatari. Le distribuzioni non-FIPS passano null e il comportamento è invariato.
  • Il sottocomando fips:self-test di bin/nextpdf-enterprise esegue la batteria on-demand ed esce con codice diverso da zero nello stato ERROR; collegarlo a job di manutenzione o a endpoint di health riservati agli amministratori (self-test on-demand ISO/IEC 19790:2025).
  • FipsBootGuard::resetProcessErrorLatchForTesting() è @internal e solo per i test; il codice di produzione non lo chiama mai, perché vanificherebbe lo stato ERROR persistente.
  • Costruire i firmatari una volta e riutilizzarli; la costruzione effettua il login e legge il certificato, e la cache di modulo per libreria rende sicura la costruzione ripetuta sulla stessa libreria.
  • Fornire il PIN da un secret manager. È un #[SensitiveParameter], mai registrato nei log né serializzato; non inserirlo nella configurazione tramite commit.
  • L’operatore possiede il provisioning del token, la gestione del PIN, la configurazione dello slot, la protezione di rete di un HSM connesso in rete e la configurazione di fiducia. Questa pagina non espone i dettagli interni della policy di PIN del token né il materiale di credenziali del fornitore.
  • Non abilitare l’anteprima post-quantistica per le firme AdES di produzione. Il catalogo delle suite crittografiche AdES non riconosce ancora le suite post-quantistiche, la maggior parte dei visualizzatori PDF rifiuta tali firme e la convalida hardware round-trip non è completa. Il dettaglio dei meccanismi interni resta nella documentazione interna del repository sorgente ed è fuori ambito per questo manuale.

Questa pagina documenta solo il comportamento osservabile dall’esterno e la superficie API pubblica supportata. I percorsi di namespace interni, le classi helper, le tabelle dei meccanismi, i nomi di file di runbook e i prefissi di ticket sono fuori ambito.