Ir al contenido
getnextpdf.com

Enterprise edición

Seguridad — Referencia detallada (HSM, PKCS#11, modo FIPS)

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.

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.

Ventana de terminal
composer require nextpdf/enterprise:^3

Los 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ímboloParámetrosComportamiento predeterminadoDevuelveLanza o falla conNotas
Pkcs11Signer::__construct()string $libraryPath, int $slotId, string $pin, string $certLabel, ?string $keyLabel = null, array $chainDer = [], bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = nullAbre la biblioteca del proveedor, inicia sesión en la ranura y carga los metadatos del certificado y del algoritmo de claveHsmOperationException cuando falta ext-pkcs11 o el acceso al token fallaEl PIN y las etiquetas son #[SensitiveParameter]; se almacena en caché un identificador de módulo por ruta de biblioteca y por proceso
Pkcs11Signer::isAvailable()NingunoIndica si ext-pkcs11 está cargadoboolNingunoEstá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 DERstring con los bytes de firma en brutoHsmOperationException (clave no encontrada, fallo del token); InvalidArgumentException (algoritmo no mapeado); FipsViolationException / FipsModuleErrorStateException antes de firmar cuando hay un enforcer conectadoConjunto cerrado de algoritmos; véase Contrato de comportamiento
Pkcs11Signer::signPqs()string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = trueRechazado salvo que se haya establecido $enablePostQuantum; despacha el mecanismo poscuántico provisional de PKCS#11string con los bytes de firma en brutoHsmOperationException (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 Pkcs11SignerNingunoResultados de construcción de solo lecturabool / string / array<string>NingunoisPostQuantumEnabled, 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 = nullVerifica proc_open, sondea el binario, resuelve el backend y carga los certificadosHsmOperationException (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 0600string con los bytes de firma en brutoHsmOperationException (tiempo de espera agotado, PIN rechazado, clave no encontrada, salida vacía); InvalidArgumentException (algoritmo no mapeado); excepciones de la puerta FIPS antes de firmarEl subproceso se termina tras $timeoutSeconds; stderr se redacta
Superficie de descriptores de acceso de OpenSslCliSignerNingunoResultados de construcción de solo lecturastring / array<string> / OpenSslCliBackendNingunogetCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm, getCertificatePem, getResolvedBackend, getOpensslVersion
OpenSslCliBackendEnumeración: Provider, Engine, AutoNingunoSelección de backend para el firmante por CLI
Pkcs11PqsAlgorithmEnumeración de conjuntos de parámetros ML-DSA y SLH-DSANingunoAuxiliares: isMlDsa, isSlhDsa, mechanismId, parameterSetId, signatureLength, nistCategory
PqsCapabilityStatus::current()NingunoConstruye la postura poscuántica honesta del procesoPqsCapabilityStatusNingunoTodos los booleanos de declaración de conformidad están fijados a false en el código; ningún indicador puede activar uno
HsmSignerProviderAdapterHsmSignerInterface $hsm, string $providerId, SignatureAlgorithm $algorithm = SignatureAlgorithm::Pkcs1v15Expone una implementación concreta de HSM como un SignerProviderInterface unificadoSegún la SPIKeyManagementException (versión de clave no nula); SignatureFailedException (fallo del controlador, firma vacía)Ids de proveedor: pkcs11-{module-id}, openssl-cli
HsmOperationExceptionFallo tipado para cada ruta de firma HSMExtiende el NextPdfException de Core
FipsCryptoPolicy::strict() / ::standard()?FipsSelfTest $selfTest = nullPerfiles predefinidos de fábrica; strict es el perfil FIPS 140-3 y standard añade AES-128-CBCFipsCryptoPolicyNingunoListas de permitidos inmutables; véase Comportamiento en modo FIPS
Superficie de predicados de FipsCryptoPolicyentradas string / intComprobaciones de pertenencia a la lista de permitidosbool / stringNingunoisHashAlgorithmAllowed, isSignatureAlgorithmAllowed, isEncryptionAlgorithmAllowed, isKeyStrengthAllowed, getPreferredHashAlgorithm, getName
FipsCryptoPolicy::assertPreOperational()NingunoEjecuta (o repite) la autoprueba de arranquevoidFipsModuleErrorStateExceptionImpulsado por el punto de aplicación de Core en la primera operación criptográfica
FipsModeGuard::__construct()CryptoPolicyInterface $policy, ?FipsBootGuard $bootGuard = null, ?FipsAuditLogger $auditLogger = nullEnvuelve una política con límites de estilo assertNingunoSin un guardián de arranque, la puerta de autoprueba no existe (solo política)
Superficie de aserciones de FipsModeGuardentradas string / intPrimero el catálogo de denegación, luego la lista de permitidos; registro de auditoría antes de cualquier lanzamientovoidFipsViolationException; FipsModuleErrorStateException (con guardián de arranque conectado)assertHashAllowed, assertSignatureAlgorithmAllowed, assertEncryptionAllowed, assertKeyStrengthAllowed, además de getPolicy
FipsBootGuard::report() / ::rerun()NingunoEjecuta la batería de autopruebas (en caché / forzada)FipsSelfTestReportNingunoUn informe ERROR bloquea el proceso; una nueva ejecución correcta nunca libera el bloqueo
FipsBootGuard::assertOperational()NingunoVerifica que el módulo está OPERATIONALvoidFipsModuleErrorStateExceptionPersistente: un ERROR bloqueado a nivel de proceso rechaza incluso una instancia limpia
FipsBootGuard::status()NingunoInforma del estado en cachéFipsSelfTestStatusNingunoPRE_OPERATIONAL, OPERATIONAL o ERROR
FipsSelfTest::run()NingunoEjecuta la batería completa de pruebas de respuesta conocida; nunca se cortocircuitaFipsSelfTestReportNingunoEl constructor acepta proveedores inyectables de hash y de bytes aleatorios para pruebas deterministas
FipsSelfTestReport / FipsSelfTestResult / FipsSelfTestStatusObjetos de valor del informe y enumeración de estadoFipsSelfTestReport::assertOperational() lanza FipsModuleErrorStateExceptionresults siempre enumera cada resultado como evidencia de auditoría
FipsSignatureEnforcer::assertSignatureGenerationAllowed()string $algorithm, string $certificatePemResuelve el OID de firma y la fortaleza de la clave, y luego delega en el guardiánvoidFipsViolationException (no permitido o no clasificable, con cierre seguro)El punto de control que ambos firmantes invocan al inicio de sign() en modo FIPS
FipsAuditLoggerCryptoPolicyInterface $policy, LoggerInterface $loggerEmite registros ALLOW (INFO) / DENY (WARNING) por cada decisiónbool por cada llamada de registroNingunologHashOperation, logSignatureOperation, logEncryptionOperation, logKeyStrengthCheck
FipsTransitioningAlgorithmsentradas string / intCatálogo de denegación estático de NIST SP 800-131Abool / arrayNingunoLa capa de denegación explícita bajo cada límite de guardián
FipsBootstrap::boot() / ::lazy()?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = nullCompone 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ímiteFipsModeGuardboot(): FipsModuleErrorStateException ante una prueba fallidaUsa la política strict de forma predeterminada
FipsBootstrap::signatureEnforcer()?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = nullArranca el módulo y devuelve la puerta de tiempo de generación para los firmantesFipsSignatureEnforcerFipsModuleErrorStateExceptionPasar el resultado al parámetro $fipsEnforcer de un firmante
FipsBootstrap::selfTestReport()?FipsSelfTest $selfTest = nullEjecuta la batería bajo demanda y la resumearray{status, operational, failed}NingunoPensado para endpoints de salud y el subcomando de CLI
FipsViolationException / FipsModuleErrorStateExceptionFallos FIPS tipadosExponen 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(): bool
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
public function signPqs(string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = true): string
public 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'): string
public static function strict(?FipsSelfTest $selfTest = null): self
public static function standard(?FipsSelfTest $selfTest = null): self
public function assertPreOperational(): void
public function __construct(private CryptoPolicyInterface $policy, private ?FipsBootGuard $bootGuard = null, private ?FipsAuditLogger $auditLogger = null)
public function assertHashAllowed(string $algorithm): void
public function assertSignatureAlgorithmAllowed(string $oid): void
public function assertEncryptionAllowed(string $algorithm): void
public function assertKeyStrengthAllowed(string $keyType, int $bitLength): void
public function getPolicy(): CryptoPolicyInterface
public static function boot(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuard
public static function lazy(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuard
public static function signatureEnforcer(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null): FipsSignatureEnforcer
public static function selfTestReport(?FipsSelfTest $selfTest = null): array
  • Resolución de contratos. Ambos firmantes implementan el HsmSignerInterface de Core; la política implementa el CryptoPolicyInterface de 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. Pkcs11Signer delega la operación en el token; OpenSslCliSigner pasa 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 (Pkcs11Signer también acepta ecdsa-raw). Cualquier otro identificador lanza InvalidArgumentException; 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 forma ECDSA-Sig-Value codificada 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. FipsSignatureEnforcer gobierna 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.
  • Construir Pkcs11Signer sin ext-pkcs11 lanza HsmOperationException de 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 HsmOperationException nombrando la clase de objeto que falta.
  • OpenSslCliSigner rechaza en la construcción un $keyUri que contenga pin-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 FipsModuleErrorStateException con 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 lanza InvalidArgumentException (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.

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.

AfirmaciónEstándarCláusula
Semántica de la operación de firma en el token, la sesión y el inicio de sesión del usuarioPKCS#11 v3.1§5 (sign)
La longitud de la sal PSS es igual a la longitud del resumenPKCS#11 v3.1§5 (PSS sLen)
Generación de firmas ECDSA; emparejamiento de curva y hashFIPS 186-5§6.3.2; §6.1.1
Longitud mínima de clave RSA y estado de transición de la generación de firmasNIST SP 800-131A Rev.2§3
Categoría de autoprueba, documentación, activación condicional y conjunto disjuntoISO/IEC 19790:2025§7.10, §7.10.2, §7.10.3, §7.10.3.p3
Unicidad del vector de inicialización de AES-GCMNIST SP 800-38D§5
Protección de la clave y responsabilidades de custodiaNIST SP 800-57 Part 1 Rev.5§5.5.2
Cadena de contexto de firma poscuántica limitada a 255 bytesFIPS 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.

  • 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 $fipsEnforcer de los firmantes. Las implementaciones no FIPS pasan null y el comportamiento no cambia.
  • El subcomando fips:self-test de bin/nextpdf-enterprise ejecuta 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 @internal y 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.

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.