Cifratura: AES-256 (CBC) e AES-256-GCM
In breve
Sezione intitolata “In breve”Core cifra i PDF con AES-256 secondo il gestore di sicurezza Standard di ISO 32000-2:2020 §7.6. La modalità predefinita è V=5 / R=6 / AESV3 (AES-256-CBC). Come alternativa opzionale è disponibile il percorso autenticato AES-256-GCM V=6 / R=7 di ISO/TS 32003:2023. Questa pagina documenta la derivazione delle chiavi, il formato del flusso, il confine dei permessi e i limiti che un deployment deve comprendere.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/core:^3Il percorso predefinito richiede l’estensione openssl. Il percorso AES-256-GCM usa openssl o ext-sodium. Su un host senza hardware AES-NI, libsodium rifiuta GCM e Core passa all’implementazione OpenSSL, più lenta, invece di degradare l’algoritmo.
Panoramica concettuale
Sezione intitolata “Panoramica concettuale”Il gestore predefinito è il gestore di sicurezza Standard V=5 / R=6 con crypt filter AESV3. Alla chiamata di setEncryption(), Core genera una chiave di file casuale a 256 bit dalla sorgente crittografica casuale della piattaforma (random_bytes()). La lunghezza è di 32 byte, corrispondente alla lunghezza della chiave di FIPS 197. Il contenuto di ogni oggetto è cifrato con AES-256-CBC. Il vettore di inizializzazione di 16 byte viene anteposto a ciascun testo cifrato, come prescrive ISO 32000-2:2020 §7.6.4.
La derivazione della chiave segue l’Algoritmo 2.B alla revisione 6. La password viene prima normalizzata con SASLprep (RFC 4013) e poi troncata a 127 byte UTF-8 su un confine di carattere, come prescrive ISO 32000-2:2020 §7.6.4.3.3. L’hash derivato è calcolato con una routine iterata SHA-256 / SHA-384 / SHA-512 guidata da un passaggio AES-128-CBC, che aumenta il costo di un tentativo offline di indovinare la password. I salt utente, proprietario e per chiave sono generati una sola volta per ogni istanza dell’encryptor; di conseguenza, una singola istanza emette byte di dizionario deterministici, precondizione per un writer a più passaggi.
useAesGcm() attiva il percorso opzionale AES-256-GCM. Implementa il crypt filter AESV4 V=6 / R=7 di ISO/TS 32003:2023. Il cifrario è AES-256-GCM con parametri tratti da NIST SP 800-38D. Per ogni oggetto cifrato, il flusso è composto da un IV di 12 byte, dal testo cifrato e quindi da un tag di autenticazione di 16 byte. I dati autenticati aggiuntivi sono vuoti, come prescrive il profilo §5.2 di TS 32003. La decifratura verifica il tag e solleva TamperedDataException in caso di discordanza; non restituisce mai testo in chiaro per un tag non valido. Questo percorso aggiunge il rilevamento delle modifiche, che il percorso CBC predefinito da solo non fornisce.
La disciplina di unicità dell’IV nel percorso GCM segue NIST SP 800-38D §8. I 4 byte superiori dell’IV sono un campo fisso per istanza, impostato da una sorgente casuale alla costruzione. Gli 8 byte inferiori sono un contatore big-endian che viene incrementato dopo ogni IV emesso. Questo corrisponde all’approccio di costruzione deterministica del §8.2.1, con la differenza che il campo fisso è randomizzato per neutralizzare le collisioni tra documenti invece di essere enumerato. Una seconda protezione registra ogni IV emesso in un insieme di collisioni e solleva NonceReuseException se un valore si ripete. Anche il rollover del contatore solleva NonceReuseException, perché il rollover è la modalità di guasto per riuso dell’IV da cui il §8 mette in guardia.
Nel percorso GCM si applicano due limiti di lunghezza. Il limite massimo di testo in chiaro per oggetto è di 2^39 − 256 byte, il limite per invocazione derivato in NIST SP 800-38D §5.2.1.1. Un input più grande solleva un’eccezione di lunghezza con indicazioni per partizionare il contenuto tra più oggetti. Il limite di sicurezza sulle invocazioni è di 2^32 chiamate per chiave. assertWithinSafetyBound() è un controllo opzionale che solleva GcmInvocationLimitExceededException affinché il chiamante ruoti la chiave del documento prima della soglia del §8.3. NIST SP 800-57 Part 1 §4 inquadra questa decisione sulla durata della chiave come responsabilità del deployment.
I flag dei permessi sono indicativi. La bitmask viene scritta nella voce cifrata /Perms e nel valore /P, quindi recuperata in lettura con validatePerms(), che fallisce in modo sicuro su un marcatore corrotto. Un reader conforme dovrebbe rispettare i flag. I flag non sono imposti dalla crittografia: un elaboratore che possiede la chiave di decifratura e ignora i bit può leggere, copiare o modificare il contenuto. Descrivere i flag dei permessi come una convenzione del reader, non come un controllo di accesso.
Superficie API
Sezione intitolata “Superficie API”| Tipo | Genere | Membri principali | Stabilità | Da |
|---|---|---|---|---|
Aes256Encryptor | class | encrypt(), decrypt(), encryptForObject(), buildEncryptionDictionary(), verifyUserPassword(), verifyOwnerPassword(), validatePerms(), getEncryptionKey() | stable | 1.0.0 |
Aes256GcmEncryptor | class | encrypt(), decrypt(), encryptStream(), assertWithinSafetyBound(), invocationCount(), isAvailable() | stable | 2.18.0 |
KeyMaterial | final readonly class | generate(), exposeKey(), fingerprint() | stable | 2.18.0 |
EncryptedPayloadSpec | final readonly class | toDict() | stable | 2.18.0 |
CryptoCapabilities | final class | hasAesGcm(), detectFipsMode(), assertFipsAvailableForProfile() | stable | 2.0.0 |
NonceReuseException | exception | — | stable | 2.18.0 |
TamperedDataException | exception | — | stable | 2.18.0 |
DecryptionFailedException | exception | — | stable | 2.18.0 |
GcmInvocationLimitExceededException | exception | — | stable | 3.0.0 |
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
// AES-256-CBC, V=5/R=6. Call before addPage().$doc->setEncryption( userPassword: 'demo', ownerPassword: 'admin', permissions: 4, // printing only; copy/modify denied for a conforming reader);
$doc->addPage();$doc->setFont('helvetica', '', 12);$doc->cell(0, 8, 'Confidential', newLine: true);
$doc->save(__DIR__ . '/output/22-protection.pdf');Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Security\CryptoCapabilities;use NextPDF\Security\Encryption\Aes256GcmEncryptor;use NextPDF\Security\Exception\TamperedDataException;use NextPDF\Security\KeyMaterial;use Psr\Log\LoggerInterface;
final readonly class AuthenticatedBlobCipher{ public function __construct(private LoggerInterface $logger) {}
/** * Seal a payload with AES-256-GCM and return the wire-format bytes. * * @param non-empty-string $plaintext The payload to protect. * * @return non-empty-string IV(12) || ciphertext || tag(16). */ public function seal(string $plaintext, KeyMaterial $key): string { if (!CryptoCapabilities::hasAesGcm()) { throw new \RuntimeException('Host cannot perform AES-256-GCM.'); }
$cipher = new Aes256GcmEncryptor($key); // Opt-in NIST SP 800-38D §8.3 key-rotation guard. $cipher->assertWithinSafetyBound();
$wire = $cipher->encrypt($plaintext);
$this->logger->info('Payload sealed', [ 'key_fingerprint' => $key->fingerprint(), 'invocations' => $cipher->invocationCount(), ]);
return $wire; }
/** * Open a sealed payload; a modified payload raises, never returns plaintext. * * @param non-empty-string $wire IV(12) || ciphertext || tag(16). */ public function open(string $wire, KeyMaterial $key): string { try { return (new Aes256GcmEncryptor($key))->decrypt($wire); } catch (TamperedDataException $e) { $this->logger->warning('Tampered payload rejected', [ 'key_fingerprint' => $key->fingerprint(), ]);
throw $e; } }}Il cifrario verifica le capacità dell’host, applica la protezione opzionale sulle invocazioni, registra solo l’impronta non reversibile della chiave e rilancia il rifiuto per manomissione invece di restituire byte sospetti.
Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Il percorso predefinito AES-256-CBC garantisce solo la riservatezza. Da solo non rileva testo cifrato modificato. Usare il percorso AES-256-GCM quando serve rilevare le modifiche.
useAesGcm()solleva un’eccezione quando la modalità PDF/A è attiva e quando néopensslnéext-sodiumoffre AES-256-GCM. Catturare entrambe le eccezioni e presentare un messaggio azionabile per l’operatore.- Su un host privo di AES-NI, libsodium rifiuta GCM. Core ricade su OpenSSL GCM, che è corretto ma più lento; il throughput cala, la sicurezza no.
- Il limite massimo di testo in chiaro per oggetto in GCM è di
2^39 − 256byte. Un input più grande solleva un’eccezione di lunghezza; partizionare il contenuto tra più oggetti conencryptStream(). - Un’istanza di
KeyMaterialdeve essere esattamente di 32 byte; una lunghezza errata viene rifiutata alla costruzione, non troncata. - Il percorso di lettura (
verifyUserPassword(),verifyOwnerPassword(),validatePerms()) usa il confronto a tempo costante sul materiale crittografico e fallisce in modo sicuro su un marcatore dei permessi corrotto.
Prestazioni
Sezione intitolata “Prestazioni”La cifratura AES-256-CBC per oggetto è una singola chiamata OpenSSL, O(n) sul corpo dell’oggetto. La derivazione della chiave esegue la routine iterata dell’Algoritmo 2.B una volta per istanza dell’encryptor; il costo è limitato e costante per documento. Il percorso di streaming AES-256-GCM partiziona l’input in blocchi da 16 MiB, limitando l’heap attivo a circa 64 MB indipendentemente dalla dimensione totale dell’input, ben al di sotto del budget di picco documentato di 64 MB. Ogni oggetto GCM aggiunge 28 byte di overhead (IV di 12 byte più tag di 16 byte). L’hardware AES-NI migliora sensibilmente il throughput di GCM; la sua assenza riduce soltanto il throughput.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”Il modello di minaccia per questa superficie è esplicito. Il costo dei tentativi offline di indovinare la password aumenta grazie alla normalizzazione SASLprep e alla derivazione iterata della chiave alla revisione 6, ma una password debole resta il rischio residuo dominante. Nessuna derivazione lo elimina. La modifica del testo cifrato è rilevata nel percorso GCM tramite la verifica del tag e non è rilevata nel percorso CBC predefinito. Il riuso dell’IV nel percorso GCM è impedito da un contatore più un insieme di collisioni, coerentemente con la disciplina dell’IV di NIST SP 800-38D §8.1. Il rollover del contatore viene rifiutato invece di ripartire da zero. La divulgazione della chiave attraverso i log è mitigata dall’oscuramento di KeyMaterial e dall’attributo #[\SensitiveParameter] sulle password. Il materiale di chiave derivato viene azzerato dopo l’uso dove la piattaforma lo consente.
Il confine è altrettanto esplicito. La cifratura AES-256 è applicata come definito in ISO 32000-2:2020 §7.6 e, per il percorso opzionale, in ISO/TS 32003:2023 §5.2; la protezione effettiva dipende dalla robustezza della password, dalla gestione delle chiavi, dall’ambiente di deployment e dal reader che consuma il documento. I flag dei permessi sono rispettati dai reader conformi e non sono imposti dalla crittografia. Il passaggio AES-ECB usato per il valore /Perms è imposto da ISO 32000-2:2020 §7.6.4.4.10 per un singolo blocco di 16 byte. Non è una modalità per uso generico. La rotazione della chiave prima del limite di 2^32 invocazioni è una responsabilità del deployment: Core espone un controllo, ma non lo impone per impostazione predefinita.
Residenza dei dati e mitigazioni PII
Sezione intitolata “Residenza dei dati e mitigazioni PII”La cifratura e la decifratura sono eseguite in-process; nessun byte del documento, password o valore di chiave lascia l’host attraverso questa superficie. L’insieme di collisioni degli IV GCM è indicizzato su un’impronta non reversibile della chiave, non sui byte della chiave. Un deployment che premette alla chiave una gestione esterna delle chiavi o un token PKCS#11 è responsabile della residenza di quel backend; OASIS PKCS#11 v3.1 C_GenerateKey è il punto di contratto per la generazione di chiavi residenti nel token.
Telemetria sicura e ripulitura dei log
Sezione intitolata “Telemetria sicura e ripulitura dei log”Registrare il nome della policy e l’impronta della chiave di 8 caratteri, mai la chiave o la password. KeyMaterial::__toString() e __debugInfo() restituiscono un segnaposto oscurato. I messaggi di eccezione di questa superficie riportano un’etichetta dell’operazione e un’impronta, non i byte della chiave. Il conteggio delle invocazioni GCM è un segnale di telemetria sicuro per le dashboard di rotazione delle chiavi.
Modello di minaccia
Sezione intitolata “Modello di minaccia”| Minaccia | Mitigazione in Core | Confine residuo |
|---|---|---|
| Tentativi offline di indovinare la password | SASLprep più derivazione iterata alla revisione 6 | Una password debole resta il rischio dominante |
| Modifica del testo cifrato | Verifica del tag GCM (percorso opzionale) | Il percorso CBC garantisce solo la riservatezza |
| Riuso dell’IV (GCM) | Campo fisso casuale più contatore più insieme di collisioni; il rollover rifiuta | — |
| Testo in chiaro GCM eccessivamente lungo | Controllo di lunghezza a 2^39 − 256; indicazioni per il partizionamento | Il chiamante deve gestire in streaming gli input di grandi dimensioni |
| Uso eccessivo della chiave (GCM) | assertWithinSafetyBound() a 2^32 | Opzionale; non imposto per impostazione predefinita |
| Aggiramento dei flag dei permessi | Nessuna — i flag sono indicativi | Un reader non conforme ignora i flag |
| Divulgazione della chiave tramite i log | KeyMaterial oscuramento; #[\SensitiveParameter] | Un chiamante che registra nei log exposeKey() vanifica questa mitigazione |
Comportamento in modalità FIPS
Sezione intitolata “Comportamento in modalità FIPS”Core non è un modulo crittografico convalidato FIPS e non è certificato FIPS. CryptoCapabilities::detectFipsMode() è un rilevamento best-effort che segnala lo stato come attivo, assente o indeterminato, e assertFipsAvailableForProfile() fallisce in modo sicuro quando viene selezionato un profilo FIPS su un host che non dimostra la presenza di un provider FIPS. La superficie di cifratura opera in una modalità compatibile con FIPS quando viene eseguita su una build OpenSSL dell’host che ha caricato un provider convalidato FIPS. Una postura convalidata e certificata rientra nell’edizione Enterprise.
Conformità
Sezione intitolata “Conformità”| Affermazione | Standard | Clausola | Evidenza |
|---|---|---|---|
| Ogni IV GCM è unico per invocazione tramite una costruzione deterministica con campo fisso più contatore. | NIST SP 800-38D | §8.2.1 | |
| La disciplina di costruzione dell’IV impedisce il riuso tra invocazioni sulla stessa chiave. | NIST SP 800-38D | §8.1 | |
| Il limite massimo di testo in chiaro per oggetto corrisponde al limite di lunghezza per invocazione. | NIST SP 800-38D | §5.2.1.1 | |
| Il cryptoperiodo e la rotazione della chiave sono responsabilità del deployment. | NIST SP 800-57 Part 1 Rev. 5 | §4 | |
| La chiave di file AES è di 256 bit, corrispondente alla lunghezza della chiave prevista dallo standard. | FIPS 197 | §4.2.1 | |
| La generazione di chiavi residenti nel token è il punto di integrazione con l’archivio di chiavi esterno. | OASIS PKCS#11 v3.1 | C_GenerateKey |
ISO 32000-2:2020 §7.6 e ISO/TS 32003:2023 §5.2 sono la base normativa per i gestori qui documentati. Il loro testo è soggetto a restrizioni di licenza. Questa pagina li parafrasa, cita la clausola per numero e non riporta alcuna citazione testuale. L’evidenza di runtime verificata per la derivazione della chiave byte-esatta è il test sugli standard dell’Algoritmo 2.B e la fixture dell’oracolo esterno elencata nel trailer delle evidenze della pagina.
Contesto commerciale
Sezione intitolata “Contesto commerciale”Core fornisce sia il percorso predefinito AES-256-CBC sia il percorso opzionale AES-256-GCM con una superficie a chiave locale e il gate della crypto-policy. L’edizione Enterprise aggiunge un backend di custodia delle chiavi HSM/PKCS#11 e un profilo di crypto-policy in modalità FIPS dietro gli stessi contratti. L’API pubblica è identica; cambiano il backend di custodia delle chiavi e l’implementazione della policy.
Vedere anche
Sezione intitolata “Vedere anche”- Security — panoramica del modulo di sicurezza e confine dei permessi.
- Contracts / Security Policy — il contratto di crypto-policy che regola l’accesso al cifrario.
- Security / Signing — firme e marche temporali, la superficie crittografica affine.
- Conformance — il divieto PDF/A della chiave
Encrypt.