Seguridad: cifrado, política criptográfica y superficie de firma
De un vistazo
Sección titulada «De un vistazo»El módulo de seguridad de Core aplica cifrado AES-256 a documentos, controla cada elección de algoritmo mediante un contrato de política criptográfica y expone los puntos de integración que un despliegue usa para conectar un servicio de gestión de claves. La protección efectiva de un documento depende del manejo de claves, la robustez de la contraseña, el lector que lo consume y el entorno de despliegue; esta página explicita cada límite.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Visión conceptual general
Sección titulada «Visión conceptual general»El módulo de seguridad agrupa tres superficies. La primera es el cifrado: el punto de entrada setEncryption() del documento configura el gestor de seguridad estándar AES-256. La segunda es la compuerta de política criptográfica: CryptoPolicyInterface decide qué hash, firma, cifrador y robustez de clave permite un despliegue. La tercera es la superficie de firma, que esta página menciona pero no documenta; consultar Firma.
El cifrado usa AES-256 tal como se define en ISO 32000-2:2020 §7.6. La ruta predeterminada es el gestor de seguridad estándar V=5 / R=6 con el filtro de cifrado AESV3. La clave del archivo tiene una longitud de 32 bytes (256 bits), lo que coincide con FIPS 197. Una ruta opcional añade cifrado autenticado AES-256-GCM V=6 / R=7 de ISO/TS 32003:2023. La página detallada documenta ambos: Cifrado.
La compuerta de política criptográfica es un predicado que deniega o permite. Core consulta CryptoPolicyInterface antes de cualquier paso de firma, cifrado o hash. Si no se define una política, Core permite todos los algoritmos: un valor predeterminado abierto adecuado para desarrollo, no para una postura de producción. Un despliegue regulado debe definir una política explícita. Contracts / Security Policy documenta la superficie del contrato.
Los indicadores de permisos son el punto en el que más suele exagerarse el alcance, por lo que esta página lo explicita. La máscara de bits de permisos viaja en la entrada cifrada /Perms y en el valor /P. Se espera que un lector conforme respete las restricciones. Los indicadores no se hacen cumplir criptográficamente. Un procesador que ignore los bits aún puede leer, copiar o modificar el contenido una vez que tiene la clave de descifrado. Debe exponerse este límite ante cualquier parte que dependa de los indicadores de permisos.
La gestión de claves y la integración PKCS#11 son puntos de contrato. Core incluye una ruta de clave local. El objeto de valor KeyMaterial envuelve una clave de 256 bits con longitud verificada y evita la divulgación a través de sus representaciones de cadena y de depuración. La ruta de custodia de claves HSM y PKCS#11 es una capacidad Enterprise y se controla mediante los mismos contratos; esta página identifica el punto de integración, pero no documenta la implementación Enterprise.
Superficie de API
Sección titulada «Superficie de API»| Tipo | Clase | Miembros clave | Estabilidad | Desde |
|---|---|---|---|---|
Document::setEncryption() | método (área HasSecurity) | userPassword, ownerPassword, permissions | estable | 1.0.0 |
Document::useAesGcm() | método (área HasSecurity) | ?bool $enabled — ISO/TS 32003 V=6/R=7 opcional | estable | 2.18.0 |
Aes256Encryptor | clase | encrypt(), decrypt(), buildEncryptionDictionary(), verifyUserPassword(), verifyOwnerPassword(), validatePerms() | estable | 1.0.0 |
Aes256GcmEncryptor | clase | encrypt(), decrypt(), encryptStream(), assertWithinSafetyBound(), invocationCount() | estable | 2.18.0 |
KeyMaterial | clase final de solo lectura | generate(), exposeKey(), fingerprint() | estable | 2.18.0 |
CryptoPolicyInterface | interfaz | isHashAlgorithmAllowed(), isSignatureAlgorithmAllowed(), isEncryptionAlgorithmAllowed(), isKeyStrengthAllowed(), getPreferredHashAlgorithm(), getName() | estable | 1.9.0 |
Config::withCryptoPolicy() | método | CryptoPolicyInterface $policy | estable | 1.9.0 |
CryptoCapabilities | clase final | hasAesGcm(), detectFipsMode(), assertFipsAvailableForProfile() | estable | 2.0.0 |
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Encrypted Document — Restricted Permissions');
// Call setEncryption() BEFORE addPage().// Permission bit 3 (value 4) = printing allowed; all other operations denied.$doc->setEncryption( userPassword: 'demo', ownerPassword: 'admin', permissions: 4,);
$doc->addPage();$doc->setFont('helvetica', 'B', 20);$doc->cell(0, 14, 'Encrypted PDF Document', newLine: true);
$doc->save(__DIR__ . '/output/22-protection.pdf');La contraseña de usuario abre el documento. La contraseña de propietario concede acceso completo. Los indicadores de permisos solo restringen el comportamiento de un lector conforme.
Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\CryptoPolicyInterface;use NextPDF\Core\Document;use Psr\Log\LoggerInterface;
final readonly class PolicyGatedEncryption{ public function __construct( private CryptoPolicyInterface $cryptoPolicy, private LoggerInterface $logger, ) {}
/** * Encrypt only when the active policy permits AES-256-CBC. * * @param non-empty-string $userPassword Opens the document. * @param non-empty-string $ownerPassword Grants full access. */ public function protect( Document $doc, string $userPassword, string $ownerPassword, int $permissions, ): void { if (!$this->cryptoPolicy->isEncryptionAlgorithmAllowed('aes-256-cbc')) { $this->logger->error('Encryption refused by crypto policy', [ 'policy' => $this->cryptoPolicy->getName(), ]);
throw new \RuntimeException('AES-256-CBC denied by the active crypto policy.'); }
$doc->setEncryption($userPassword, $ownerPassword, $permissions);
$this->logger->info('Document encrypted', [ 'policy' => $this->cryptoPolicy->getName(), 'algorithm' => 'aes-256-cbc', ]); }}La compuerta consulta la política antes de cifrar, registra el nombre de la política para la trazabilidad de auditoría y rechaza la operación con una excepción específica cuando la política deniega el cifrador.
Casos límite y trampas
Sección titulada «Casos límite y trampas»- Llamar a
setEncryption()antes deaddPage(). Una llamada posterior no cifra retroactivamente el contenido que el escritor ya ha emitido. - El modo PDF/A y el cifrado son mutuamente excluyentes. ISO 19005 prohíbe la clave de tráiler
Encrypten todas las variantes de PDF/A, de modo quesetEncryption()yuseAesGcm()lanzan una excepción cuando un gestor de PDF/A está activo. - Dentro de
setEncryption(), una contraseña de propietario vacía recae en la contraseña de usuario. Un documento con una sola contraseña compartida concede a quien posee la contraseña de usuario acceso de nivel de propietario. CryptoPolicyInterfacepermite todos los algoritmos cuando no se inyecta ninguna política. Tratar el valor predeterminado abierto como una comodidad de desarrollo y definir una política explícita en cualquier despliegue regulado.- Los indicadores de permisos son orientativos para el lector. No deben describirse como un control de acceso que un procesador hostil no pueda eludir.
Rendimiento
Sección titulada «Rendimiento»setEncryption() ejecuta una rutina iterada de derivación de claves (Algoritmo 2.B, revisión 6) al construir el documento. El costo está acotado y es constante por documento, no proporcional al número de páginas. El cifrado por objeto es una operación AES por flujo o cadena. La ruta opcional AES-256-GCM añade una sobrecarga de 28 bytes por objeto (IV de 12 bytes más etiqueta de 16 bytes) y transmite el contenido de gran tamaño en fragmentos de 16 MiB. Así, la pasada de transmisión se mantiene por debajo del pico documentado de 64 MB. El performance_budget de 1500 ms de reloj y pico de 64 MB está dominado por el renderizado del documento, no por el paso de cifrado.
Notas de seguridad
Sección titulada «Notas de seguridad»El modelo de amenazas es explícito. La degradación de algoritmos se mitiga mediante la compuerta de política criptográfica, que rechaza cifradores débiles, hashes débiles y claves cortas antes de cualquier operación. El motor no sustituye silenciosamente por una primitiva más débil cuando la solicitada no está disponible: lanza una excepción para que el operador pueda actuar. La divulgación de claves a través del registro se mitiga mediante KeyMaterial, cuyas formas de cadena y de depuración ocultan los bytes y exponen solo una huella no reversible. La manipulación del texto cifrado se detecta únicamente en la ruta opcional AES-256-GCM, donde se verifica la etiqueta de autenticación y una discrepancia lanza una excepción en lugar de devolver texto plano. La ruta predeterminada AES-256-CBC es solo de confidencialidad y no detecta por sí misma la modificación. La reutilización de IV en la ruta GCM se mitiga mediante un contador monótono más un conjunto de colisiones como defensa en profundidad, en consonancia con el requisito de IV único de NIST SP 800-38D §8.
El límite es igualmente explícito. El cifrado AES-256 se aplica tal como se define en ISO 32000-2:2020 §7.6. La protección efectiva depende de la robustez de la contraseña, la gestión de claves, el entorno de despliegue y el lector que consuma el documento. Los lectores conformes respetan los indicadores de permisos, pero estos no se hacen cumplir criptográficamente. La sonda de modo FIPS informa si la compilación de OpenSSL del host cargó un proveedor FIPS. La biblioteca opera en un modo compatible con FIPS cuando el host proporciona un módulo validado, y ella misma no certifica ningún módulo. NIST SP 800-57 Parte 1 §4 enmarca la vida útil de la clave y el criptoperíodo como una responsabilidad del despliegue. Core expone los controles, pero cada despliegue define la política de rotación.
Residencia de datos y mitigaciones de PII
Sección titulada «Residencia de datos y mitigaciones de PII»La superficie de cifrado no transmite los bytes del documento fuera del host. La derivación de claves, el cifrado y el descifrado se ejecutan dentro del proceso. La ruta opcional GCM indexa un conjunto de colisiones de IV en memoria mediante una huella de clave no reversible, no con los bytes de la clave. El módulo de seguridad no escribe en disco ninguna contraseña ni valor de clave. Un despliegue que enruta las claves a través de un servicio externo de gestión de claves es responsable de la residencia de ese servicio.
Telemetría segura y depuración de registros
Sección titulada «Telemetría segura y depuración de registros»KeyMaterial::__toString() y __debugInfo() devuelven un marcador de posición redactado, de modo que un registro accidental de un objeto de clave produce una huella, no los bytes de la clave. Las contraseñas pasadas a setEncryption() llevan el atributo #[\SensitiveParameter], que las redacta de una traza de pila. Los identificadores aptos para auditoría de una operación criptográfica son el nombre de la política de CryptoPolicyInterface::getName() y la huella de clave de 8 caracteres: registrar esos valores, nunca la clave ni la contraseña.
Modelo de amenazas
Sección titulada «Modelo de amenazas»| Amenaza | Mitigación en Core | Frontera residual |
|---|---|---|
| Degradación de algoritmos / sustitución por cifrador débil | Compuerta de política criptográfica; sin degradación silenciosa (lanza UnsupportedAlgorithmException) | Solo es efectiva cuando se inyecta una política |
| Divulgación de claves a través de registros | KeyMaterial redacta; #[\SensitiveParameter] en las contraseñas | Un llamador que pasa exposeKey() a un registrador lo anula |
| Manipulación del texto cifrado | Verificación de etiqueta GCM en la ruta opcional | La ruta predeterminada CBC es solo de confidencialidad |
| Reutilización de IV (GCM) | Contador monótono más conjunto de colisiones; el desbordamiento rechaza la operación | — |
| Elusión de los indicadores de permisos | Ninguna: los indicadores son orientativos | Un lector no conforme ignora los indicadores |
| Fuerza bruta sobre una contraseña débil | SASLprep más la derivación iterada de claves eleva el costo | Una contraseña débil sigue siendo el riesgo dominante |
Comportamiento en modo FIPS
Sección titulada «Comportamiento en modo FIPS»Core no es un módulo criptográfico validado por FIPS ni está certificado por FIPS. CryptoCapabilities::detectFipsMode() es una sonda de tiempo de ejecución de mejor esfuerzo: lee una anulación del operador, luego la lista de proveedores de OpenSSL, después la llamada heredada de modo FIPS, e informa si está activo, ausente o indeterminado. assertFipsAvailableForProfile() falla de forma segura cuando se selecciona un perfil FIPS en un host que no demuestra un proveedor FIPS. La biblioteca opera en un modo compatible con FIPS cuando se configura contra una compilación de OpenSSL del host que cargó un proveedor validado por FIPS. Una postura FIPS validada y certificada corresponde a Enterprise; consultar la documentación Enterprise.
Conformidad
Sección titulada «Conformidad»| Afirmación | Estándar | Cláusula | Evidencia |
|---|---|---|---|
| La ruta GCM mantiene cada IV único por invocación, en consonancia con el requisito de unicidad del estándar. | NIST SP 800-38D | §8.2.1 | |
| La vida útil de la clave y el criptoperíodo son una responsabilidad del despliegue para la que Core expone controles. | NIST SP 800-57 Parte 1 Rev. 5 | §4 | |
| La clave del archivo AES es de 256 bits, lo que coincide con la longitud de clave del estándar. | FIPS 197 | §4.2.1 | |
| La generación de claves residentes en el token es el punto de integración para un almacén de claves externo. | OASIS PKCS#11 v3.1 | C_GenerateKey |
ISO 32000-2:2020 §7.6 es la base normativa del gestor de seguridad estándar. Su texto tiene licencia restringida y aquí se parafrasea, nunca se cita; la cláusula se cita por número. Todas las afirmaciones anteriores están parafraseadas del estándar citado.
Contexto comercial
Sección titulada «Contexto comercial»Core define y fija el contrato de política criptográfica, incluye la ruta de cifrado AES-256 y proporciona una superficie local de claves. La edición Enterprise suministra una ruta de custodia de claves HSM/PKCS#11 y un perfil de política criptográfica en modo FIPS mediante la misma CryptoPolicyInterface. La superficie del contrato es idéntica en todas las ediciones; la diferencia es la implementación de la política y el backend de custodia de claves que un despliegue inyecta.
Véase también
Sección titulada «Véase también»- Security / Encryption — la referencia detallada de AES-256 y AES-256-GCM.
- Contracts / Security Policy — los contratos de política criptográfica y de política de recursos.
- Security / Signing — firmas PAdES, CMS y marcas de tiempo.
- Audit — registro de auditoría del nombre de la política y de las operaciones.
- Conformance — interacción de PDF/A con el cifrado.