Pular para o conteúdo
getnextpdf.com

Pro edição

Assinatura com Cloud KMS — Referência Profunda

Esta página é a referência em nível de contrato para a superfície de assinatura com cloud KMS do NextPDF Pro. A superfície consiste em uma Service Provider Interface, NextPDF\Pro\Security\Signing\Kms\KmsSignerInterface, e três signers de provedor: AwsKmsSigner, AzureKeyVaultSigner e GcpKmsSigner. Dois adaptadores, AwsKmsSigningStrategy e AzureKeyVaultSigningStrategy, conectam um signer ao contrato SigningStrategy do Pro. Cada signer envia apenas um digest de mensagem ao seu provedor via HTTP PSR-18. A chave privada e o documento nunca cruzam a fronteira. Esta página declara a API pública, o contrato de comportamento observável e os modos de falha tipados. A orquestração de sessão (RemoteSigningSession, SequentialSigner) e o timestamping (PadesBtTimestamper) ficam em suas próprias páginas.

Esta capacidade é distribuída no NextPDF Pro (nextpdf/pro) e é ativada com um envelope de licença de nível Pro. Uma implantação sem essa habilitação não carrega as classes da capacidade. Compare as edições e obtenha uma licença.

SímboloParâmetrosComportamento padrãoRetornaLança ou falha comNotas
KmsSignerInterfaceEstende o contrato Core HsmSignerInterfaceSPI para drivers KMS e HSM; ids embutidos reservados: aws-kms, azure-keyvault, gcp-kms, pkcs11, openssl-cli
KmsSignerInterface::providerId()nenhumChave estável de lookup no registronon-empty-stringDrivers de terceiros devem usar namespace no seu identificador
KmsSignerInterface::signWithVersion()$data, $algorithm = 'sha256WithRSAEncryption', $keyVersion = nullVersão de chave null recorre ao padrão do provedoroctetos de assinatura string: RSA como retornado pelo provedor (colocado diretamente em SignerInfo.signature), ECDSA como DER ECDSA-Sig-Value conforme as regras do CMSKeyManagementException, UnsupportedAlgorithmException, SignatureFailedExceptionA semântica de null difere por provedor; veja o contrato de comportamento
KmsSignerInterface::supportsAlgorithm()string $algorithmSonda de capacidade; não realiza I/OboolChamado antes da seleção do provedor
KmsSignerInterface::supportedAlgorithms()nenhumLista os nomes no estilo OpenSSL que o provedor aceitalist<non-empty-string>
AwsKmsSignerconstrutor: AwsKmsConfig, cert DER, chain DER, cliente PSR-18, fábricas PSR-17, logger PSR-3O algoritmo assume por padrão KmsSigningAlgorithm::RsaPkcs1Sha256veja os métodosfinal; PROVIDER_ID = 'aws-kms'
AwsKmsSigner::create()id da chave, cert DER, dependências PSR, chain opcional, config, loggerConstrói AwsKmsConfig::fromEnvironment($keyId) quando $config é nullselfLê as variáveis de ambiente padrão AWS_*
AwsKmsSigner::withAlgorithm()KmsSigningAlgorithm $algorithmRetorna um clone modificadoselfDeve corresponder ao tipo de chave provisionado no AWS KMS
AwsKmsSigner::sign()$data, $algorithm = 'sha256WithRSAEncryption'Delega a signWithVersion($data, $algorithm, null)stringcomo signWithVersion()Caminho legado do contrato Core de dois argumentos
AzureKeyVaultSignerconstrutor: AzureKeyVaultConfig, cert DER, chain DER, cliente PSR-18, fábricas PSR-17, logger PSR-3O algoritmo assume por padrão AzureSigningAlgorithm::Rs256; um token de acesso da config semeia o bearer tokenveja os métodosfinal; PROVIDER_ID = 'azure-keyvault'
AzureKeyVaultSigner::create()nome do vault, nome da chave, cert DER, dependências PSR, chain opcional, config, loggerConstrói AzureKeyVaultConfig::fromEnvironment() quando $config é nullselfSuporta token pré-obtido ou credenciais de service principal
AzureKeyVaultSigner::withAlgorithm()AzureSigningAlgorithm $algorithmRetorna um clone modificadoselfChaves RSA usam valores RS/PS; chaves EC usam valores ES
GcpKmsSignerconstrutor: GcpKmsConfig, cert DER, chain DER, cliente PSR-18, fábricas PSR-17, logger PSR-3O algoritmo assume por padrão GcpKmsSigningAlgorithm::RsaSignPkcs1_2048Sha256veja os métodosfinal; PROVIDER_ID = 'gcp-kms', API_VERSION = 'v1'
GcpKmsSigner::create()id do projeto, localização, key ring, crypto key, cert DER, dependências PSR, chain opcional, config, loggerConstrói GcpKmsConfig::fromEnvironment() quando $config é nullselfA aquisição do bearer token é delegada ao chamador
GcpKmsSigner::withAlgorithm()GcpKmsSigningAlgorithm $algorithmApenas prévia em tempo de config; o nome de fio por chamada prevalece no momento da assinaturaselfO tamanho da chave é fixado pela CryptoKeyVersion provisionada
AwsKmsSigningStrategyconstrutor: AwsKmsSigner $signerSíncrono; isAsync() retorna falsePropaga as exceções do signer encapsuladoAdaptador para RemoteSigningSession::complete()
AzureKeyVaultSigningStrategyconstrutor: AzureKeyVaultSigner $signerSíncrono; isAsync() retorna falsePropaga as exceções do signer encapsuladoAdaptador para RemoteSigningSession::complete()
KmsSigningAlgorithmenum, 9 casos (RSA PKCS#1, RSA-PSS, ECDSA; SHA-256/384/512)Valores de fio SigningAlgorithm do AWS KMSInvalidArgumentException de fromOpenSslName()resolveForWireName() preserva o digest PSS configurado
AzureSigningAlgorithmenum, 9 casos (RS256ES512)Valores estilo JWA do Azure Key VaultInvalidArgumentException de fromOpenSslName()isEcdsa() marca valores cuja saída precisa de conversão DER
GcpKmsSigningAlgorithmenum, 10 casos (EC P-256/P-384, RSA PKCS#1, RSA-PSS)Valores de algoritmo CryptoKeyVersion do GCPUnsupportedAlgorithmException de fromOpenSslName()A resolução do nome de fio escolhe o menor tamanho de chave correspondente
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 o contrato Core HsmSignerInterface. Ele adiciona providerId(), o signWithVersion() ciente da versão de chave, e as sondas de capacidade supportsAlgorithm() e supportedAlgorithms(). O sign() herdado de dois argumentos delega a signWithVersion() com versão de chave null nos três signers. getCertificateDer(), getCertificateChainDer() e getPublicKeyAlgorithm() são implementados a partir do material fornecido pelo construtor. As sondas de capacidade não realizam I/O. Cada signer também expõe os acessadores getSigningAlgorithm() e getConfig() para inspeção.

Cada signer faz o hash de $data localmente com o digest do algoritmo resolvido e transmite apenas esse digest. A AWS recebe um digest em base64 com MessageType: DIGEST. O Azure recebe um digest em base64url no corpo da requisição de assinatura. O GCP recebe um digest em base64 no campo de digest específico do algoritmo. Os bytes do documento nunca aparecem em uma requisição ao provedor. Todo o transporte usa um cliente HTTP PSR-18 padrão sobre o endpoint HTTPS do provedor; nenhum SDK de fornecedor de nuvem está envolvido.

signWithVersion() valida o argumento de versão de chave de forma fail-closed antes de qualquer requisição ser construída. Um valor que não passa na gramática do provedor levanta KeyManagementException e impede a injeção de segmento de URL ou de KeyId.

ProvedorVersão de chave nullString vaziaGramática de override
AwsKmsSignerUsa AwsKmsConfig::$keyId; um alias ou ARN resolve para a chave atual no lado do provedorRejeitadoUUID (com ou sem traços), alias/<name>, ou um ARN de chave/alias do KMS
AzureKeyVaultSignerUsa a versão de chave configurada; um valor de config vazio seleciona a versão habilitada mais recente no servidorRejeitadoIdentificador hexadecimal de 32 caracteres
GcpKmsSignerUsa a versão fixada em GcpKmsConfig; sem nenhuma fixada, levanta KeyManagementExceptionRejeitadoId decimal de CryptoKeyVersion, apenas dígitos

O GCP não tem uma primitiva de “versão ativa” no servidor. O endpoint de assinatura assimétrica opera apenas sobre um recurso cryptoKeyVersions/{n} específico, então uma versão deve sempre ser resolvível.

A camada de estratégia encaminha um nome de fio no estilo OpenSSL. AWS e Azure aceitam sete nomes de fio (PKCS#1 e ECDSA em SHA-256/384/512, mais RSASSA-PSS). O GCP aceita cinco (sha256WithRSAEncryption, sha512WithRSAEncryption, RSASSA-PSS, ecdsa-with-SHA256, ecdsa-with-SHA384). O nome de fio RSASSA-PSS não codifica um digest, então é ambíguo quanto ao digest. AwsKmsSigner o resolve através de KmsSigningAlgorithm::resolveForWireName(), que preserva o digest da variante PSS configurada. AzureKeyVaultSigner confia na variante PSS configurada para o nome ambíguo. Ele levanta UnsupportedAlgorithmException se um digest PSS resolvido divergir do configurado. GcpKmsSigner re-resolve o enum a partir do nome de fio em cada chamada; withAlgorithm() no GCP é uma prévia em tempo de config e não altera o comportamento no momento da assinatura. Um nome de fio não suportado levanta UnsupportedAlgorithmException antes de qualquer chamada de rede. Em AwsKmsSigner e GcpKmsSigner, uma chamada de assinatura atualiza o valor posteriormente reportado por getSigningAlgorithm() para o algoritmo resolvido por chamada. Em AzureKeyVaultSigner, a resolução é local à chamada e o valor configurado permanece autoritativo.

AWS e GCP retornam assinaturas na forma que o CMS consome: os octetos de assinatura RSA vão para SignerInfo.signature sem alteração, e o ECDSA chega codificado em DER. O Azure retorna ECDSA em formato bruto IEEE P1363 (r||s), que o signer converte para um DER ECDSA-Sig-Value antes de retornar.

Um adaptador SigningStrategy assina os atributos assinados codificados em DER fornecidos pela sessão. Com atributos assinados presentes, a entrada da assinatura do CMS é o digest da codificação DER completa do valor SignedAttrs — RFC 5652 §5.4. O getSignatureAlgorithmOid() e o getDigestAlgorithm() do adaptador alimentam os campos signatureAlgorithm e digestAlgorithm do SignerInfo — RFC 5652 §5.3. Os bytes retornados tornam-se o OCTET STRING da assinatura do SignerInfo — RFC 5652 §5.5. A montagem do CMS, o tratamento de ByteRange e o ciclo de vida da sessão pertencem a RemoteSigningSession; os fluxos multipartes pertencem a SequentialSigner. Um carimbo de tempo de assinatura PAdES B-T, cujo messageImprint faz o hash do valor de assinatura do SignerInfo — RFC 3161 Appendix A — é aplicado por PadesBtTimestamper, não por estes signers. Todos os três estão documentados na referência detalhada de segurança do Pro.

  • Uma versão de chave em string vazia é rejeitada nos três provedores. Passe null para herdar o padrão configurado.
  • Uma versão de chave malformada é rejeitada antes de qualquer requisição ser construída, com o valor ofensivo nomeado na exceção.
  • AwsKmsSigner com um AwsKmsConfig::$keyId vazio e uma versão de chave null levanta KeyManagementException.
  • Respostas do provedor que indicam uma falha de gerenciamento de chave mapeiam para KeyManagementException: AWS NotFoundException, DisabledException, KeyUnavailableException, InvalidKeyUsageException, ou HTTP 404; Azure HTTP 404, KeyNotFound, KeyDisabled, ou KeyNotActive; GCP HTTP 404 ou 409, NOT_FOUND, FAILED_PRECONDITION, ou um HTTP 400 cuja mensagem nomeia uma versão.
  • Outras respostas de provedor diferentes de 200 levantam SignatureFailedException no AWS e no GCP, e AzureKeyVaultException no Azure.
  • Uma falha de transporte PSR-18 durante a assinatura mapeia para SignatureFailedException com a exceção do cliente preservada como o throwable anterior.
  • AzureKeyVaultSigner sem token de acesso e sem credenciais de service principal levanta AzureKeyVaultException antes de qualquer chamada ao vault. Uma aquisição de token do Azure AD que falha também levanta AzureKeyVaultException.
  • AzureKeyVaultSigner valida o nome do vault, o nome da chave, a versão de chave e o tenant id contra as gramáticas publicadas do Azure no ponto de estrangulamento da requisição. Um valor que carrega caracteres estruturais de URL falha de forma fail-closed com AzureKeyVaultException.
  • GcpKmsSigner sem um bearer token OAuth2 levanta SignatureFailedException; a aquisição do token é responsabilidade do chamador.
  • Uma resposta de provedor que não é JSON válido, ou que não tem o campo de assinatura, levanta SignatureFailedException (Azure: um campo value ausente levanta AzureKeyVaultException).
  • Um campo de assinatura do provedor que falha na decodificação base64 levanta SignatureFailedException no AWS e no GCP, e AzureKeyVaultException no Azure.
  • Nenhum adaptador SigningStrategy para GcpKmsSigner é distribuído no 3.1.0. O signer do GCP é consumido diretamente através do contrato KmsSignerInterface.

AwsKmsConfig::withFipsEndpoint() roteia as requisições para o endpoint kms-fips da região. O status de validação FIPS desse endpoint é uma propriedade da AWS, não do NextPDF. AzureKeyVaultConfig e GcpKmsConfig não expõem nenhum helper dedicado de endpoint FIPS no 3.1.0. O cálculo do digest roda em processo com a função PHP hash() e não é, ele mesmo, um módulo validado. O NextPDF Pro pode operar contra uma fronteira KMS ou HSM validada por FIPS, mas o NextPDF não é um módulo criptográfico validado por FIPS e não faz nenhuma alegação de certificação FIPS.

AlegaçãoPadrãoCláusula
A estratégia assina os atributos assinados codificados em DER; o digest de entrada da assinatura do CMS cobre a codificação DER completa de SignedAttrs.RFC 5652§5.4
SignedAttributes são codificados em DER e carregam content-type e message-digest no mínimo; signatureAlgorithm identifica o algoritmo do signer.RFC 5652§5.3
Os bytes de assinatura retornados são codificados como um OCTET STRING e carregados no campo de assinatura do SignerInfo.RFC 5652§5.5
O messageImprint de um carimbo de tempo de assinatura faz o hash do valor de assinatura do SignerInfo (superfície B-T adjacente, não estes signers).RFC 3161Appendix A

Todas as cláusulas são parafraseadas; o NextPDF não reproduz texto normativo. Estas são declarações de capacidade, não certificações. O NextPDF não detém nenhuma certificação e não concede nenhuma. Se uma assinatura produzida verifica ou não é decisão do verificador contra suas próprias âncoras de confiança e política; os signers retornam os bytes de assinatura e não asseguram nenhum resultado confiável. A custódia da chave, a proteção da chave e a validação de algoritmo do lado do provedor são propriedades do KMS configurado, não do NextPDF.

  • Disponibilidade dentro do pacote Pro: AwsKmsSigner desde 1.9.0, AzureKeyVaultSigner desde 2.0.0, GcpKmsSigner e KmsSignerInterface desde 2.1.0. Todos são atuais no nextpdf/pro 3.1.0.
  • Os signers dependem apenas de PSR-18, PSR-17 e PSR-3. Nenhum SDK da AWS, Azure ou Google é necessário ou empacotado.
  • Sonde supportsAlgorithm() antes de assinar para que um provedor incompatível seja rejeitado no momento da seleção, não no meio da sessão.
  • Os campos de credencial são injetados pelo construtor e marcados como parâmetros sensíveis. As mensagens de log carregam apenas campos estruturais; nenhuma credencial, token ou conteúdo de documento é gravado nos logs.
  • Fixe as versões de chave explicitamente em implantações reguladas. Os padrões de resolução por alias (AWS) e de versão habilitada mais recente (Azure) são convenientes, mas não são determinísticos entre rotações.
  • Drivers de terceiros implementam KmsSignerInterface e devem usar namespace no seu providerId() para evitar colisões com os identificadores embutidos reservados.

Esta página documenta apenas o comportamento observável externamente e a superfície de API pública suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de ticket estão fora de escopo.