Enkripsi: AES-256 (CBC) dan AES-256-GCM
Gambaran umum
Bagian berjudul “Gambaran umum”Core mengenkripsi berkas Portable Document Format (PDF) dengan AES-256 (Advanced Encryption Standard dengan kunci 256 bit) menggunakan Standard security handler ISO 32000-2:2020 §7.6. Mode standarnya adalah V=5 / R=6 / AESV3 (AES-256-CBC, Cipher Block Chaining). Mode terautentikasi yang bersifat opt-in adalah jalur ISO/TS 32003:2023 V=6 / R=7 AES-256-GCM (Galois/Counter Mode). Halaman ini mendefinisikan derivasi kunci, format wire, batas izin, dan batasan deployment.
Pemasangan
Bagian berjudul “Pemasangan”composer require nextpdf/core:^3Jalur standar memerlukan ekstensi openssl. Jalur AES-256-GCM menggunakan openssl atau ext-sodium. Pada host tanpa perangkat keras AES-NI, libsodium menolak GCM; Core beralih ke implementasi OpenSSL yang lebih lambat tanpa mengubah algoritmanya.
Tinjauan konseptual
Bagian berjudul “Tinjauan konseptual”Handler standar menggunakan Standard security handler V=5 / R=6 dengan crypt filter AESV3. Saat Anda memanggil setEncryption(), Core menghasilkan kunci berkas acak 256 bit dari sumber keacakan kriptografis platform (random_bytes()). Kunci tersebut berukuran 32 byte, sesuai dengan panjang kunci FIPS 197. Core mengenkripsi konten per objek dengan AES-256-CBC. Core menambahkan initialization vector 16 byte di awal setiap ciphertext, sebagaimana diarahkan oleh ISO 32000-2:2020 §7.6.4.
Derivasi kunci mengikuti Algorithm 2.B pada revisi 6. Core terlebih dahulu menormalkan kata sandi dengan SASLprep (RFC 4013), lalu memotongnya menjadi 127 byte UTF-8 pada batas karakter, sebagaimana diarahkan oleh ISO 32000-2:2020 §7.6.4.3.3. Core menghitung hash turunan dengan rutin SHA-256 / SHA-384 / SHA-512 yang diiterasi dan digerakkan oleh langkah AES-128-CBC, sehingga meningkatkan biaya penebakan kata sandi secara offline. Core menghasilkan salt pengguna, salt pemilik, dan salt per kunci sekali untuk setiap instans encryptor, sehingga satu instans menghasilkan byte dictionary secara deterministik, sebuah prasyarat bagi writer multi-pass.
useAesGcm() mengaktifkan jalur AES-256-GCM yang bersifat opt-in. Jalur ini mengimplementasikan crypt filter AESV4 ISO/TS 32003:2023 V=6 / R=7. Cipher yang digunakan adalah AES-256-GCM dengan parameter dari NIST SP 800-38D. Untuk setiap objek terenkripsi, tata letak wire-nya adalah IV 12 byte, ciphertext, dan tag autentikasi 16 byte. Additional authenticated data-nya kosong, sebagaimana diarahkan oleh profil TS 32003 §5.2. Dekripsi memverifikasi tag dan memunculkan TamperedDataException saat terjadi ketidaksesuaian; dekripsi tidak pernah mengembalikan plaintext setelah tag gagal. Jalur ini menambahkan deteksi modifikasi yang tidak disediakan oleh jalur CBC standar dengan sendirinya.
Jalur GCM mengikuti disiplin keunikan IV dalam NIST SP 800-38D §8. Empat byte teratas dari IV adalah fixed field per instans yang disetel dari sumber acak selama konstruksi. Delapan byte terbawah adalah penghitung big-endian yang bertambah setelah setiap IV diterbitkan. Ini mengikuti pendekatan konstruksi-deterministik dalam §8.2.1, kecuali bahwa fixed field diacak untuk mencegah tumbukan lintas dokumen alih-alih dienumerasi. Pelindung kedua mencatat setiap IV yang dipancarkan dalam sebuah collision set dan memunculkan NonceReuseException jika ada nilai yang berulang. Counter rollover juga memunculkan NonceReuseException, karena rollover adalah mode kegagalan penggunaan ulang IV yang diperingatkan oleh §8.
Dua batas panjang berlaku pada jalur GCM. Batas atas plaintext per objek adalah 2^39 − 256 byte, yaitu batas per invokasi yang diturunkan dalam NIST SP 800-38D §5.2.1.1. Masukan yang lebih besar memunculkan length exception disertai panduan untuk membagi data ke beberapa objek. Batas keamanan invokasi adalah 2^32 pemanggilan per kunci. assertWithinSafetyBound() adalah pemeriksaan opt-in yang memunculkan GcmInvocationLimitExceededException, sehingga pemanggil dapat merotasi kunci dokumen sebelum ambang §8.3. NIST SP 800-57 Part 1 §4 memperlakukan keputusan masa pakai kunci ini sebagai tanggung jawab deployment.
Flag izin bersifat advisory. Core menulis bitmask ke entri /Perms yang terenkripsi dan nilai /P, lalu memulihkannya dengan validatePerms() saat dibaca; proses ini gagal-tertutup pada penanda yang rusak. Reader yang patuh diharapkan menghormati flag tersebut. Flag tersebut tidak ditegakkan oleh kriptografi: prosesor yang memiliki kunci dekripsi dan mengabaikan bit tersebut dapat membaca, menyalin, atau mengubah kontennya. Deskripsikan flag izin sebagai konvensi reader, bukan sebagai kontrol akses.
Permukaan API
Bagian berjudul “Permukaan API”| Tipe | Jenis | Anggota utama | Stabilitas | Sejak |
|---|---|---|---|---|
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 |
Contoh kode — Mulai cepat
Bagian berjudul “Contoh kode — Mulai cepat”<?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');Contoh kode — Produksi
Bagian berjudul “Contoh kode — Produksi”<?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; } }}Cipher ini memeriksa kapabilitas host, menerapkan invocation guard yang bersifat opt-in, hanya mencatat fingerprint kunci yang tidak dapat dibalik, dan melempar ulang penolakan tamper alih-alih mengembalikan byte yang mencurigakan.
Kasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”- Jalur AES-256-CBC standar hanya menyediakan kerahasiaan. Jalur ini tidak mendeteksi ciphertext yang dimodifikasi dengan sendirinya. Gunakan jalur AES-256-GCM saat Anda memerlukan deteksi modifikasi.
useAesGcm()memunculkan kesalahan saat mode PDF/A aktif dan saatopensslmaupunext-sodiumtidak menyediakan AES-256-GCM. Tangani kedua kasus tersebut dan tampilkan pesan yang dapat ditindaklanjuti oleh operator.- Pada host tanpa AES-NI, libsodium menolak GCM. Core beralih ke OpenSSL GCM, yang benar tetapi lebih lambat; throughput menurun, bukan keamanan.
- Batas atas plaintext per objek GCM adalah
2^39 − 256byte. Masukan yang lebih besar memunculkan length exception; bagi konten ke beberapa objek denganencryptStream(). - Instans
KeyMaterialharus tepat 32 byte. Pembuatan menolak panjang yang salah alih-alih memotongnya. - Jalur reader (
verifyUserPassword(),verifyOwnerPassword(),validatePerms()) menggunakan perbandingan waktu-konstan untuk material kriptografis dan gagal-tertutup pada penanda izin yang rusak.
Kinerja
Bagian berjudul “Kinerja”Enkripsi AES-256-CBC per objek adalah satu pemanggilan OpenSSL dan bersifat O(n) terhadap isi objek. Derivasi kunci menjalankan rutin Algorithm 2.B yang diiterasi sekali per instans encryptor; biayanya terbatas dan konstan per dokumen. Jalur streaming AES-256-GCM membagi masukan menjadi potongan 16 MiB, membatasi penggunaan heap aktif menjadi kira-kira 64 MB terlepas dari ukuran total masukan dan tetap di bawah anggaran puncak 64 MB yang terdokumentasi. Setiap objek GCM menambahkan overhead 28 byte (IV 12 byte ditambah tag 16 byte). Perangkat keras AES-NI secara signifikan meningkatkan throughput GCM; tanpanya, hanya throughput yang menurun.
Catatan keamanan
Bagian berjudul “Catatan keamanan”Permukaan enkripsi ini memiliki threat model yang eksplisit. Normalisasi SASLprep ditambah derivasi kunci revisi-6 yang diiterasi meningkatkan biaya penebakan kata sandi secara offline, tetapi kata sandi yang lemah tetap menjadi risiko residual yang dominan. Tidak ada derivasi yang menghilangkan risiko tersebut. Jalur GCM mendeteksi modifikasi ciphertext melalui verifikasi tag; jalur CBC standar tidak. Pada jalur GCM, penghitung beserta collision set mencegah penggunaan ulang IV, konsisten dengan disiplin IV NIST SP 800-38D §8.1. Counter rollover menolak alih-alih membungkus. Redaksi KeyMaterial dan atribut #[\SensitiveParameter] pada kata sandi memitigasi pengungkapan kunci melalui log. Material kunci turunan dinolkan setelah digunakan jika platform mengizinkannya.
Batasannya juga eksplisit. Core menerapkan enkripsi AES-256 sebagaimana didefinisikan dalam ISO 32000-2:2020 §7.6 dan, untuk jalur opt-in, ISO/TS 32003:2023 §5.2. Perlindungan yang efektif bergantung pada kekuatan kata sandi, manajemen kunci, lingkungan deployment, dan reader yang mengonsumsinya. Reader yang patuh menghormati flag izin, tetapi kriptografi tidak menegakkannya. Langkah AES-ECB yang digunakan untuk nilai /Perms diwajibkan oleh ISO 32000-2:2020 §7.6.4.4.10 untuk satu blok 16 byte. Ini bukan mode tujuan-umum. Core menyediakan pemeriksaan untuk rotasi kunci sebelum batas invokasi 2^32, tetapi tidak menegakkannya secara default; rotasi tersebut adalah tanggung jawab deployment.
Residensi Data & Mitigasi PII
Bagian berjudul “Residensi Data & Mitigasi PII”Enkripsi dan dekripsi berjalan dalam proses; tidak ada byte dokumen, kata sandi, atau nilai kunci yang meninggalkan host melalui permukaan ini. Collision set IV GCM berbasis pada fingerprint kunci yang tidak dapat dibalik, bukan pada byte kunci. Jika sebuah deployment menempatkan kunci di belakang sistem manajemen kunci eksternal atau token PKCS#11, backend tersebut bertanggung jawab atas residensi; OASIS PKCS#11 v3.1 C_GenerateKey adalah titik kontrak untuk pembuatan kunci yang berada di token.
Telemetri Aman & Pembersihan Log
Bagian berjudul “Telemetri Aman & Pembersihan Log”Catat nama kebijakan dan fingerprint kunci 8 karakter; jangan pernah mencatat kunci atau kata sandinya. KeyMaterial::__toString() dan __debugInfo() mengembalikan placeholder yang diredaksi. Exception dari permukaan ini menyertakan label operasi dan fingerprint, bukan byte kunci. Hitungan invokasi GCM adalah telemetri aman untuk dasbor rotasi kunci.
Threat model
Bagian berjudul “Threat model”| Ancaman | Mitigasi di Core | Batas residual |
|---|---|---|
| Penebakan kata sandi secara offline | SASLprep ditambah derivasi revisi-6 yang diiterasi | Kata sandi yang lemah tetap menjadi risiko dominan |
| Modifikasi ciphertext | Verifikasi tag GCM (jalur opt-in) | Jalur CBC hanya kerahasiaan |
| Penggunaan ulang IV (GCM) | Fixed field acak ditambah penghitung ditambah collision set; rollover menolak | — |
| Plaintext GCM yang terlalu panjang | Pemeriksaan panjang pada 2^39 − 256; panduan pembagian | Pemanggil harus melakukan streaming masukan yang besar |
| Penggunaan kunci yang berlebihan (GCM) | assertWithinSafetyBound() pada 2^32 | Opt-in; tidak ditegakkan secara default |
| Pengabaian flag izin | Tidak ada — flag bersifat advisory | Reader yang tidak patuh mengabaikan flag tersebut |
| Pengungkapan kunci melalui log | Redaksi KeyMaterial; #[\SensitiveParameter] | Pemanggil yang mencatat exposeKey() menggagalkan ini |
Perilaku mode FIPS
Bagian berjudul “Perilaku mode FIPS”Core bukan modul kriptografis yang tervalidasi FIPS dan tidak bersertifikat FIPS. CryptoCapabilities::detectFipsMode() adalah probe best-effort yang melaporkan aktif, tidak ada, atau tidak pasti. assertFipsAvailableForProfile() gagal-tertutup saat profil FIPS dipilih pada host yang tidak membuktikan adanya FIPS provider. Permukaan enkripsi beroperasi dalam mode yang kompatibel dengan FIPS saat dijalankan terhadap build OpenSSL host yang telah memuat provider tervalidasi FIPS. Postur yang tervalidasi dan tersertifikasi adalah ranah Enterprise.
Konformansi
Bagian berjudul “Konformansi”| Klaim | Standar | Klausul | Bukti |
|---|---|---|---|
| Setiap IV GCM unik per invokasi melalui konstruksi fixed-field-plus-counter yang deterministik. | NIST SP 800-38D | §8.2.1 | |
| Disiplin konstruksi IV mencegah penggunaan ulang lintas invokasi pada satu kunci. | NIST SP 800-38D | §8.1 | |
| Batas atas plaintext per objek sesuai dengan batas panjang per invokasi. | NIST SP 800-38D | §5.2.1.1 | |
| Cryptoperiod dan rotasi kunci adalah tanggung jawab deployment. | NIST SP 800-57 Part 1 Rev. 5 | §4 | |
| Kunci berkas AES berukuran 256 bit, sesuai dengan panjang kunci standar tersebut. | FIPS 197 | §4.2.1 | |
| Pembuatan kunci yang berada di token adalah titik integrasi key-store eksternal. | OASIS PKCS#11 v3.1 | C_GenerateKey |
ISO 32000-2:2020 §7.6 dan ISO/TS 32003:2023 §5.2 adalah dasar normatif bagi handler yang didokumentasikan di sini. Teksnya bersifat license-restricted. Halaman ini memparafrasakan standar tersebut, mengutip klausul berdasarkan nomor, dan tidak mengutip satu pun darinya. Standards test Algorithm 2.B dan fixture external-oracle dalam evidence trailer halaman ini menyediakan bukti runtime terverifikasi untuk derivasi kunci yang byte-exact.
Konteks komersial
Bagian berjudul “Konteks komersial”Core menyertakan jalur AES-256-CBC standar, jalur AES-256-GCM yang bersifat opt-in, permukaan local-key, dan gerbang kebijakan kripto. Edisi Enterprise menambahkan backend key-custody HSM/PKCS#11 dan profil kebijakan kripto mode FIPS di balik kontrak yang sama. Antarmuka pemrograman aplikasi (API) publiknya identik; backend key-custody dan implementasi kebijakannya berbeda.
Lihat juga
Bagian berjudul “Lihat juga”- Keamanan — tinjauan modul keamanan dan batas izin.
- Contracts / Security Policy — kontrak kebijakan kripto yang menjadi gerbang untuk cipher.
- Security / Signing — tanda tangan dan timestamp, permukaan kripto serumpun.
- Konformansi — larangan PDF/A terhadap kunci
Encrypt.