Ir al contenido

Seguridad: cifrado, política criptográfica y superficie de firma

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.

Ventana de terminal
composer require nextpdf/core:^3

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.

TipoClaseMiembros claveEstabilidadDesde
Document::setEncryption()método (área HasSecurity)userPassword, ownerPassword, permissionsestable1.0.0
Document::useAesGcm()método (área HasSecurity)?bool $enabled — ISO/TS 32003 V=6/R=7 opcionalestable2.18.0
Aes256Encryptorclaseencrypt(), decrypt(), buildEncryptionDictionary(), verifyUserPassword(), verifyOwnerPassword(), validatePerms()estable1.0.0
Aes256GcmEncryptorclaseencrypt(), decrypt(), encryptStream(), assertWithinSafetyBound(), invocationCount()estable2.18.0
KeyMaterialclase final de solo lecturagenerate(), exposeKey(), fingerprint()estable2.18.0
CryptoPolicyInterfaceinterfazisHashAlgorithmAllowed(), isSignatureAlgorithmAllowed(), isEncryptionAlgorithmAllowed(), isKeyStrengthAllowed(), getPreferredHashAlgorithm(), getName()estable1.9.0
Config::withCryptoPolicy()métodoCryptoPolicyInterface $policyestable1.9.0
CryptoCapabilitiesclase finalhasAesGcm(), detectFipsMode(), assertFipsAvailableForProfile()estable2.0.0
examples/22-protection.php
<?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.

examples/security/policy-gated-encryption.php
<?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.

  • Llamar a setEncryption() antes de addPage(). 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 Encrypt en todas las variantes de PDF/A, de modo que setEncryption() y useAesGcm() 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.
  • CryptoPolicyInterface permite 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.

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.

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.

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.

AmenazaMitigación en CoreFrontera residual
Degradación de algoritmos / sustitución por cifrador débilCompuerta 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 registrosKeyMaterial redacta; #[\SensitiveParameter] en las contraseñasUn llamador que pasa exposeKey() a un registrador lo anula
Manipulación del texto cifradoVerificación de etiqueta GCM en la ruta opcionalLa 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 permisosNinguna: los indicadores son orientativosUn lector no conforme ignora los indicadores
Fuerza bruta sobre una contraseña débilSASLprep más la derivación iterada de claves eleva el costoUna contraseña débil sigue siendo el riesgo dominante

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.

AfirmaciónEstándarCláusulaEvidencia
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.1C_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.

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.