Enterprise edición
Seguridad — Referencia detallada (HSM, PKCS#11, modo FIPS)
De un vistazo
Sección titulada «De un vistazo»Esta página es la referencia detallada combinada de la superficie de seguridad de NextPDF Enterprise. Abarca la firma con token hardware sobre PKCS#11, la firma en subproceso mediante la interfaz de línea de comandos (CLI) de OpenSSL, los perfiles predefinidos de política criptográfica FIPS, el guardián FIPS en tiempo de ejecución y el guardián de autoprueba de arranque. Existen dos complementos específicos: HSM — Referencia detallada para el detalle del firmante y FIPS 140 — Referencia detallada para el detalle del módulo FIPS. La ruta de firma poscuántica es una vista previa sin declaración de conformidad. NextPDF no posee ninguna certificación ni la otorga; el soporte no equivale a conformidad y la conformidad no equivale a certificación.
Disponibilidad y licencias
Sección titulada «Disponibilidad y licencias»Esta funcionalidad se distribuye en NextPDF Enterprise (nextpdf/enterprise) y se activa con un sobre de licencia de nivel Enterprise. Una implementación sin ese derecho no carga las clases de la funcionalidad. Comparar ediciones y obtener una licencia.
Superficie de API pública
Sección titulada «Superficie de API pública»composer require nextpdf/enterprise:^3Los tipos de firma residen en NextPDF\Enterprise\Security\Signature\Hsm; los tipos FIPS residen en NextPDF\Enterprise\Security\Fips; la raíz de composición reside en NextPDF\Enterprise\Bootstrap. Ambos firmantes implementan el contrato NextPDF\Contracts\HsmSignerInterface de Core. La política implementa los contratos NextPDF\Contracts\CryptoPolicyInterface y NextPDF\Contracts\PreOperationalSelfTestInterface de Core.
| Símbolo | Parámetros | Comportamiento predeterminado | Devuelve | Lanza o falla con | Notas |
|---|---|---|---|---|---|
Pkcs11Signer::__construct() | string $libraryPath, int $slotId, string $pin, string $certLabel, ?string $keyLabel = null, array $chainDer = [], bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = null | Abre la biblioteca del proveedor, inicia sesión en la ranura y carga los metadatos del certificado y del algoritmo de clave | — | HsmOperationException cuando falta ext-pkcs11 o el acceso al token falla | El PIN y las etiquetas son #[SensitiveParameter]; se almacena en caché un identificador de módulo por ruta de biblioteca y por proceso |
Pkcs11Signer::isAvailable() | Ninguno | Indica si ext-pkcs11 está cargado | bool | Ninguno | Estático; comprobar antes de la construcción |
Pkcs11Signer::sign() | string $data, string $algorithm = 'sha256WithRSAEncryption' | Firma en el token; la salida ECDSA en bruto se convierte a ECDSA-Sig-Value DER | string con los bytes de firma en bruto | HsmOperationException (clave no encontrada, fallo del token); InvalidArgumentException (algoritmo no mapeado); FipsViolationException / FipsModuleErrorStateException antes de firmar cuando hay un enforcer conectado | Conjunto cerrado de algoritmos; véase Contrato de comportamiento |
Pkcs11Signer::signPqs() | string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = true | Rechazado salvo que se haya establecido $enablePostQuantum; despacha el mecanismo poscuántico provisional de PKCS#11 | string con los bytes de firma en bruto | HsmOperationException (deshabilitado, fallo del token, longitud de firma no coincidente); InvalidArgumentException (contexto de más de 255 bytes) | Vista previa; sin declaración de conformidad |
Superficie de descriptores de acceso de Pkcs11Signer | Ninguno | Resultados de construcción de solo lectura | bool / string / array<string> | Ninguno | isPostQuantumEnabled, getCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm |
OpenSslCliSigner::__construct() | string $keyUri, string $certPath, string $pin, array $extraCertPaths = [], OpenSslCliBackend $backend = OpenSslCliBackend::Auto, string $opensslBinary = 'openssl', int $timeoutSeconds = 30, ?string $modulePath = null, ?string $configPath = null, bool $legacyPinDelivery = false, ?FipsSignatureEnforcer $fipsEnforcer = null | Verifica proc_open, sondea el binario, resuelve el backend y carga los certificados | — | HsmOperationException (proc_open deshabilitado, falta el archivo de módulo/configuración/certificado, sin backend); InvalidArgumentException (pin-value dentro de $keyUri) | Auto prefiere el proveedor de OpenSSL 3.x y luego el motor |
OpenSslCliSigner::sign() | string $data, string $algorithm = 'sha256WithRSAEncryption' | Firma en un subproceso openssl; el PIN viaja de forma predeterminada por un archivo de origen de PIN efímero con permisos 0600 | string con los bytes de firma en bruto | HsmOperationException (tiempo de espera agotado, PIN rechazado, clave no encontrada, salida vacía); InvalidArgumentException (algoritmo no mapeado); excepciones de la puerta FIPS antes de firmar | El subproceso se termina tras $timeoutSeconds; stderr se redacta |
Superficie de descriptores de acceso de OpenSslCliSigner | Ninguno | Resultados de construcción de solo lectura | string / array<string> / OpenSslCliBackend | Ninguno | getCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm, getCertificatePem, getResolvedBackend, getOpensslVersion |
OpenSslCliBackend | — | Enumeración: Provider, Engine, Auto | — | Ninguno | Selección de backend para el firmante por CLI |
Pkcs11PqsAlgorithm | — | Enumeración de conjuntos de parámetros ML-DSA y SLH-DSA | — | Ninguno | Auxiliares: isMlDsa, isSlhDsa, mechanismId, parameterSetId, signatureLength, nistCategory |
PqsCapabilityStatus::current() | Ninguno | Construye la postura poscuántica honesta del proceso | PqsCapabilityStatus | Ninguno | Todos los booleanos de declaración de conformidad están fijados a false en el código; ningún indicador puede activar uno |
HsmSignerProviderAdapter | HsmSignerInterface $hsm, string $providerId, SignatureAlgorithm $algorithm = SignatureAlgorithm::Pkcs1v15 | Expone una implementación concreta de HSM como un SignerProviderInterface unificado | Según la SPI | KeyManagementException (versión de clave no nula); SignatureFailedException (fallo del controlador, firma vacía) | Ids de proveedor: pkcs11-{module-id}, openssl-cli |
HsmOperationException | — | Fallo tipado para cada ruta de firma HSM | — | — | Extiende el NextPdfException de Core |
FipsCryptoPolicy::strict() / ::standard() | ?FipsSelfTest $selfTest = null | Perfiles predefinidos de fábrica; strict es el perfil FIPS 140-3 y standard añade AES-128-CBC | FipsCryptoPolicy | Ninguno | Listas de permitidos inmutables; véase Comportamiento en modo FIPS |
Superficie de predicados de FipsCryptoPolicy | entradas string / int | Comprobaciones de pertenencia a la lista de permitidos | bool / string | Ninguno | isHashAlgorithmAllowed, isSignatureAlgorithmAllowed, isEncryptionAlgorithmAllowed, isKeyStrengthAllowed, getPreferredHashAlgorithm, getName |
FipsCryptoPolicy::assertPreOperational() | Ninguno | Ejecuta (o repite) la autoprueba de arranque | void | FipsModuleErrorStateException | Impulsado por el punto de aplicación de Core en la primera operación criptográfica |
FipsModeGuard::__construct() | CryptoPolicyInterface $policy, ?FipsBootGuard $bootGuard = null, ?FipsAuditLogger $auditLogger = null | Envuelve una política con límites de estilo assert | — | Ninguno | Sin un guardián de arranque, la puerta de autoprueba no existe (solo política) |
Superficie de aserciones de FipsModeGuard | entradas string / int | Primero el catálogo de denegación, luego la lista de permitidos; registro de auditoría antes de cualquier lanzamiento | void | FipsViolationException; FipsModuleErrorStateException (con guardián de arranque conectado) | assertHashAllowed, assertSignatureAlgorithmAllowed, assertEncryptionAllowed, assertKeyStrengthAllowed, además de getPolicy |
FipsBootGuard::report() / ::rerun() | Ninguno | Ejecuta la batería de autopruebas (en caché / forzada) | FipsSelfTestReport | Ninguno | Un informe ERROR bloquea el proceso; una nueva ejecución correcta nunca libera el bloqueo |
FipsBootGuard::assertOperational() | Ninguno | Verifica que el módulo está OPERATIONAL | void | FipsModuleErrorStateException | Persistente: un ERROR bloqueado a nivel de proceso rechaza incluso una instancia limpia |
FipsBootGuard::status() | Ninguno | Informa del estado en caché | FipsSelfTestStatus | Ninguno | PRE_OPERATIONAL, OPERATIONAL o ERROR |
FipsSelfTest::run() | Ninguno | Ejecuta la batería completa de pruebas de respuesta conocida; nunca se cortocircuita | FipsSelfTestReport | Ninguno | El constructor acepta proveedores inyectables de hash y de bytes aleatorios para pruebas deterministas |
FipsSelfTestReport / FipsSelfTestResult / FipsSelfTestStatus | — | Objetos de valor del informe y enumeración de estado | — | FipsSelfTestReport::assertOperational() lanza FipsModuleErrorStateException | results siempre enumera cada resultado como evidencia de auditoría |
FipsSignatureEnforcer::assertSignatureGenerationAllowed() | string $algorithm, string $certificatePem | Resuelve el OID de firma y la fortaleza de la clave, y luego delega en el guardián | void | FipsViolationException (no permitido o no clasificable, con cierre seguro) | El punto de control que ambos firmantes invocan al inicio de sign() en modo FIPS |
FipsAuditLogger | CryptoPolicyInterface $policy, LoggerInterface $logger | Emite registros ALLOW (INFO) / DENY (WARNING) por cada decisión | bool por cada llamada de registro | Ninguno | logHashOperation, logSignatureOperation, logEncryptionOperation, logKeyStrengthCheck |
FipsTransitioningAlgorithms | entradas string / int | Catálogo de denegación estático de NIST SP 800-131A | bool / array | Ninguno | La capa de denegación explícita bajo cada límite de guardián |
FipsBootstrap::boot() / ::lazy() | ?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null | Compone el guardián de arranque, la política y el guardián de modo; boot() ejecuta la autoprueba de inmediato, lazy() la difiere al primer límite | FipsModeGuard | boot(): FipsModuleErrorStateException ante una prueba fallida | Usa la política strict de forma predeterminada |
FipsBootstrap::signatureEnforcer() | ?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null | Arranca el módulo y devuelve la puerta de tiempo de generación para los firmantes | FipsSignatureEnforcer | FipsModuleErrorStateException | Pasar el resultado al parámetro $fipsEnforcer de un firmante |
FipsBootstrap::selfTestReport() | ?FipsSelfTest $selfTest = null | Ejecuta la batería bajo demanda y la resume | array{status, operational, failed} | Ninguno | Pensado para endpoints de salud y el subcomando de CLI |
FipsViolationException / FipsModuleErrorStateException | — | Fallos FIPS tipados | — | — | Exponen policyName / violatingItem / reason y failedResults respectivamente |
public function __construct(private readonly string $libraryPath, private readonly int $slotId, #[SensitiveParameter] private readonly string $pin, #[SensitiveParameter] private readonly string $certLabel, #[SensitiveParameter] private readonly ?string $keyLabel = null, array $chainDer = [], private readonly bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = null)public static function isAvailable(): boolpublic function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): stringpublic function signPqs(string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = true): stringpublic function __construct(private string $keyUri, string $certPath, #[SensitiveParameter] private string $pin, array $extraCertPaths = [], private OpenSslCliBackend $backend = OpenSslCliBackend::Auto, private string $opensslBinary = 'openssl', private int $timeoutSeconds = 30, private ?string $modulePath = null, private ?string $configPath = null, private bool $legacyPinDelivery = false, private ?FipsSignatureEnforcer $fipsEnforcer = null)public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): stringpublic static function strict(?FipsSelfTest $selfTest = null): selfpublic static function standard(?FipsSelfTest $selfTest = null): selfpublic function assertPreOperational(): voidpublic function __construct(private CryptoPolicyInterface $policy, private ?FipsBootGuard $bootGuard = null, private ?FipsAuditLogger $auditLogger = null)public function assertHashAllowed(string $algorithm): voidpublic function assertSignatureAlgorithmAllowed(string $oid): voidpublic function assertEncryptionAllowed(string $algorithm): voidpublic function assertKeyStrengthAllowed(string $keyType, int $bitLength): voidpublic function getPolicy(): CryptoPolicyInterfacepublic static function boot(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuardpublic static function lazy(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuardpublic static function signatureEnforcer(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null): FipsSignatureEnforcerpublic static function selfTestReport(?FipsSelfTest $selfTest = null): arrayContrato de comportamiento
Sección titulada «Contrato de comportamiento»- Resolución de contratos. Ambos firmantes implementan el
HsmSignerInterfacede Core; la política implementa elCryptoPolicyInterfacede Core. El código que llama depende de los contratos, por lo que una actualización de edición cambia la composición, no los puntos de llamada. - Custodia de la clave. La clave privada nunca abandona el límite del token.
Pkcs11Signerdelega la operación en el token;OpenSslCliSignerpasa una referencia de clave por URI PKCS#11 al subproceso. NextPDF no almacena, genera ni garantiza la seguridad de la clave de firma. La protección de la clave es responsabilidad de custodia del operador (NIST SP 800-57 Part 1 Rev.5 §5.5.2). - Sesión e inicio de sesión. La operación de firma en el token, la sesión y el inicio de sesión del usuario siguen PKCS#11 v3.1 §5. La etiqueta del certificado y la etiqueta de la clave privada pueden diferir; el constructor acepta una etiqueta de clave separada para esos tokens.
- Conjunto cerrado de algoritmos. Los firmantes aceptan exactamente: RSA PKCS#1 v1.5 con SHA-256/384/512, RSASSA-PSS con SHA-256/384/512 y ECDSA con SHA-256/384/512 (
Pkcs11Signertambién aceptaecdsa-raw). Cualquier otro identificador lanzaInvalidArgumentException; nunca se firma un algoritmo sustituto. - Vinculación de la sal PSS. En cada variante PSS la longitud de la sal es igual a la longitud del resumen —32, 48 o 64 bytes— y los parámetros de hash y de generación de máscara coinciden con el resumen elegido (PKCS#11 v3.1 §5).
- Conversión ECDSA. Los mecanismos ECDSA del token devuelven una firma en bruto;
sign()la convierte a la formaECDSA-Sig-Valuecodificada en DER para la interoperabilidad con PDF y OpenSSL. La generación de firmas sigue FIPS 186-5 §6.3.2. - Contenido de los perfiles predefinidos. El perfil strict permite SHA-256/384/512; los OID de firma RSA y ECDSA con esos hashes; RSASSA-PSS; AES-256-CBC y AES-256-GCM; RSA de 2048 como mínimo y EC de 256. El perfil standard permite además AES-128-CBC por interoperabilidad heredada. Cualquier uso de AES-GCM exige un vector de inicialización único por clave (NIST SP 800-38D §5).
- Aplicación en dos capas. Cada límite de guardián consulta primero el catálogo de denegación explícito de NIST SP 800-131A y luego la lista de permitidos de la política. La capa de denegación produce la señal «no permitido» clara para auditoría; la lista de permitidos sigue siendo la autoridad.
- Autoprueba de arranque. La batería abarca SHA-256/384/512, HMAC-SHA-256, AES-256-CBC, AES-256-GCM, una prueba de consistencia por pares ECDSA P-256 y una comprobación de salud de bits aleatorios. La primera operación criptográfica bajo la política en la ruta de Core la ejecuta una vez por proceso, con cierre seguro. Un fallo pone el módulo en estado ERROR; los servicios criptográficos se rechazan hasta el reinicio. Esto sigue ISO/IEC 19790:2025 §7.10, §7.10.2, §7.10.3 y §7.10.3.p3.
- Estado ERROR persistente. Un ERROR observado se bloquea durante todo el proceso. Construir una política o un guardián de arranque nuevos no lo puede blanquear; una nueva ejecución correcta no lo borra. Solo un reinicio del proceso —un verdadero ciclo de encendido— restablece el estado.
- Solo puerta de generación.
FipsSignatureEnforcergobierna la producción de firmas nuevas. La validación de firmas preexistentes es uso heredado y nunca pasa por el enforcer. - Rastro de auditoría. Cuando un guardián se compone con un registrador de auditoría, cada límite emite un registro ALLOW o DENY antes de permitir o rechazar la operación. El registrador consulta la misma política que aplica el guardián, por lo que la decisión registrada no puede divergir.
Casos límite y modos de fallo
Sección titulada «Casos límite y modos de fallo»- Construir
Pkcs11Signersinext-pkcs11lanzaHsmOperationExceptionde inmediato; la extensión no se incluye en las distribuciones estándar de PHP. - Una etiqueta de certificado o de clave privada que no coincide con ningún objeto del token lanza
HsmOperationExceptionnombrando la clase de objeto que falta. OpenSslCliSignerrechaza en la construcción un$keyUrique contengapin-value, con cierre seguro; en su lugar, el PIN viaja por la ruta segura de origen de PIN.- En modo FIPS, un identificador de algoritmo que no se puede mapear a un OID de firma conocido se deniega con cierre seguro; también un certificado cuya fortaleza de clave pública no se puede determinar.
- Un tipo de clave desconocido se deniega de forma predeterminada; la política nunca recurre a un algoritmo más débil.
- Una prueba de respuesta conocida fallida lanza
FipsModuleErrorStateExceptioncon los resultados fallidos; cada límite posterior del proceso repite el fallo hasta el reinicio. - Un guardián construido sin un guardián de arranque aplica las listas de permitidos pero no proporciona puerta de autoprueba; la composición FIPS de producción proporciona una a través del bootstrap.
signPqs()se niega a ejecutarse salvo que se haya activado la opción en el constructor. Una cadena de contexto de más de 255 bytes lanzaInvalidArgumentException(FIPS 204 §5.4). Una firma devuelta cuya longitud en bytes no coincide con el conjunto de parámetros seleccionado se rechaza antes de llegar a la codificación.
Comportamiento en modo FIPS
Sección titulada «Comportamiento en modo FIPS»Permitido por FIPS en modo strict: SHA-256/384/512; RSA PKCS#1 v1.5 y RSA-PSS con esos hashes; ECDSA con esos hashes; AES-256-CBC y AES-256-GCM; RSA de al menos 2048 bits, EC de al menos 256 bits. Rechazado por FIPS en modo strict: hashes más débiles o heredados, OID de firma no aprobados, AES-128 (permitido solo en el perfil standard) y cualquier clave por debajo de la fortaleza mínima. La longitud mínima de clave RSA y el estado de transición siguen NIST SP 800-131A Rev.2 §3. El emparejamiento de curva y hash ECDSA sigue FIPS 186-5 §6.1.1. La ruta tiene cierre seguro y nunca sustituye por un algoritmo más débil.
NextPDF Enterprise no es un módulo criptográfico validado por FIPS y no realiza ninguna declaración de certificación FIPS. NextPDF Enterprise opera en un modo compatible con FIPS únicamente cuando se configura con un proveedor criptográfico validado por FIPS —por ejemplo, un proveedor de OpenSSL validado por FIPS— o un HSM validado por FIPS. La política de modo FIPS asiste al cumplimiento; no es una certificación. No existe ningún artefacto de certificación FIPS en este repositorio.
Conformidad
Sección titulada «Conformidad»| Afirmación | Estándar | Cláusula |
|---|---|---|
| Semántica de la operación de firma en el token, la sesión y el inicio de sesión del usuario | PKCS#11 v3.1 | §5 (sign) |
| La longitud de la sal PSS es igual a la longitud del resumen | PKCS#11 v3.1 | §5 (PSS sLen) |
| Generación de firmas ECDSA; emparejamiento de curva y hash | FIPS 186-5 | §6.3.2; §6.1.1 |
| Longitud mínima de clave RSA y estado de transición de la generación de firmas | NIST SP 800-131A Rev.2 | §3 |
| Categoría de autoprueba, documentación, activación condicional y conjunto disjunto | ISO/IEC 19790:2025 | §7.10, §7.10.2, §7.10.3, §7.10.3.p3 |
| Unicidad del vector de inicialización de AES-GCM | NIST SP 800-38D | §5 |
| Protección de la clave y responsabilidades de custodia | NIST SP 800-57 Part 1 Rev.5 | §5.5.2 |
| Cadena de contexto de firma poscuántica limitada a 255 bytes | FIPS 204 | §5.4 |
Todas las cláusulas están parafraseadas; no se reproduce ningún texto normativo. Estas son afirmaciones de capacidad sobre el código de NextPDF, no certificaciones. Que una firma producida se verifique es decisión del verificador según su propia configuración de confianza. La política de modo FIPS es una función de asistencia al cumplimiento, no una opinión jurídica; consultar a sus propios asesores de cumplimiento y jurídicos. Este módulo concierne a la funcionalidad criptográfica; tratarlo como sensible a la seguridad en su propia revisión.
Notas de desarrollo
Sección titulada «Notas de desarrollo»- Componer el modo FIPS a través del bootstrap:
boot()para una puerta de arranque,lazy()para diferir la batería al primer límite y la fábrica de enforcer para el parámetro$fipsEnforcerde los firmantes. Las implementaciones no FIPS pasannully el comportamiento no cambia. - El subcomando
fips:self-testdebin/nextpdf-enterpriseejecuta la batería bajo demanda y sale con código distinto de cero en estado ERROR; conectarlo a tareas de mantenimiento o a endpoints de salud solo para administradores (autopruebas bajo demanda de ISO/IEC 19790:2025). FipsBootGuard::resetProcessErrorLatchForTesting()es@internaly solo para pruebas; el código de producción nunca lo invoca, porque anularía el estado ERROR persistente.- Construir los firmantes una vez y reutilizarlos; la construcción inicia sesión y lee el certificado, y la caché de módulo por biblioteca hace que la construcción repetida contra la misma biblioteca sea segura.
- Suministrar el PIN desde un gestor de secretos. Es un
#[SensitiveParameter], nunca se registra ni se serializa; no incluirlo en la configuración. - El operador es responsable del aprovisionamiento del token, el manejo del PIN, la configuración de la ranura, la protección de red de un HSM conectado a la red y la configuración de confianza. Esta página no expone los detalles internos de la política de PIN del token ni el material de credenciales del proveedor.
- No habilitar la vista previa poscuántica para firmas AdES de producción. El catálogo de suites criptográficas de AdES todavía no reconoce las suites poscuánticas, la mayoría de los visores de PDF rechazan esas firmas y la validación de ida y vuelta en hardware no está completa. El detalle interno de los mecanismos permanece en la documentación interna del repositorio de origen y queda fuera del alcance de este manual.
Límite de publicación
Sección titulada «Límite de publicación»Esta página documenta únicamente el comportamiento observable externamente y la superficie de API pública compatible. 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 del alcance.
Véase también
Sección titulada «Véase también»- Seguridad — NextPDF Enterprise — la página de funcionalidad de esta superficie.
- Firma con módulo de seguridad hardware (PKCS#11) — pasos de instalación, configuración y verificación.
- Política criptográfica FIPS 140 — la página de funcionalidad FIPS.
- HSM — Referencia detallada — la referencia específica del firmante.
- FIPS 140 — Referencia detallada — la referencia específica del módulo FIPS.
- Seguridad — NextPDF Pro — la superficie de seguridad de nivel Pro.
- Seguridad — NextPDF Core — la línea base de seguridad de Core.