Przejdź do głównej zawartości

Szyfrowanie: AES-256 (CBC) i AES-256-GCM

Core szyfruje pliki w formacie Portable Document Format (PDF) algorytmem AES-256 (Advanced Encryption Standard z kluczami 256-bitowymi) zgodnie ze standardowym programem obsługi zabezpieczeń z normy ISO 32000-2:2020 §7.6. Tryb domyślny to V=5 / R=6 / AESV3 (AES-256-CBC, Cipher Block Chaining). Opcjonalna uwierzytelniona ścieżka to AES-256-GCM (Galois/Counter Mode) V=6 / R=7 z normy ISO/TS 32003:2023. Ta strona definiuje wyprowadzanie klucza, format transmisji, granicę uprawnień oraz ograniczenia wdrożeniowe.

Okno terminala
composer require nextpdf/core:^3

Ścieżka domyślna wymaga rozszerzenia openssl. Ścieżka AES-256-GCM korzysta z openssl lub ext-sodium. Na hostach bez sprzętowej obsługi AES-NI libsodium odmawia wykonywania GCM; Core przełącza się wtedy na wolniejszą implementację OpenSSL, nie zmieniając algorytmu.

Domyślny mechanizm korzysta ze standardowego programu obsługi zabezpieczeń V=5 / R=6 z filtrem szyfrującym AESV3. Po wywołaniu setEncryption() Core generuje losowy 256-bitowy klucz pliku z kryptograficznego źródła losowości platformy (random_bytes()). Klucz ma 32 bajty, co odpowiada długości klucza według FIPS 197. Core szyfruje zawartość poszczególnych obiektów algorytmem AES-256-CBC. Na początku każdego szyfrogramu dołącza 16-bajtowy wektor inicjujący, zgodnie z wytycznymi normy ISO 32000-2:2020 §7.6.4.

Wyprowadzanie klucza przebiega zgodnie z Algorytmem 2.B w wersji 6. Core najpierw normalizuje hasło za pomocą SASLprep (RFC 4013), a następnie skraca je do 127 bajtów UTF-8 na granicy znaku, zgodnie z wytycznymi normy ISO 32000-2:2020 §7.6.4.3.3. Wyprowadzony skrót oblicza iterowaną procedurą SHA-256 / SHA-384 / SHA-512 sterowaną krokiem AES-128-CBC, co zwiększa koszt zgadywania hasła w trybie offline. Core generuje sole użytkownika, właściciela oraz sole poszczególnych kluczy raz dla danego egzemplarza szyfratora, dzięki czemu jeden egzemplarz emituje deterministyczne bajty słownika. Jest to warunek wstępny dla wieloprzebiegowego mechanizmu zapisu.

useAesGcm() włącza opcjonalną ścieżkę AES-256-GCM. Implementuje ona filtr szyfrujący AESV4 V=6 / R=7 z normy ISO/TS 32003:2023. Używanym szyfrem jest AES-256-GCM z parametrami z NIST SP 800-38D. Dla każdego zaszyfrowanego obiektu układ transmisji składa się z 12-bajtowego wektora IV, szyfrogramu oraz 16-bajtowego znacznika uwierzytelniającego. Dodatkowe dane uwierzytelniane pozostają puste, zgodnie z wytycznymi profilu TS 32003 §5.2. Odszyfrowywanie weryfikuje znacznik i w przypadku niezgodności zgłasza TamperedDataException; nigdy nie zwraca tekstu jawnego po nieudanej weryfikacji znacznika. Ta ścieżka zapewnia wykrywanie modyfikacji, którego domyślna ścieżka CBC sama z siebie nie zapewnia.

Ścieżka GCM przestrzega zasady unikalności wektora IV opisanej w NIST SP 800-38D §8. Górne 4 bajty wektora IV stanowią pole stałe dla danego egzemplarza, ustawiane podczas konstrukcji z losowego źródła. Dolne 8 bajtów to licznik w porządku big-endian, który zwiększa się po każdym wydanym wektorze IV. Jest to zgodne z podejściem konstrukcji deterministycznej z §8.2.1, z tą różnicą, że pole stałe jest losowane, aby zapobiec kolizjom między dokumentami, zamiast być numerowane. Drugie zabezpieczenie rejestruje każdy wyemitowany wektor IV w zbiorze kolizji i zgłasza NonceReuseException, jeśli którakolwiek wartość się powtórzy. Przepełnienie licznika również zgłasza NonceReuseException, ponieważ jest to tryb awarii polegający na ponownym użyciu wektora IV, przed którym ostrzega §8.

Do ścieżki GCM mają zastosowanie dwa ograniczenia długości. Górny limit tekstu jawnego na obiekt wynosi 2^39 − 256 bajtów, czyli ograniczenie na pojedyncze wywołanie wyprowadzone z NIST SP 800-38D §5.2.1.1. Większe dane wejściowe powodują zgłoszenie wyjątku długości wraz ze wskazówką, aby podzielić dane na obiekty. Limit bezpieczeństwa wywołań wynosi 2^32 wywołań na klucz. assertWithinSafetyBound() to opcjonalne sprawdzenie, które zgłasza GcmInvocationLimitExceededException, pozwalając wywołującemu zmienić klucz dokumentu przed osiągnięciem progu z §8.3. NIST SP 800-57 część 1 §4 traktuje decyzję dotyczącą okresu życia klucza jako obowiązek wdrożeniowy.

Flagi uprawnień mają charakter zaleceń. Core zapisuje maskę bitową w zaszyfrowanym wpisie /Perms oraz w wartości /P, a następnie odzyskuje ją podczas odczytu za pomocą validatePerms(); w przypadku uszkodzonego znacznika ta walidacja kończy się odmową. Oczekuje się, że zgodny czytnik będzie respektował te flagi. Flagi te nie są egzekwowane kryptograficznie: procesor, który ma klucz odszyfrowujący i ignoruje te bity, może odczytać, skopiować lub zmodyfikować zawartość. Opisuj flagi uprawnień jako konwencję czytnika, a nie jako kontrolę dostępu.

TypRodzajKluczowe składoweStabilnośćOd wersji
Aes256Encryptorklasaencrypt(), decrypt(), encryptForObject(), buildEncryptionDictionary(), verifyUserPassword(), verifyOwnerPassword(), validatePerms(), getEncryptionKey()stabilny1.0.0
Aes256GcmEncryptorklasaencrypt(), decrypt(), encryptStream(), assertWithinSafetyBound(), invocationCount(), isAvailable()stabilny2.18.0
KeyMaterialklasa final readonlygenerate(), exposeKey(), fingerprint()stabilny2.18.0
EncryptedPayloadSpecklasa final readonlytoDict()stabilny2.18.0
CryptoCapabilitiesklasa finalhasAesGcm(), detectFipsMode(), assertFipsAvailableForProfile()stabilny2.0.0
NonceReuseExceptionwyjątekstabilny2.18.0
TamperedDataExceptionwyjątekstabilny2.18.0
DecryptionFailedExceptionwyjątekstabilny2.18.0
GcmInvocationLimitExceededExceptionwyjątekstabilny3.0.0
examples/22-protection.php
<?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');
examples/security/gcm-authenticated-encryption.php
<?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;
}
}
}

Szyfr sprawdza możliwości hosta, stosuje opcjonalne zabezpieczenie wywołań, rejestruje wyłącznie nieodwracalny odcisk klucza i ponownie zgłasza odrzucenia wynikające z naruszenia integralności, zamiast zwracać podejrzane bajty.

  • Domyślna ścieżka AES-256-CBC zapewnia wyłącznie poufność. Sama z siebie nie wykrywa zmodyfikowanego szyfrogramu. Gdy potrzebujesz wykrywania modyfikacji, użyj ścieżki AES-256-GCM.
  • useAesGcm() zgłasza wyjątek, gdy aktywny jest tryb PDF/A oraz gdy ani openssl, ani ext-sodium nie oferuje AES-256-GCM. Przechwyć oba przypadki i przekaż operatorowi komunikat umożliwiający podjęcie działania.
  • Na hostach bez AES-NI libsodium odmawia wykonywania GCM. Core przełącza się na OpenSSL GCM, który jest poprawny, lecz wolniejszy; spada przepustowość, a nie bezpieczeństwo.
  • Górny limit tekstu jawnego GCM na obiekt wynosi 2^39 − 256 bajtów. Większe dane wejściowe powodują zgłoszenie wyjątku długości; podziel zawartość na wiele obiektów za pomocą encryptStream().
  • Egzemplarz KeyMaterial musi mieć dokładnie 32 bajty. Konstruktor odrzuca błędną długość, zamiast ją skracać.
  • Ścieżka odczytu (verifyUserPassword(), verifyOwnerPassword(), validatePerms()) używa porównania o stałym czasie wykonania dla materiału kryptograficznego i w przypadku uszkodzonego znacznika uprawnień kończy się odmową.

Szyfrowanie AES-256-CBC pojedynczego obiektu to jedno wywołanie OpenSSL o złożoności O(n) względem rozmiaru treści obiektu. Wyprowadzanie klucza uruchamia iterowaną procedurę Algorytmu 2.B raz na egzemplarz szyfratora; koszt jest ograniczony i stały na dokument. Strumieniowa ścieżka AES-256-GCM dzieli dane wejściowe na fragmenty po 16 MiB, ograniczając bieżące użycie sterty do około 64 MB niezależnie od całkowitego rozmiaru danych wejściowych i pozostając poniżej udokumentowanego limitu szczytowego 64 MB. Każdy obiekt GCM dodaje 28 bajtów narzutu (12-bajtowy wektor IV plus 16-bajtowy znacznik). Sprzęt AES-NI znacząco poprawia przepustowość GCM; bez niego spada jedynie przepustowość.

Ta powierzchnia szyfrowania ma jawny model zagrożeń. Normalizacja SASLprep wraz z iterowanym wyprowadzaniem klucza w wersji 6 podnosi koszt zgadywania hasła w trybie offline, jednak słabe hasło pozostaje dominującym ryzykiem szczątkowym. Żaden sposób wyprowadzania klucza nie usuwa tego ryzyka. Ścieżka GCM wykrywa modyfikację szyfrogramu dzięki weryfikacji znacznika; domyślna ścieżka CBC tego nie robi. W ścieżce GCM licznik wraz ze zbiorem kolizji zapobiega ponownemu użyciu wektora IV, zgodnie z zasadą dotyczącą IV z NIST SP 800-38D §8.1. Przepełnienie licznika powoduje odmowę, a nie zawinięcie. Maskowanie KeyMaterial oraz atrybut #[\SensitiveParameter] na hasłach ograniczają ujawnienie klucza poprzez dzienniki. Wyprowadzony materiał klucza jest zerowany po użyciu tam, gdzie pozwala na to platforma.

Granica również jest wyraźnie określona. Core stosuje szyfrowanie AES-256 zgodnie z definicją w ISO 32000-2:2020 §7.6, a dla ścieżki opcjonalnej zgodnie z ISO/TS 32003:2023 §5.2. Skuteczna ochrona zależy od siły hasła, zarządzania kluczami, środowiska wdrożeniowego oraz czytnika używanego do odczytu. Zgodne czytniki respektują flagi uprawnień, ale kryptografia ich nie egzekwuje. Krok AES-ECB użyty dla wartości /Perms jest wymagany przez ISO 32000-2:2020 §7.6.4.4.10 dla pojedynczego 16-bajtowego bloku. Nie jest to tryb ogólnego przeznaczenia. Core udostępnia sprawdzenie rotacji klucza przed osiągnięciem limitu 2^32 wywołań, ale domyślnie jej nie egzekwuje; ta rotacja jest obowiązkiem wdrożeniowym.

Rezydencja danych i ograniczanie ryzyka związanego z danymi osobowymi (PII)

Dział zatytułowany „Rezydencja danych i ograniczanie ryzyka związanego z danymi osobowymi (PII)”

Szyfrowanie i odszyfrowywanie odbywają się w obrębie procesu; ta powierzchnia nie powoduje, że bajty dokumentu, hasło lub wartość klucza opuszczają hosta. Zbiór kolizji wektorów IV GCM jest indeksowany nieodwracalnym odciskiem klucza, a nie bajtami klucza. Jeśli wdrożenie umieszcza klucz za zewnętrznym systemem zarządzania kluczami lub tokenem PKCS#11, za rezydencję odpowiada to zaplecze; punktem kontraktowym dla generowania klucza rezydującego w tokenie jest OASIS PKCS#11 v3.1 C_GenerateKey.

Rejestruj nazwę polityki oraz 8-znakowy odcisk klucza, nigdy klucz ani hasło. KeyMaterial::__toString() oraz __debugInfo() zwracają zamaskowany symbol zastępczy. Wyjątki z tej powierzchni zawierają etykietę operacji oraz odcisk, a nie bajty klucza. Liczba wywołań GCM jest bezpieczną telemetrią dla pulpitów rotacji kluczy.

ZagrożenieOgraniczenie ryzyka w CoreGranica szczątkowa
Zgadywanie hasła w trybie offlineSASLprep wraz z iterowanym wyprowadzaniem klucza w wersji 6Słabe hasło wciąż pozostaje dominującym ryzykiem
Modyfikacja szyfrogramuWeryfikacja znacznika GCM (ścieżka opcjonalna)Ścieżka CBC zapewnia wyłącznie poufność
Ponowne użycie wektora IV (GCM)Losowe pole stałe wraz z licznikiem i zbiorem kolizji; przepełnienie powoduje odmowę
Zbyt długi tekst jawny GCMSprawdzenie długości przy 2^39 − 256; wskazówka dotycząca podziałuWywołujący musi strumieniować duże dane wejściowe
Nadmierne użycie klucza (GCM)assertWithinSafetyBound() przy 2^32Opcjonalne; domyślnie nieegzekwowane
Obejście flag uprawnieńBrak — flagi mają charakter zaleceńNiezgodny czytnik ignoruje flagi
Ujawnienie klucza poprzez dziennikiMaskowanie KeyMaterial; #[\SensitiveParameter]Wywołujący, który rejestruje exposeKey(), niweczy to zabezpieczenie

Core nie jest modułem kryptograficznym walidowanym według FIPS i nie ma certyfikatu FIPS. CryptoCapabilities::detectFipsMode() to sonda o charakterze best-effort, która zgłasza stan aktywny, nieobecny lub nieokreślony. assertFipsAvailableForProfile() kończy się odmową, gdy profil FIPS zostanie wybrany na hoście, który nie potwierdza dostępności dostawcy FIPS. Powierzchnia szyfrowania działa w trybie zgodnym z FIPS, gdy uruchamiana jest na hoście z kompilacją OpenSSL, która załadowała dostawcę walidowanego według FIPS. Walidowana, certyfikowana konfiguracja jest kwestią edycji Enterprise.

TwierdzenieStandardKlauzulaDowód
Każdy wektor IV GCM jest unikalny w obrębie wywołania dzięki deterministycznej konstrukcji pole-stałe-plus-licznik.NIST SP 800-38D§8.2.1
Zasada konstrukcji wektora IV zapobiega ponownemu użyciu w obrębie wywołań na jednym kluczu.NIST SP 800-38D§8.1
Górny limit tekstu jawnego na obiekt odpowiada ograniczeniu długości na pojedyncze wywołanie.NIST SP 800-38D§5.2.1.1
Okres życia klucza i jego rotacja są obowiązkiem wdrożeniowym.NIST SP 800-57 część 1 wyd. 5§4
Klucz pliku AES ma 256 bitów, co odpowiada długości klucza określonej w standardzie.FIPS 197§4.2.1
Generowanie klucza rezydującego w tokenie jest punktem integracji z zewnętrznym magazynem kluczy.OASIS PKCS#11 v3.1C_GenerateKey

ISO 32000-2:2020 §7.6 oraz ISO/TS 32003:2023 §5.2 stanowią normatywną podstawę dla programów obsługi udokumentowanych tutaj. Ich tekst jest objęty ograniczeniami licencyjnymi. Ta strona parafrazuje te standardy, cytuje klauzule po numerach i nie przytacza żadnego z nich dosłownie. Test zgodności Algorytmu 2.B oraz fikstura zewnętrznego oracle wskazane w stopce dowodowej strony dostarczają zweryfikowanych dowodów wykonania dla bajtowo dokładnego wyprowadzania klucza.

Core dostarcza domyślną ścieżkę AES-256-CBC, opcjonalną ścieżkę AES-256-GCM, powierzchnię klucza lokalnego oraz bramkę polityki kryptograficznej. Edycja Enterprise dodaje zaplecze przechowywania kluczy HSM/PKCS#11 oraz profil polityki kryptograficznej w trybie FIPS w obrębie tych samych kontraktów. Publiczne API jest identyczne; różni się zaplecze przechowywania kluczy oraz implementacja polityki.