Contratti / Firma
In breve
Sezione intitolata “In breve”Il dominio della firma comprende sei contratti. Definiscono come generare una firma CMS, applicare una marca temporale RFC 3161, firmare con una chiave hardware e abilitare la convalida a lungo termine. Core pubblica i contratti; le edizioni Pro ed Enterprise forniscono le implementazioni di produzione.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/core:^3Panoramica concettuale
Sezione intitolata “Panoramica concettuale”Una firma digitale PDF è una struttura CMS SignedData memorizzata nel dizionario della firma. La voce Contents contiene la struttura codificata in DER. La voce ByteRange indica gli intervalli di byte coperti dal digest. Il digest copre l’intero file ed esclude il valore stesso della firma — vedere ISO 32000-2 §12.8.1. La struttura CMS segue RFC 5652 §5.1: una sequenza composta da versione, algoritmi di digest, contenuto incapsulato e informazioni sul firmatario.
SignerInterface è il contratto principale. Produce strutture CMS SignedData per un intervallo di byte, applica una marca temporale a un valore di firma e indica se supporta la convalida a lungo termine. Copre i livelli baseline PAdES da B-B a B-LTA come definiti in ETSI EN 319 142. Ogni livello superiore aggiunge materiale. B-B contiene la firma di base. B-T aggiunge una marca temporale della firma. B-LT aggiunge i dati di revoca. B-LTA aggiunge una marca temporale di archiviazione.
HsmSignerInterface firma con una chiave custodita in un Hardware Security Module. La chiave privata non lascia il confine hardware. Il contratto restituisce il certificato del firmatario e la catena di certificati in formato DER, così il livello CMS può costruire la struttura. DeferredSignerInterface estende SignerInterface per la firma asincrona. Il chiamante invia i dati, riceve un identificatore di job, verifica periodicamente il completamento e quindi recupera il risultato. Utilizzarlo quando un HSM remoto o un servizio di chiavi cloud non restituisce subito un risultato.
TimestampProviderInterface richiede un token di marca temporale RFC 3161. Il protocollo prevede una richiesta e una risposta scambiate con una Time-Stamping Authority — vedere RFC 3161 §2.4. Il messageImprint nel token è un hash del valore della firma — RFC 3161 §2.4.2. LtvManagerInterface abilita la convalida a lungo termine. Raccoglie la catena di certificati, recupera le risposte OCSP e CRL, costruisce il Document Security Store e aggiunge una marca temporale del documento per B-LTA. CryptoPolicyInterface controlla quali algoritmi di hash, firma e cifratura e quali livelli di robustezza delle chiavi sono consentiti prima dell’esecuzione di qualsiasi operazione crittografica.
Superficie API
Sezione intitolata “Superficie API”| Tipo | Categoria | Membri principali | Stabilità | A partire da |
|---|---|---|---|---|
SignerInterface | interface | sign(string): SignatureResult, timestamp(string): string, supportsLtv(): bool | stable | 1.0.0 |
HsmSignerInterface | interface | sign(string, string): string, getCertificateDer(), getCertificateChainDer(), getPublicKeyAlgorithm() | stable | 1.0.0 |
DeferredSignerInterface | interface | submitForSigning(string): string, retrieveSignature(string), isComplete(string) (estende SignerInterface) | experimental | 3.0.0 |
TimestampProviderInterface | interface | getTimestamp(string): string | experimental | 3.0.0 |
LtvManagerInterface | interface | enableLtv(...), addDocumentTimestamp(...) | stable | 1.10.0 |
CryptoPolicyInterface | interface | isHashAlgorithmAllowed(), isSignatureAlgorithmAllowed(), isEncryptionAlgorithmAllowed(), isKeyStrengthAllowed(), getPreferredHashAlgorithm(), getName() | stable | 1.9.0 |
SignerInterface::sign() restituisce un NextPDF\Security\Signature\SignatureResult. La proprietà pubblica $cmsSignedData contiene il CMS codificato in DER. La proprietà pubblica $digestHex contiene il digest SHA-256. La proprietà pubblica $timestampToken contiene il token TSA opzionale. I metodi accessor sono toHex() / toHexPadded(int) / getSize() / hasTimestamp(). HsmSignerInterface::sign() restituisce byte codificati in DER per RSA e byte r‖s grezzi per ECDSA. L’argomento dell’algoritmo usa gli identificatori OpenSSL.
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\SignerInterface;
/** * Sign a byte range with any SignerInterface implementation. * * @param SignerInterface $signer A core or Premium signer. * @param string $byteRange The PDF byte range to sign. * * @return string Hex-encoded CMS SignedData for the PDF /Contents field. */function signByteRange(SignerInterface $signer, string $byteRange): string{ $result = $signer->sign($byteRange);
return $result->toHex();}SignerInterface::sign() restituisce un SignatureResult. toHex() produce la stringa esadecimale che il writer inserisce nel campo /Contents; i byte DER grezzi si trovano nella proprietà pubblica $cmsSignedData. La funzione dipende dal contratto, non da una classe concreta. Un firmatario di test di Core e un firmatario HSM Premium soddisfano entrambi il contratto.
Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\CryptoPolicyInterface;use NextPDF\Contracts\SignerInterface;use NextPDF\Contracts\TimestampProviderInterface;use NextPDF\Exception\NextPdfException;use Psr\Log\LoggerInterface;
final readonly class TimestampedSigningService{ public function __construct( private SignerInterface $signer, private TimestampProviderInterface $timestamps, private CryptoPolicyInterface $policy, private LoggerInterface $logger, ) {}
/** * Sign a byte range, then timestamp the CMS structure. * * @param string $byteRange The PDF byte range to sign. * * @return array{cms: string, digest: string, tst: string} */ public function sign(string $byteRange): array { if (!$this->policy->isHashAlgorithmAllowed($this->policy->getPreferredHashAlgorithm())) { throw new \LogicException('Preferred hash rejected by crypto policy.'); }
try { $signature = $this->signer->sign($byteRange); $token = $this->timestamps->getTimestamp($signature->cmsSignedData);
return [ 'cms' => $signature->toHex(), 'digest' => $signature->digestHex, 'tst' => $token, ]; } catch (NextPdfException $e) { $this->logger->error('Signing failed', [ 'policy' => $this->policy->getName(), 'error' => $e->getMessage(), ]);
throw $e; } }}Il servizio inietta tre contratti. La policy crittografica viene consultata prima dell’operazione di firma. SignatureResult espone i byte CMS nella proprietà pubblica $cmsSignedData, il digest SHA-256 in $digestHex e toHex() per la stringa esadecimale /Contents. Il provider di marche temporali riceve i byte CMS e restituisce un token codificato in DER. Il blocco catch registra il nome della policy e rilancia l’eccezione. Non sopprime mai l’errore.
Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Il digest dell’intervallo di byte deve escludere il valore della firma. Un digest che copre la voce
Contentsproduce una firma che non può mai essere verificata — ISO 32000-2 §12.8.1. SignerInterface::supportsLtv()riporta la capacità, non lo stato. Un firmatario può supportare la convalida a lungo termine e produrre comunque una firma B-B quando non è configurato alcun servizio di marca temporale.DeferredSignerInterface::retrieveSignature()restituiscenullfinché il job non è completo. Verificare primaisComplete()per evitare di trasferire il payload a ogni controllo. Il recupero è idempotente una volta disponibile il risultato.LtvManagerInterface::addDocumentTimestamp()deve essere eseguito dopo la scrittura del Document Security Store. Chiamarlo prima produce una struttura B-LTA non valida.CryptoPolicyInterfacerestituiscetrueper ogni algoritmo quando non è impostata alcuna policy. In un ambiente regolamentato, impostare una policy esplicita; non fare affidamento sul comportamento predefinito aperto.HsmSignerInterface::getCertificateChainDer()esclude il certificato del firmatario. UsaregetCertificateDer()per il certificato foglia del firmatario e il metodo della catena per i certificati intermedi.
Prestazioni
Sezione intitolata “Prestazioni”Il costo della firma è determinato soprattutto dall’operazione crittografica e da eventuali round trip di rete, non dal contratto. Una firma software locale richiede pochi millisecondi. Una firma HSM aggiunge il round trip verso il dispositivo. Una marca temporale aggiunge un round trip di rete verso la Time-Stamping Authority. La convalida a lungo termine aggiunge un recupero OCSP o CRL per ogni certificato della catena. Il performance_budget di 1500 ms di tempo reale copre una singola firma con marca temporale tramite una TSA remota su una connessione già stabilita. La convalida a lungo termine verso un endpoint di revoca lento supera questo budget e dovrebbe essere eseguita al di fuori del percorso della richiesta. Il profilo di riproducibilità è structural, non bitwise. Una marca temporale incorpora l’istante di firma, quindi due esecuzioni differiscono nei byte della marca temporale mentre la struttura del documento rimane identica.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”I contratti di firma costituiscono il principale confine crittografico del motore, quindi il modello delle minacce è esplicito. La custodia delle chiavi è il primo aspetto: HsmSignerInterface mantiene la chiave privata all’interno del confine hardware e il contratto non espone mai il materiale della chiave. Il downgrade dell’algoritmo è il secondo: CryptoPolicyInterface blocca gli hash deboli e le chiavi corte prima dell’operazione, consentendo a un’installazione di applicare un profilo FIPS 140-3 o eIDAS senza eseguire un fork del motore. L’attendibilità della marca temporale è il terzo: un token RFC 3161 è affidabile solo quanto la Time-Stamping Authority, perciò il contratto del provider è iniettabile e l’installazione vincola l’autorità da usare. La convalida a lungo termine è il quarto: il materiale di revoca viene recuperato al momento della firma e memorizzato nel Document Security Store, in modo che la verifica sopravviva alla scadenza del certificato. Trattare ogni input del firmatario come non attendibile. L’intervallo di byte è calcolato dal motore, mai accettato dal chiamante. Questa pagina è contrassegnata con export_control_class: legal-review-required perché i contratti regolano la firma crittografica. Il testo parafrasa tutte le fonti normative e non ne riporta citazioni testuali, in conformità con l’igiene delle citazioni.
Conformità
Sezione intitolata “Conformità”| Dichiarazione | Standard | Clausola | Evidenza |
|---|---|---|---|
Il valore della firma è memorizzato con codifica DER nella voce Contents del dizionario della firma, come CMS SignedData o come TimeStampToken. | ISO 32000-2 | §12.8.1 | |
Il digest è calcolato sull’intervallo di byte definito dall’array ByteRange ed esclude il valore della firma. | ISO 32000-2 | §12.8.1 | , |
| Il materiale di convalida a lungo termine è contenuto nel Document Security Store con voci VRI, OCSP, CRL e voci di certificato. | ISO 32000-2 | §12.8.4.3 | , |
| La convalida a lungo termine PAdES colloca i dati di convalida nei dizionari DSS e VRI. | ETSI EN 319 142-2 | §6.3 | , |
Un token di marca temporale RFC 3161 vincola un hash del valore della firma tramite messageImprint ed è ottenuto tramite uno scambio richiesta-risposta TSA. | RFC 3161 | §2.4.2, §2.4 | , |
| La sequenza CMS SignedData contiene versione, algoritmi di digest, contenuto incapsulato e informazioni sul firmatario. | RFC 5652 | §5.1 |
Tutte le clausole sono parafrasate. NextPDF non riproduce il testo normativo. Consultare gli standard pubblicati per il testo autorevole.
Contesto commerciale
Sezione intitolata “Contesto commerciale”Core pubblica e congela i contratti di firma. Le implementazioni di produzione dietro HsmSignerInterface, LtvManagerInterface e il firmatario differito sono fornite nelle edizioni Pro ed Enterprise, comprese l’integrazione hardware PKCS#11 e le implementazioni PAdES B-LT e B-LTA. Core le risolve a runtime con class_exists() e le adatta al contratto, in modo che il motore open source non introduca alcuna dipendenza commerciale e l’API non cambi al momento dell’aggiornamento.
Vedere anche
Sezione intitolata “Vedere anche”- Contratti: 41 interfacce pubbliche (SPI) — la panoramica SPI e i livelli di stabilità.
- Contratti / Policy di sicurezza — gating di algoritmi e chiavi di
CryptoPolicyInterface. - Contratti / Estrazione — applicazione di PDF/A abbinata all’archiviazione firmata.
- Sicurezza — superficie di implementazione della cifratura e della firma.
- Audit — registrazione di audit del nome della policy e degli eventi di firma.
- Exception — gerarchia
NextPdfExceptiongenerata dai firmatari.