Salta ai contenuti
getnextpdf.com

Pro edizione

Firma con Cloud KMS — Riferimento approfondito

Questa pagina è il riferimento a livello di contratto per la superficie di firma cloud-KMS di NextPDF Pro. La superficie è composta da una Service Provider Interface, NextPDF\Pro\Security\Signing\Kms\KmsSignerInterface, e da tre signer per provider: AwsKmsSigner, AzureKeyVaultSigner e GcpKmsSigner. Due adapter, AwsKmsSigningStrategy e AzureKeyVaultSigningStrategy, collegano un signer al contratto SigningStrategy di Pro. Ogni signer invia al proprio provider solo un message digest tramite HTTP PSR-18. La chiave privata e il documento non attraversano mai il confine. Questa pagina espone l’API pubblica, il contratto di comportamento osservabile e le modalità di errore tipizzate. L’orchestrazione delle sessioni (RemoteSigningSession, SequentialSigner) e la marcatura temporale (PadesBtTimestamper) risiedono nelle rispettive pagine.

Questa capacità è distribuita in NextPDF Pro (nextpdf/pro) e si attiva con un envelope di licenza di tier Pro. Un deployment privo di tale entitlement non carica le classi della capacità. Confronta le edizioni e ottieni una licenza.

SimboloParametriComportamento predefinitoRestituisceSolleva o fallisce conNote
KmsSignerInterfaceEstende il contratto Core HsmSignerInterfaceSPI per driver KMS e HSM; id integrati riservati: aws-kms, azure-keyvault, gcp-kms, pkcs11, openssl-cli
KmsSignerInterface::providerId()nessunoChiave stabile di lookup nel registrynon-empty-stringI driver di terze parti devono usare un namespace per il proprio identificatore
KmsSignerInterface::signWithVersion()$data, $algorithm = 'sha256WithRSAEncryption', $keyVersion = nullUna versione della chiave null ricade sul default del providerstring ottetti di firma: RSA come restituita dal provider (collocata direttamente in SignerInfo.signature), ECDSA come ECDSA-Sig-Value DER secondo le regole CMSKeyManagementException, UnsupportedAlgorithmException, SignatureFailedExceptionLa semantica di null per provider differisce; vedere il contratto di comportamento
KmsSignerInterface::supportsAlgorithm()string $algorithmSonda di capacità; non esegue alcun I/OboolChiamata prima della selezione del provider
KmsSignerInterface::supportedAlgorithms()nessunoElenca i nomi in stile OpenSSL accettati dal providerlist<non-empty-string>
AwsKmsSignercostruttore: AwsKmsConfig, cert DER, chain DER, client PSR-18, factory PSR-17, logger PSR-3L’algoritmo predefinito è KmsSigningAlgorithm::RsaPkcs1Sha256vedere i metodifinal; PROVIDER_ID = 'aws-kms'
AwsKmsSigner::create()key id, cert DER, dipendenze PSR, chain opzionale, config, loggerCostruisce AwsKmsConfig::fromEnvironment($keyId) quando $config è nullselfLegge le variabili d’ambiente standard AWS_*
AwsKmsSigner::withAlgorithm()KmsSigningAlgorithm $algorithmRestituisce un clone modificatoselfDeve corrispondere al tipo di chiave provisionata in AWS KMS
AwsKmsSigner::sign()$data, $algorithm = 'sha256WithRSAEncryption'Delega a signWithVersion($data, $algorithm, null)stringcome signWithVersion()Percorso legacy del contratto Core a due argomenti
AzureKeyVaultSignercostruttore: AzureKeyVaultConfig, cert DER, chain DER, client PSR-18, factory PSR-17, logger PSR-3L’algoritmo predefinito è AzureSigningAlgorithm::Rs256; un access token di config inizializza il bearer tokenvedere i metodifinal; PROVIDER_ID = 'azure-keyvault'
AzureKeyVaultSigner::create()nome vault, nome chiave, cert DER, dipendenze PSR, chain opzionale, config, loggerCostruisce AzureKeyVaultConfig::fromEnvironment() quando $config è nullselfSupporta token pre-ottenuto o credenziali service-principal
AzureKeyVaultSigner::withAlgorithm()AzureSigningAlgorithm $algorithmRestituisce un clone modificatoselfLe chiavi RSA usano valori RS/PS; le chiavi EC usano valori ES
GcpKmsSignercostruttore: GcpKmsConfig, cert DER, chain DER, client PSR-18, factory PSR-17, logger PSR-3L’algoritmo predefinito è GcpKmsSigningAlgorithm::RsaSignPkcs1_2048Sha256vedere i metodifinal; PROVIDER_ID = 'gcp-kms', API_VERSION = 'v1'
GcpKmsSigner::create()project id, location, key ring, crypto key, cert DER, dipendenze PSR, chain opzionale, config, loggerCostruisce GcpKmsConfig::fromEnvironment() quando $config è nullselfL’acquisizione del bearer token è delegata al chiamante
GcpKmsSigner::withAlgorithm()GcpKmsSigningAlgorithm $algorithmSolo anteprima al tempo di config; il nome di wire per chiamata prevale al momento della firmaselfLa dimensione della chiave è fissata dalla CryptoKeyVersion provisionata
AwsKmsSigningStrategycostruttore: AwsKmsSigner $signerSincrono; isAsync() restituisce falsePropaga le eccezioni del signer incapsulatoAdapter per RemoteSigningSession::complete()
AzureKeyVaultSigningStrategycostruttore: AzureKeyVaultSigner $signerSincrono; isAsync() restituisce falsePropaga le eccezioni del signer incapsulatoAdapter per RemoteSigningSession::complete()
KmsSigningAlgorithmenum, 9 casi (RSA PKCS#1, RSA-PSS, ECDSA; SHA-256/384/512)Valori di wire SigningAlgorithm di AWS KMSInvalidArgumentException da fromOpenSslName()resolveForWireName() preserva il digest PSS configurato
AzureSigningAlgorithmenum, 9 casi (RS256ES512)Valori in stile JWA di Azure Key VaultInvalidArgumentException da fromOpenSslName()isEcdsa() contrassegna i valori il cui output richiede conversione DER
GcpKmsSigningAlgorithmenum, 10 casi (EC P-256/P-384, RSA PKCS#1, RSA-PSS)Valori di algoritmo CryptoKeyVersion di GCPUnsupportedAlgorithmException da fromOpenSslName()La risoluzione del nome di wire sceglie la più piccola dimensione di chiave corrispondente
public function providerId(): string;
public function signWithVersion(
string $data,
string $algorithm = 'sha256WithRSAEncryption',
?string $keyVersion = null,
): string;
public function supportsAlgorithm(string $algorithm): bool;
public function supportedAlgorithms(): array;
public static function create(
string $keyId,
string $certDer,
ClientInterface $httpClient,
RequestFactoryInterface $requestFactory,
StreamFactoryInterface $streamFactory,
array $chainDer = [],
?AwsKmsConfig $config = null,
?LoggerInterface $logger = null,
): self
public function withAlgorithm(KmsSigningAlgorithm $algorithm): self
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
public static function create(
string $vaultName,
string $keyName,
string $certDer,
ClientInterface $httpClient,
RequestFactoryInterface $requestFactory,
StreamFactoryInterface $streamFactory,
array $chainDer = [],
?AzureKeyVaultConfig $config = null,
?LoggerInterface $logger = null,
): self
public function withAlgorithm(AzureSigningAlgorithm $algorithm): self
public static function create(
string $projectId,
string $location,
string $keyRing,
string $cryptoKey,
string $certDer,
ClientInterface $httpClient,
RequestFactoryInterface $requestFactory,
StreamFactoryInterface $streamFactory,
array $chainDer = [],
?GcpKmsConfig $config = null,
?LoggerInterface $logger = null,
): self
public function withAlgorithm(GcpKmsSigningAlgorithm $algorithm): self
public function __construct(
private AwsKmsSigner $signer,
) {}
public function sign(string $signedAttributesDer): string
public function __construct(
private AzureKeyVaultSigner $signer,
) {}
public function sign(string $signedAttributesDer): string

KmsSignerInterface estende il contratto Core HsmSignerInterface. Aggiunge providerId(), il signWithVersion() consapevole della versione della chiave, e le sonde di capacità supportsAlgorithm() e supportedAlgorithms(). Il sign() ereditato a due argomenti delega a signWithVersion() con una versione della chiave null su tutti e tre i signer. getCertificateDer(), getCertificateChainDer() e getPublicKeyAlgorithm() sono implementati a partire dal materiale fornito dal costruttore. Le sonde di capacità non eseguono alcun I/O. Ogni signer espone inoltre gli accessor getSigningAlgorithm() e getConfig() a fini di ispezione.

Ogni signer esegue localmente l’hash di $data con il digest dell’algoritmo risolto e trasmette solo quel digest. AWS riceve un digest in base64 con MessageType: DIGEST. Azure riceve un digest in base64url nel corpo della sign request. GCP riceve un digest in base64 nel campo digest specifico dell’algoritmo. I byte del documento non compaiono mai in una request al provider. Tutto il trasporto usa un client HTTP PSR-18 standard sull’endpoint HTTPS del provider; non è coinvolto alcun SDK del vendor cloud.

signWithVersion() valida l’argomento della versione della chiave in modalità fail-closed prima che venga costruita qualsiasi request. Un valore che non supera la grammatica del provider solleva KeyManagementException e previene l’injection nel segmento di URL o nel KeyId.

ProviderVersione della chiave nullStringa vuotaGrammatica di override
AwsKmsSignerUsa AwsKmsConfig::$keyId; un alias o un ARN si risolve nella chiave corrente lato providerRifiutataUUID (con o senza trattini), alias/<name>, o un ARN di chiave/alias KMS
AzureKeyVaultSignerUsa la versione della chiave configurata; un valore di config vuoto seleziona lato server l’ultima versione abilitataRifiutataIdentificatore esadecimale di 32 caratteri
GcpKmsSignerUsa la versione pinnata in GcpKmsConfig; se nessuna è pinnata, solleva KeyManagementExceptionRifiutataId decimale di CryptoKeyVersion, sole cifre

GCP non ha una primitiva lato server per la “versione attiva”. L’endpoint asymmetric-sign opera solo su una specifica risorsa cryptoKeyVersions/{n}, quindi una versione deve sempre essere risolvibile.

Il livello strategy inoltra un nome di wire in stile OpenSSL. AWS e Azure accettano sette nomi di wire (PKCS#1 ed ECDSA a SHA-256/384/512, più RSASSA-PSS). GCP ne accetta cinque (sha256WithRSAEncryption, sha512WithRSAEncryption, RSASSA-PSS, ecdsa-with-SHA256, ecdsa-with-SHA384). Il nome di wire RSASSA-PSS non codifica un digest, quindi è ambiguo rispetto al digest. AwsKmsSigner lo risolve tramite KmsSigningAlgorithm::resolveForWireName(), che preserva il digest della variante PSS configurata. AzureKeyVaultSigner si affida alla variante PSS configurata per il nome ambiguo. Solleva UnsupportedAlgorithmException se un digest PSS risolto divergesse da quello configurato. GcpKmsSigner ri-risolve l’enum dal nome di wire a ogni chiamata; withAlgorithm() su GCP è un’anteprima al tempo di config e non modifica il comportamento al momento della firma. Un nome di wire non supportato solleva UnsupportedAlgorithmException prima di qualsiasi chiamata di rete. Su AwsKmsSigner e GcpKmsSigner, una sign call aggiorna il valore riportato successivamente da getSigningAlgorithm() all’algoritmo risolto per quella chiamata. Su AzureKeyVaultSigner, la risoluzione è locale alla chiamata e il valore configurato resta autorevole.

AWS e GCP restituiscono le firme nella forma che il CMS consuma: gli ottetti di firma RSA finiscono in SignerInfo.signature invariati, e l’ECDSA arriva codificata in DER. Azure restituisce l’ECDSA in forma raw IEEE P1363 (r||s), che il signer converte in un ECDSA-Sig-Value DER prima di restituirla.

Un adapter SigningStrategy firma gli attributi firmati codificati in DER forniti dalla sessione. In presenza di attributi firmati, l’input di firma CMS è il digest dell’intera codifica DER del valore SignedAttrs — RFC 5652 §5.4. I metodi getSignatureAlgorithmOid() e getDigestAlgorithm() dell’adapter alimentano i campi signatureAlgorithm e digestAlgorithm del SignerInfo — RFC 5652 §5.3. I byte restituiti diventano la OCTET STRING della firma del SignerInfo — RFC 5652 §5.5. L’assemblaggio CMS, la gestione di ByteRange e il ciclo di vita della sessione appartengono a RemoteSigningSession; i flussi multi-parte appartengono a SequentialSigner. Una signature-time-stamp PAdES B-T, il cui messageImprint esegue l’hash del valore di firma del SignerInfo — RFC 3161 Appendix A — è applicata da PadesBtTimestamper, non da questi signer. Tutti e tre sono documentati nel riferimento approfondito sulla sicurezza di Pro.

  • Una versione della chiave a stringa vuota è rifiutata su tutti e tre i provider. Passare null per ereditare il default configurato.
  • Una versione della chiave malformata è rifiutata prima che venga costruita qualsiasi request, con il valore incriminato indicato nell’eccezione.
  • AwsKmsSigner con un AwsKmsConfig::$keyId vuoto e una versione della chiave null solleva KeyManagementException.
  • Le risposte del provider che indicano un fallimento di key-management si mappano a KeyManagementException: AWS NotFoundException, DisabledException, KeyUnavailableException, InvalidKeyUsageException, o HTTP 404; Azure HTTP 404, KeyNotFound, KeyDisabled, o KeyNotActive; GCP HTTP 404 o 409, NOT_FOUND, FAILED_PRECONDITION, o un HTTP 400 il cui messaggio nomina una versione.
  • Altre risposte del provider diverse da 200 sollevano SignatureFailedException su AWS e GCP, e AzureKeyVaultException su Azure.
  • Un fallimento di trasporto PSR-18 durante la firma si mappa a SignatureFailedException con l’eccezione del client preservata come throwable precedente.
  • AzureKeyVaultSigner senza access token e senza credenziali service-principal solleva AzureKeyVaultException prima di qualsiasi chiamata al vault. Anche un’acquisizione fallita del token Azure AD solleva AzureKeyVaultException.
  • AzureKeyVaultSigner valida il nome del vault, il nome della chiave, la versione della chiave e il tenant id rispetto alle grammatiche pubblicate da Azure nel chokepoint della request. Un valore che contiene caratteri strutturali di URL fallisce in modo fail-closed con AzureKeyVaultException.
  • GcpKmsSigner senza un bearer token OAuth2 solleva SignatureFailedException; l’acquisizione del token è responsabilità del chiamante.
  • Una risposta del provider che non è JSON valido, o a cui manca il campo della firma, solleva SignatureFailedException (Azure: un campo value mancante solleva AzureKeyVaultException).
  • Un campo di firma del provider che non supera la decodifica base64 solleva SignatureFailedException su AWS e GCP, e AzureKeyVaultException su Azure.
  • Nessun adapter SigningStrategy per GcpKmsSigner è distribuito nella 3.1.0. Il signer GCP è consumato direttamente tramite il contratto KmsSignerInterface.

AwsKmsConfig::withFipsEndpoint() instrada le request all’endpoint kms-fips della regione. Lo stato di validazione FIPS di quell’endpoint è una proprietà di AWS, non di NextPDF. AzureKeyVaultConfig e GcpKmsConfig non espongono alcun helper dedicato per l’endpoint FIPS nella 3.1.0. Il calcolo del digest viene eseguito in-process con la funzione PHP hash() e non è di per sé un modulo validato. NextPDF Pro può operare contro un confine KMS o HSM validato FIPS, ma NextPDF non è un modulo crittografico validato FIPS e non avanza alcuna rivendicazione di certificazione FIPS.

RivendicazioneStandardClausola
La strategy firma gli attributi firmati codificati in DER; il digest di input della firma CMS copre l’intera codifica DER di SignedAttrs.RFC 5652§5.4
Gli SignedAttributes sono codificati in DER e contengono almeno content-type e message-digest; signatureAlgorithm identifica l’algoritmo del signer.RFC 5652§5.3
I byte di firma restituiti sono codificati come OCTET STRING e trasportati nel campo signature del SignerInfo.RFC 5652§5.5
Il messageImprint di una signature time-stamp esegue l’hash del valore di firma del SignerInfo (superficie B-T adiacente, non questi signer).RFC 3161Appendix A

Tutte le clausole sono parafrasate; NextPDF non riproduce il testo normativo. Si tratta di dichiarazioni di capacità, non di certificazioni. NextPDF non detiene alcuna certificazione e non ne concede alcuna. Se una firma prodotta verifichi è una decisione del verificatore rispetto ai propri trust anchor e alla propria policy; i signer restituiscono i byte di firma e non asseriscono alcun esito attendibile. La custodia della chiave, la protezione della chiave e la validazione dell’algoritmo lato provider sono proprietà del KMS configurato, non di NextPDF.

  • Disponibilità all’interno del package Pro: AwsKmsSigner dalla 1.9.0, AzureKeyVaultSigner dalla 2.0.0, GcpKmsSigner e KmsSignerInterface dalla 2.1.0. Tutti sono attuali in nextpdf/pro 3.1.0.
  • I signer dipendono solo da PSR-18, PSR-17 e PSR-3. Non è richiesto né incluso alcun SDK AWS, Azure o Google.
  • Sondare supportsAlgorithm() prima di firmare, così che un provider incompatibile venga rifiutato al momento della selezione, non a metà sessione.
  • I campi delle credenziali sono iniettati dal costruttore e contrassegnati come parametri sensibili. I messaggi di log contengono solo campi strutturali; nessuna credenziale, token o contenuto del documento viene scritto nei log.
  • Pinnare esplicitamente le versioni delle chiavi nei deployment regolamentati. I default di risoluzione dell’alias (AWS) e dell’ultima versione abilitata (Azure) sono comodi ma non deterministici tra una rotazione e l’altra.
  • I driver di terze parti implementano KmsSignerInterface e devono usare un namespace per il proprio providerId() per evitare collisioni con gli identificatori integrati riservati.

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