Ir al contenido
getnextpdf.com

Pro edición

Firma con KMS en la nube — Referencia detallada

Esta página es la referencia a nivel de contrato de la superficie de firma con KMS en la nube de NextPDF Pro. La superficie consta de una interfaz de proveedor de servicios, NextPDF\Pro\Security\Signing\Kms\KmsSignerInterface, y tres firmadores de proveedor: AwsKmsSigner, AzureKeyVaultSigner y GcpKmsSigner. Dos adaptadores, AwsKmsSigningStrategy y AzureKeyVaultSigningStrategy, conectan un firmador con el contrato SigningStrategy de Pro. Cada firmador envía únicamente un digest de mensaje a su proveedor a través de HTTP PSR-18. La clave privada y el documento nunca cruzan el límite. Esta página expone la API pública, el contrato de comportamiento observable y los modos de fallo tipados. La orquestación de sesión (RemoteSigningSession, SequentialSigner) y el sellado de tiempo (PadesBtTimestamper) residen en sus propias páginas.

Esta capacidad se distribuye en NextPDF Pro (nextpdf/pro) y se activa con un sobre de licencia de nivel Pro. Un despliegue sin ese derecho no carga las clases de la capacidad. Compara ediciones y obtén una licencia.

SímboloParámetrosComportamiento por defectoDevuelveLanza o falla conNotas
KmsSignerInterfaceExtiende el contrato HsmSignerInterface de CoreSPI para drivers de KMS y HSM; ids integrados reservados: aws-kms, azure-keyvault, gcp-kms, pkcs11, openssl-cli
KmsSignerInterface::providerId()ningunoClave estable de búsqueda en el registronon-empty-stringLos drivers de terceros deben espaciar por nombre su identificador
KmsSignerInterface::signWithVersion()$data, $algorithm = 'sha256WithRSAEncryption', $keyVersion = nullUna versión de clave null recae en el valor por defecto del proveedoroctetos de firma string: RSA tal como los devuelve el proveedor (colocados directamente en SignerInfo.signature), ECDSA como DER ECDSA-Sig-Value según las reglas de CMSKeyManagementException, UnsupportedAlgorithmException, SignatureFailedExceptionLa semántica de null difiere por proveedor; véase el contrato de comportamiento
KmsSignerInterface::supportsAlgorithm()string $algorithmSondeo de capacidad; no realiza E/SboolSe invoca antes de la selección del proveedor
KmsSignerInterface::supportedAlgorithms()ningunoLista los nombres al estilo OpenSSL que acepta el proveedorlist<non-empty-string>
AwsKmsSignerconstructor: AwsKmsConfig, cert DER, cadena DER, cliente PSR-18, fábricas PSR-17, logger PSR-3El algoritmo por defecto es KmsSigningAlgorithm::RsaPkcs1Sha256véanse los métodosfinal; PROVIDER_ID = 'aws-kms'
AwsKmsSigner::create()id de clave, cert DER, dependencias PSR, cadena opcional, config, loggerConstruye AwsKmsConfig::fromEnvironment($keyId) cuando $config es nullselfLee las variables de entorno estándar AWS_*
AwsKmsSigner::withAlgorithm()KmsSigningAlgorithm $algorithmDevuelve un clon modificadoselfDebe coincidir con el tipo de clave aprovisionada en AWS KMS
AwsKmsSigner::sign()$data, $algorithm = 'sha256WithRSAEncryption'Delega en signWithVersion($data, $algorithm, null)stringcomo signWithVersion()Ruta del contrato heredado de Core con dos argumentos
AzureKeyVaultSignerconstructor: AzureKeyVaultConfig, cert DER, cadena DER, cliente PSR-18, fábricas PSR-17, logger PSR-3El algoritmo por defecto es AzureSigningAlgorithm::Rs256; un token de acceso de config siembra el token bearervéanse los métodosfinal; PROVIDER_ID = 'azure-keyvault'
AzureKeyVaultSigner::create()nombre del vault, nombre de la clave, cert DER, dependencias PSR, cadena opcional, config, loggerConstruye AzureKeyVaultConfig::fromEnvironment() cuando $config es nullselfAdmite un token pre-obtenido o credenciales de service principal
AzureKeyVaultSigner::withAlgorithm()AzureSigningAlgorithm $algorithmDevuelve un clon modificadoselfLas claves RSA usan valores RS/PS; las claves EC usan valores ES
GcpKmsSignerconstructor: GcpKmsConfig, cert DER, cadena DER, cliente PSR-18, fábricas PSR-17, logger PSR-3El algoritmo por defecto es GcpKmsSigningAlgorithm::RsaSignPkcs1_2048Sha256véanse los métodosfinal; PROVIDER_ID = 'gcp-kms', API_VERSION = 'v1'
GcpKmsSigner::create()id de proyecto, ubicación, key ring, crypto key, cert DER, dependencias PSR, cadena opcional, config, loggerConstruye GcpKmsConfig::fromEnvironment() cuando $config es nullselfLa adquisición del token bearer se delega en el invocador
GcpKmsSigner::withAlgorithm()GcpKmsSigningAlgorithm $algorithmSolo vista previa en tiempo de configuración; el nombre de cable por llamada prevalece en el momento de firmarselfEl tamaño de clave lo fija la CryptoKeyVersion aprovisionada
AwsKmsSigningStrategyconstructor: AwsKmsSigner $signerSíncrono; isAsync() devuelve falsePropaga las excepciones del firmador envueltoAdaptador para RemoteSigningSession::complete()
AzureKeyVaultSigningStrategyconstructor: AzureKeyVaultSigner $signerSíncrono; isAsync() devuelve falsePropaga las excepciones del firmador envueltoAdaptador para RemoteSigningSession::complete()
KmsSigningAlgorithmenum, 9 casos (RSA PKCS#1, RSA-PSS, ECDSA; SHA-256/384/512)Valores de cable SigningAlgorithm de AWS KMSInvalidArgumentException desde fromOpenSslName()resolveForWireName() preserva el digest PSS configurado
AzureSigningAlgorithmenum, 9 casos (RS256ES512)Valores al estilo JWA de Azure Key VaultInvalidArgumentException desde fromOpenSslName()isEcdsa() marca los valores cuya salida necesita conversión a DER
GcpKmsSigningAlgorithmenum, 10 casos (EC P-256/P-384, RSA PKCS#1, RSA-PSS)Valores de algoritmo de CryptoKeyVersion de GCPUnsupportedAlgorithmException desde fromOpenSslName()La resolución del nombre de cable elige el menor tamaño de clave coincidente
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 extiende el contrato HsmSignerInterface de Core. Añade providerId(), el signWithVersion() consciente de la versión de clave, y los sondeos de capacidad supportsAlgorithm() y supportedAlgorithms(). El sign() heredado de dos argumentos delega en signWithVersion() con una versión de clave null en los tres firmadores. getCertificateDer(), getCertificateChainDer() y getPublicKeyAlgorithm() se implementan a partir del material suministrado en el constructor. Los sondeos de capacidad no realizan E/S. Cada firmador expone además los accesores getSigningAlgorithm() y getConfig() para inspección.

Cada firmador hace hash de $data localmente con el digest del algoritmo resuelto y transmite únicamente ese digest. AWS recibe un digest en base64 con MessageType: DIGEST. Azure recibe un digest en base64url en el cuerpo de la petición de firma. GCP recibe un digest en base64 en el campo de digest específico del algoritmo. Los bytes del documento nunca aparecen en una petición del proveedor. Todo el transporte usa un cliente HTTP PSR-18 estándar sobre el endpoint HTTPS del proveedor; no interviene ningún SDK del proveedor en la nube.

signWithVersion() valida el argumento de versión de clave fail-closed antes de construir cualquier petición. Un valor que no supera la gramática del proveedor lanza KeyManagementException e impide la inyección de segmento de URL o de KeyId.

ProveedorVersión de clave nullCadena vacíaGramática de sobrescritura
AwsKmsSignerUsa AwsKmsConfig::$keyId; un alias o ARN se resuelve a la clave actual del lado del proveedorRechazadaUUID (con o sin guiones), alias/<name>, o un ARN de clave/alias de KMS
AzureKeyVaultSignerUsa la versión de clave configurada; un valor de config vacío selecciona la última versión habilitada del lado del servidorRechazadaIdentificador hexadecimal de 32 caracteres
GcpKmsSignerUsa la versión anclada en GcpKmsConfig; sin ninguna anclada, lanza KeyManagementExceptionRechazadaId decimal de CryptoKeyVersion, solo dígitos

GCP no tiene una primitiva de “versión activa” del lado del servidor. El endpoint de firma asimétrica opera únicamente sobre un recurso cryptoKeyVersions/{n} específico, de modo que una versión siempre debe ser resoluble.

La capa de estrategia reenvía un nombre de cable al estilo OpenSSL. AWS y Azure aceptan siete nombres de cable (PKCS#1 y ECDSA en SHA-256/384/512, más RSASSA-PSS). GCP acepta cinco (sha256WithRSAEncryption, sha512WithRSAEncryption, RSASSA-PSS, ecdsa-with-SHA256, ecdsa-with-SHA384). El nombre de cable RSASSA-PSS no codifica un digest, por lo que es ambiguo respecto al digest. AwsKmsSigner lo resuelve a través de KmsSigningAlgorithm::resolveForWireName(), que preserva el digest de la variante PSS configurada. AzureKeyVaultSigner confía en la variante PSS configurada para el nombre ambiguo. Lanza UnsupportedAlgorithmException si un digest PSS resuelto divergiera del configurado. GcpKmsSigner vuelve a resolver el enum a partir del nombre de cable en cada llamada; withAlgorithm() en GCP es una vista previa en tiempo de configuración y no cambia el comportamiento en el momento de firmar. Un nombre de cable no admitido lanza UnsupportedAlgorithmException antes de cualquier llamada de red. En AwsKmsSigner y GcpKmsSigner, una llamada de firma actualiza el valor que luego reporta getSigningAlgorithm() al algoritmo resuelto por llamada. En AzureKeyVaultSigner, la resolución es local a la llamada y el valor configurado sigue siendo autoritativo.

AWS y GCP devuelven las firmas en la forma que consume CMS: los octetos de firma RSA van a SignerInfo.signature sin cambios, y ECDSA llega codificado en DER. Azure devuelve ECDSA en formato IEEE P1363 en crudo (r||s), que el firmador convierte a un DER ECDSA-Sig-Value antes de devolverlo.

Un adaptador SigningStrategy firma los atributos firmados codificados en DER que suministra la sesión. Con atributos firmados presentes, la entrada de firma de CMS es el digest de la codificación DER completa del valor SignedAttrs — RFC 5652 §5.4. Los métodos getSignatureAlgorithmOid() y getDigestAlgorithm() del adaptador alimentan los campos signatureAlgorithm y digestAlgorithm del SignerInfo — RFC 5652 §5.3. Los bytes devueltos pasan a ser el OCTET STRING de firma del SignerInfo — RFC 5652 §5.5. El ensamblado de CMS, el manejo de ByteRange y el ciclo de vida de la sesión pertenecen a RemoteSigningSession; los flujos multiparte pertenecen a SequentialSigner. Un sello de tiempo de firma PAdES B-T, cuyo messageImprint hace hash del valor de firma del SignerInfo — RFC 3161 Appendix A —, lo aplica PadesBtTimestamper, no estos firmadores. Los tres se documentan en la referencia detallada de seguridad de Pro.

  • Una versión de clave de cadena vacía se rechaza en los tres proveedores. Pasa null para heredar el valor por defecto configurado.
  • Una versión de clave malformada se rechaza antes de construir cualquier petición, con el valor infractor nombrado en la excepción.
  • AwsKmsSigner con un AwsKmsConfig::$keyId vacío y una versión de clave null lanza KeyManagementException.
  • Las respuestas del proveedor que indican un fallo de gestión de claves se mapean 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 cuyo mensaje nombra una versión.
  • Otras respuestas del proveedor distintas de 200 lanzan SignatureFailedException en AWS y GCP, y AzureKeyVaultException en Azure.
  • Un fallo de transporte PSR-18 durante la firma se mapea a SignatureFailedException con la excepción del cliente preservada como el throwable previo.
  • AzureKeyVaultSigner sin token de acceso y sin credenciales de service principal lanza AzureKeyVaultException antes de cualquier llamada al vault. Una adquisición fallida de token de Azure AD también lanza AzureKeyVaultException.
  • AzureKeyVaultSigner valida el nombre del vault, el nombre de la clave, la versión de la clave y el id de tenant contra las gramáticas publicadas de Azure en el punto de estrangulamiento de la petición. Un valor que porte caracteres estructurales de URL falla en modo cerrado con AzureKeyVaultException.
  • GcpKmsSigner sin token bearer OAuth2 lanza SignatureFailedException; la adquisición del token es responsabilidad del invocador.
  • Una respuesta del proveedor que no es JSON válido, o a la que le falta el campo de firma, lanza SignatureFailedException (Azure: la falta de un campo value lanza AzureKeyVaultException).
  • Un campo de firma del proveedor que no supera la decodificación base64 lanza SignatureFailedException en AWS y GCP, y AzureKeyVaultException en Azure.
  • En 3.1.0 no se distribuye ningún adaptador SigningStrategy para GcpKmsSigner. El firmador de GCP se consume directamente a través del contrato KmsSignerInterface.

AwsKmsConfig::withFipsEndpoint() enruta las peticiones al endpoint kms-fips de la región. El estado de validación FIPS de ese endpoint es una propiedad de AWS, no de NextPDF. AzureKeyVaultConfig y GcpKmsConfig no exponen ningún helper de endpoint FIPS dedicado en 3.1.0. El cálculo del digest se ejecuta en proceso con la función hash() de PHP y no es en sí mismo un módulo validado. NextPDF Pro puede operar contra un límite de KMS o HSM validado por FIPS, pero NextPDF no es un módulo criptográfico validado por FIPS y no realiza ninguna afirmación de certificación FIPS.

AfirmaciónEstándarCláusula
La estrategia firma los atributos firmados codificados en DER; el digest de entrada de firma de CMS cubre la codificación DER completa de SignedAttrs.RFC 5652§5.4
SignedAttributes están codificados en DER y portan content-type y message-digest como mínimo; signatureAlgorithm identifica el algoritmo del firmador.RFC 5652§5.3
Los bytes de firma devueltos se codifican como un OCTET STRING y se portan en el campo de firma del SignerInfo.RFC 5652§5.5
El messageImprint de un sello de tiempo de firma hace hash del valor de firma del SignerInfo (superficie B-T adyacente, no estos firmadores).RFC 3161Appendix A

Todas las cláusulas están parafraseadas; NextPDF no reproduce texto normativo. Son declaraciones de capacidad, no certificaciones. NextPDF no posee ninguna certificación ni la otorga. Si una firma producida verifica o no es la decisión del verificador frente a sus propios anclajes de confianza y su política; los firmadores devuelven bytes de firma y no afirman ningún resultado de confianza. La custodia de la clave, la protección de la clave y la validación de algoritmos del lado del proveedor son propiedades del KMS configurado, no de NextPDF.

  • Disponibilidad dentro del paquete Pro: AwsKmsSigner desde 1.9.0, AzureKeyVaultSigner desde 2.0.0, GcpKmsSigner y KmsSignerInterface desde 2.1.0. Todos están vigentes en nextpdf/pro 3.1.0.
  • Los firmadores dependen únicamente de PSR-18, PSR-17 y PSR-3. No se requiere ni se incluye ningún SDK de AWS, Azure o Google.
  • Sondea supportsAlgorithm() antes de firmar para que un proveedor incompatible se rechace en el momento de la selección, no a mitad de sesión.
  • Los campos de credenciales se inyectan por constructor y se marcan como parámetros sensibles. Los mensajes de log portan solo campos estructurales; ningún credencial, token o contenido de documento se escribe en los logs.
  • Ancla las versiones de clave explícitamente en despliegues regulados. Los valores por defecto de resolución de alias (AWS) y de última habilitada (Azure) son cómodos pero no deterministas entre rotaciones.
  • Los drivers de terceros implementan KmsSignerInterface y deben espaciar por nombre su providerId() para evitar colisiones con los identificadores integrados reservados.

Esta página documenta únicamente el comportamiento observable externamente y la superficie de la API pública admitida. Las rutas de espacio de nombres internas, las clases auxiliares, las tablas de mecanismos, los nombres de archivo de runbook y los prefijos de ticket quedan fuera de alcance.