Ir al contenido
getnextpdf.com

Enterprise edición

Firma con módulo de seguridad de hardware (PKCS#11)

NextPDF Enterprise firma un PDF con una clave contenida dentro de un módulo de seguridad de hardware (HSM). Se apunta el firmante a un token PKCS#11 —una tarjeta inteligente, un token de bus serie universal (USB) o un HSM conectado en red— y la operación de firma se ejecuta en el dispositivo. La clave privada nunca sale del límite del token. Esta página se mantiene a nivel de comportamiento: expone qué hace el firmante, qué proporciona usted y dónde la custodia de claves deja de ser responsabilidad de NextPDF.

El firmante HSM se resuelve a través del contrato de firmante de Core, de modo que su aplicación depende del contrato, no del tipo concreto de Enterprise. Amplía la misma ruta de firma de sintaxis de mensajes criptográficos (CMS) que utiliza Core, salvo que la operación criptográfica se delega en el token.

Los requisitos previos se exponen en el frontmatter y se repiten en Requisitos previos, de modo que no le sorprendan a mitad de la tarea.

Esta capacidad se distribuye en NextPDF Enterprise (nextpdf/enterprise) y se activa con un sobre de licencia de nivel Enterprise. Un despliegue sin ese derecho no carga las clases de la capacidad. Comparar ediciones y obtener una licencia.

NextPDF Core incluye un firmante CMS por software que contiene la clave en proceso o acepta una a través del contrato de estrategia de firma de Core; NextPDF Pro añade estrategias de firma remota y de servicio de gestión de claves (KMS) en la nube. La custodia de claves en hardware a través de PKCS#11 es una capacidad de Enterprise y no la proporcionan Core ni Pro.

Un token PKCS#11 expone objetos criptográficos —certificados y claves privadas— detrás de una biblioteca compartida del proveedor. El firmante de Enterprise adapta esa biblioteca:

  1. Abre la biblioteca compartida del token una vez por proceso y almacena en caché el identificador del módulo, porque PKCS#11 requiere que el módulo se inicialice exactamente una vez por proceso.
  2. Abre una sesión en la ranura configurada e inicia sesión con el PIN suministrado. El inicio de sesión autentica al usuario antes de cualquier operación con la clave privada, según PKCS#11 v3.1 §5.6.8.
  3. Localiza el certificado de firma en el token por etiqueta, lee el certificado en formato de reglas de codificación distinguidas (DER) y detecta el algoritmo de clave pública.
  4. En el momento de la firma, localiza la clave privada por etiqueta —que puede diferir de la etiqueta del certificado en algunos tokens— y le pide al token que calcule la firma. Los datos a firmar se pasan; la clave permanece en el dispositivo.

El firmante admite RSA con relleno PKCS#1 v1.5 (SHA-256, SHA-384, SHA-512), RSA con relleno de esquema de firma probabilística (PSS) donde la longitud del salt es igual a la longitud del resumen, y el algoritmo de firma digital de curva elíptica (ECDSA) con SHA-256, SHA-384 y SHA-512. La curva y el resumen de ECDSA se emparejan convencionalmente —P-256 con SHA-256, P-384 con SHA-384, P-521 con SHA-512—, siguiendo el emparejamiento recomendado en RFC 5480. Un token devuelve una firma ECDSA como una concatenación en bruto de los dos enteros; el firmante la convierte al formato codificado en DER que esperan PDF y OpenSSL.

Para la generación de firma, una clave RSA de al menos 2048 bits y un orden de curva ECDSA de al menos 224 bits son los mínimos aceptables según NIST SP 800-131A Rev.2 §3. Aprovisione la clave de su token a esos tamaños o por encima de ellos.

Existe una ruta alternativa de motor OpenSSL para tokens respaldados por motor. En OpenSSL 3.x, la extensión OpenSSL de PHP no expone la interfaz de programación de aplicaciones (API) del motor, por lo que la clase de motor está obsoleta; la ruta respaldada por motor admitida ejecuta el binario de línea de comandos de OpenSSL. Prefiera la ruta directa PKCS#11 cuando su token disponga de una biblioteca PKCS#11.

La decisión determinante es que la clave privada nunca sale del token. Por eso el firmante delega la operación criptográfica en el dispositivo y solo mueve los datos a firmar a través de la costura PKCS#11. Nunca lee ni reconstruye material de clave en la memoria de PHP. Se resuelve a través del contrato HsmSignerInterface de Core en lugar de un tipo concreto de Enterprise, de modo que el código de firma es idéntico tanto si la clave reside en software, en un KMS en la nube o en un token de hardware. Almacena en caché el identificador del módulo una vez por proceso porque PKCS#11 inicializa cada módulo exactamente una vez por proceso, y luego convierte la salida ECDSA en bruto del token a DER para que los validadores vean la codificación que esperan. La custodia, no la conveniencia, determina la forma: el límite de confianza permanece en el borde del dispositivo.

Contexto de diseño: firma respaldada por HSM.

Antes de firmar con un HSM, confirme cada elemento:

  1. Instale NextPDF Core y el paquete Enterprise: composer require nextpdf/core:^3 y composer require nextpdf/enterprise.
  2. Disponga de una licencia activa de NextPDF Enterprise; resuelva el paquete con sus credenciales de licencia en Private Packagist.
  3. Instale la biblioteca compartida PKCS#11 del proveedor del token en el host (por ejemplo, un .so en Linux o una .dll en Windows) y anote su ruta absoluta, el número de ranura y las etiquetas de objeto.
  4. Cargue la extensión ext-pkcs11 de PHP. No viene incluida con el PHP estándar y debe instalarse por separado. El constructor del firmante genera un error de operación tipado cuando la extensión está ausente.

Suministre estas entradas al firmante:

  • Ruta de la biblioteca — la ruta absoluta a la biblioteca compartida PKCS#11 del proveedor.
  • Identificador de ranura — el número de ranura del token, normalmente 0.
  • PIN — el PIN del token. Trátelo como un secreto: suminístrelo desde su gestor de secretos, nunca desde el código fuente ni los registros. El firmante marca el parámetro PIN como sensible, de modo que se excluye de las trazas de pila y de la serialización.
  • Etiqueta del certificado — la etiqueta del objeto de certificado en el token.
  • Etiqueta de la clave — la etiqueta del objeto de clave privada, cuando difiere de la etiqueta del certificado.
  • Cadena — certificados intermedios opcionales en formato DER, cuando el token no los contiene.

Compruebe la disponibilidad del token antes de construir el firmante. La construcción lee el certificado del token, de modo que una ranura o etiqueta mal configurada falla pronto con un error tipado en lugar de en el momento de la firma.

  1. Confirme que el tiempo de ejecución admite PKCS#11 comprobando la disponibilidad de la extensión. No construya el firmante cuando la extensión esté ausente.
  2. Lea el PIN desde su gestor de secretos en una variable que nunca se registre.
  3. Construya el firmante HSM con la ruta de la biblioteca, la ranura, el PIN y las etiquetas. La construcción inicia sesión y lee el certificado.
  4. Pase el firmante al orquestador de firma de Core a través de HsmSignerInterface. El orquestador calcula el rango de bytes, construye los atributos firmados de CMS, entrega los datos al token y ensambla el PDF firmado.
  5. Capture el fallo más específico, registre un mensaje estructural sin el PIN y vuelva a lanzar.
examples/contracts/hsm-signer-availability.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\HsmSignerInterface;
/**
* Build a hardware-token signer only when the runtime supports it.
*
* The concrete PKCS#11 signer is resolved through the Core contract so the
* caller depends on the interface, not the Enterprise implementation type.
* The PIN arrives from a secret resolver; it is never written to source.
*
* @param callable(): bool $pkcs11Available Reports ext-pkcs11 availability.
* @param callable(): HsmSignerInterface $signerFactory Builds the configured token signer.
*
* @throws \RuntimeException When the PKCS#11 extension is not loaded.
*
* @return HsmSignerInterface The token signer, ready for the Core orchestrator.
*/
function resolveHsmSigner(callable $pkcs11Available, callable $signerFactory): HsmSignerInterface
{
if ($pkcs11Available() !== true) {
throw new \RuntimeException(
'PKCS#11 signing requires the ext-pkcs11 extension; install it before signing.',
);
}
return $signerFactory();
}

El cableado de producción —la lista exacta de argumentos del constructor y los tipos de excepción tipados— se documenta en la referencia profunda de HSM.

examples/contracts/hsm-sign-guarded.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\HsmSignerInterface;
use NextPDF\Exception\NextPdfException;
use Psr\Log\LoggerInterface;
final readonly class HsmSigningService
{
public function __construct(
private HsmSignerInterface $signer,
private LoggerInterface $logger,
) {}
/**
* Sign data on the token through the Core HSM contract.
*
* The byte range is computed by the engine, never accepted from the
* caller. The token performs the signing operation; the private key
* does not leave the device.
*
* @param string $data The bytes the orchestrator hands to the token.
* @param string $algorithm The OpenSSL-style signing algorithm identifier.
*
* @throws NextPdfException When the token operation fails.
*
* @return string The raw signature bytes returned by the token.
*/
public function sign(string $data, string $algorithm): string
{
try {
return $this->signer->sign($data, $algorithm);
} catch (NextPdfException $e) {
// Structural message only — never the PIN or key material.
$this->logger->error('HSM signing failed', ['reason' => $e->getMessage()]);
throw $e;
}
}
}

Confirme el resultado como lo haría un verificador:

  1. Vuelva a leer el certificado del firmante y la cadena en formato DER desde el firmante y confirme que coinciden con el certificado aprovisionado en el token.
  2. Abra el PDF firmado en un validador configurado con sus anclajes de confianza y confirme que la firma se informa como criptográficamente intacta. Una firma producida no es una firma verificada; la decisión de confianza corresponde al verificador y a sus anclajes de confianza, no al productor.
  3. Para una firma ECDSA, confirme que la firma incrustada está codificada en DER — el firmante convierte por usted la salida en bruto del token, de modo que un validador que rechace la forma concatenada en bruto debería aceptar aún la firma incrustada.
  4. Confirme que ningún PIN, etiqueta de token ni material de clave aparece en los registros de su aplicación.
  • La clave permanece en el token. Los datos a firmar se entregan al token; la operación de firma se ejecuta dentro del límite del token. La clave privada nunca se carga en la memoria de PHP.
  • El PIN es un secreto. Es un parámetro sensible del constructor, excluido de los registros y de la serialización. Suminístrelo desde un gestor de secretos. Una reautenticación fallida repetida puede bloquear el PIN en el token; el token, no NextPDF, aplica esa política.
  • Fallo cerrado. Un error del token o del HSM genera una excepción tipada. El firmante no produce un resultado sin firmar ni parcialmente firmado y nunca sustituye por un algoritmo más débil.
  • Robustez del algoritmo. Aprovisione claves RSA de al menos 2048 bits y curvas ECDSA de orden de al menos 224 bits, los mínimos aceptables para la generación de firma según NIST SP 800-131A Rev.2 §3.
  • La firma poscuántica es experimental y está desactivada de manera predeterminada. Existe una ruta poscuántica detrás de un indicador de aceptación explícita. Los perfiles de archivado a largo plazo de las firmas electrónicas avanzadas estándar de PDF (PAdES) aún no reconocen las suites poscuánticas, y la mayoría de los visores las rechazan en la validación. No la active para firmas PAdES de producción.

Esta página trata sobre firma criptográfica e integración con módulos de seguridad de hardware. Toda fuente normativa está parafraseada; no se reproduce ningún texto normativo. ### Límite de custodia de claves

NextPDF Enterprise se integra con un token o HSM PKCS#11. No almacena, genera ni garantiza la seguridad de la clave de firma. La seguridad de la clave depende del token o HSM, del despliegue y del operador — no de NextPDF Enterprise por sí solo. Usted es responsable del aprovisionamiento del token, del manejo del PIN, de la configuración de la ranura y de la protección de red de un HSM conectado en red.

  • Extensión ausente. Construir el firmante PKCS#11 genera una excepción de operación tipada cuando ext-pkcs11 no está cargada. Compruebe primero la disponibilidad.
  • Certificado o clave no encontrado por etiqueta. La construcción o la firma genera una excepción tipada que nombra el objeto ausente. Confirme la etiqueta y la ranura.
  • Ya con sesión iniciada. Cuando varias instancias del firmante comparten un módulo en caché para la misma ranura, el firmante cierra la sesión y la vuelve a iniciar para proporcionar una verificación fresca del PIN — requerido por los tokens de verificación de identidad personal con una política de «PIN cada vez».
  • Algoritmo no admitido. Solicitar un algoritmo que el firmante no asigna genera un error de argumento en lugar de firmar con un sustituto.
  • HSM de red no alcanzable. Un error de red o de dispositivo genera una excepción tipada; el firmante nunca produce silenciosamente un documento sin firmar.

Esta página documenta únicamente el comportamiento observable externamente y la superficie de 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.