Lewati ke konten
getnextpdf.com

Enterprise edisi

Watermarking digital dan penyematan steganografis

NextPDF Enterprise menyematkan payload tersembunyi dan terenkripsi ke dalam PDF yang dihasilkan dengan membuat penyesuaian kecil dan terkendali pada spasi antara pasangan huruf. Anda memasok sebuah payload — biasanya pengenal per-penerima — dan sebuah kunci rahasia; encoder menulis payload sebagai deviasi imperseptibel dari kerning alami teks. Sebuah decoder yang cocok, diberi kunci yang sama, memulihkan payload. Halaman ini berada pada tingkat perilaku: ia menyatakan apa yang ditulis encoder, kriptografi yang dipakainya, dan batas tekniknya.

Penggunaan yang dituju adalah pelacakan kebocoran dokumen internal: ketika sebuah dokumen terkendali bocor, penanda yang dipulihkan mengidentifikasi salinan penerima. Ini bukan steganografi adversarial dan bukan jaminan bertahan melalui pemrosesan sembarang.

Prasyarat dinyatakan dalam front matter dan diulang di bawah Prasyarat.

Kapabilitas ini dikapalkan dalam NextPDF Enterprise (nextpdf/enterprise) dan diaktifkan dengan envelope lisensi tingkat Enterprise. Deployment tanpa entitlement tersebut tidak memuat kelas-kelas kapabilitas ini. Kapabilitas berjalan sepenuhnya in-process selama pembuatan dokumen; tidak ada konten dokumen yang meninggalkan host. Bandingkan edisi dan dapatkan lisensi.

Teks PDF yang digambar dengan array kerning membawa penyesuaian numerik antar-glyph. Encoder memperlakukan setiap posisi penyesuaian sebagai carrier untuk beberapa bit:

  1. Ia mengenkripsi payload dengan cipher authenticated-encryption-with-associated-data (AEAD) — AES-256-GCM secara default, atau ChaCha20-Poly1305. AEAD memberikan kerahasiaan dan integritas sekaligus, sehingga carrier yang dirusak gagal dekripsi alih-alih menghasilkan payload yang salah secara diam-diam.
  2. Ia menurunkan kunci enkripsi 32-byte dari kunci rahasia Anda dan kunci font menggunakan HMAC-based Key Derivation Function (HKDF) dengan SHA-256. HKDF mengekstrak kunci pseudorandom panjang-tetap dari input keying material, lalu mengembangkannya ke panjang yang diperlukan, sesuai RFC 5869 §2.
  3. Ia menghasilkan initialization vector (IV) 12-byte acak yang segar per enkripsi. AES-GCM mengharuskan IV unik untuk kunci tertentu, atau jaminan autentikasi hilang, sesuai NIST SP 800-38D §5.2.1.
  4. Ia memetakan byte terenkripsi ke urutan bit dan mendistribusikan bit di seluruh posisi pasangan-huruf yang tersedia, meng-encode satu atau dua bit per posisi. Deviasi yang ditambahkannya pada kerning alami dibatasi oleh fraksi em yang dapat dikonfigurasi — cukup kecil agar tetap imperseptibel secara visual.

Decoder membalik prosesnya: ia membaca penyesuaian kerning dari sebuah content stream, mengurangi kerning alami, mengkuantisasi deviasi kembali ke bit, merakit ulang blob terenkripsi, dan mendekripsinya dengan kunci yang sama. Jika kunci salah atau carrier hancur, dekripsi tidak mengembalikan apa pun alih-alih payload yang salah.

Kapasitas berskala dengan panjang teks: setiap posisi pasangan-huruf membawa satu atau dua bit, sehingga sebuah payload harus muat pada posisi yang disediakan teks. Encoder memunculkan error overflow bertipe ketika payload melampaui kapasitas.

Mode kompatibilitas PDF/A membagi dua deviasi maksimum agar tetap di bawah ambang batas toleransi-lebar sebuah validator, menukar kapasitas demi konformansi yang lebih ketat.

Pilihan yang menopang teknik ini adalah menyembunyikan penanda di dalam kerning alih-alih dalam overlay yang terlihat atau field metadata. Penanda metadata sepele untuk dilucuti, dan stempel yang terlihat mengubah halaman. Deviasi kerning sebaliknya menumpang di dalam teks yang harus dipertahankan penerima, dan tetap imperseptibel. Enkripsi terautentikasi adalah pilar kedua: carrier yang dirusak atau parsial gagal autentikasi, sehingga decoder tidak mengembalikan apa pun alih-alih penerima yang salah. Kunci diturunkan per font dengan HKDF, mengikat penanda pada konteks dokumen, bukan pada secret bersama yang telanjang. Pengungkapan ketahanan yang jujur mengikuti secara langsung: penanda bertahan melalui redistribusi biasa tetapi tidak melalui penulisan-ulang content-stream yang disengaja, sehingga cakupan yang dinyatakan adalah pelacakan kebocoran internal, bukan steganografi adversarial.

Latar belakang desain: Redaksi bukanlah persegi panjang hitam.

  1. Pasang NextPDF Core dan paket Enterprise, serta pegang lisensi Enterprise aktif.
  2. Hasilkan dokumen dengan font yang mengekspos metrik kerning-pair; encoder membaca kerning alami dari metrik font.
  3. Pasok kunci rahasia dari secret manager Anda, bukan dari source. Kunci yang sama diperlukan untuk men-decode.
  4. Tentukan bit depth (satu atau dua bit per posisi) dan apakah kompatibilitas PDF/A diperlukan, berdasarkan kebutuhan kapasitas dan konformansi Anda.

Konfigurasi encoding bersifat imutabel dan divalidasi saat konstruksi:

  • Bit depth — satu atau dua bit per posisi pasangan-huruf. Depth lebih tinggi memberi lebih banyak kapasitas tetapi deviasi lebih besar.
  • Rasio penyesuaian maksimum — plafon deviasi sebagai fraksi em, dalam rentang yang dibatasi. Nilai lebih besar memberi lebih banyak headroom tetapi berisiko terlihat.
  • Cipher — AES-256-GCM (default) atau ChaCha20-Poly1305. Keduanya AEAD.
  • Kompatibilitas PDF/A — ketika diaktifkan, membagi dua deviasi maksimum efektif.

Gunakan konfigurasi yang sama untuk encoding dan decoding; ketidakcocokan menghasilkan tidak ada payload yang dipulihkan.

  1. Baca kunci rahasia dari secret manager Anda.
  2. Bangun konfigurasi encoding (bit depth, rasio deviasi, cipher, flag PDF/A).
  3. Hitung penyesuaian kerning untuk teks yang akan Anda render, dengan memberikan payload, teks, kunci font, metrik font, kunci rahasia, dan konfigurasi.
  4. Terapkan penyesuaian yang dikembalikan saat Anda menulis text run, sehingga penanda tersemat selama pembuatan.
  5. Untuk melacak salinan yang bocor, jalankan decoder atas content stream dokumen yang dicurigai dengan kunci font, metrik font, kunci rahasia, dan konfigurasi yang sama, dan baca payload yang dipulihkan.
examples/enterprise/steganography-capacity-guard.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
/**
* Reject a payload that cannot fit the carrier text before encoding.
*
* Each letter-pair position carries $bitDepth bits. Guarding capacity up
* front turns an unencodable payload into a clear caller-side error instead
* of relying on the encoder's overflow exception alone.
*
* @param non-empty-string $payload The bytes to embed (already minimal).
* @param positive-int $textLength The character count of the carrier text.
* @param int<1, 2> $bitDepth Bits encoded per letter-pair position.
*
* @throws \OverflowException When the payload cannot fit the available positions.
*/
function assertPayloadFits(string $payload, int $textLength, int $bitDepth): void
{
$positions = $textLength - 1;
$capacityBytes = \intdiv($positions * $bitDepth, 8);
if (\strlen($payload) > $capacityBytes) {
throw new \OverflowException(\sprintf(
'Payload of %d bytes exceeds carrier capacity of %d bytes.',
\strlen($payload),
$capacityBytes,
));
}
}
examples/enterprise/steganography-decode-guarded.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Enterprise\Security\Steganography\SteganographyDecoder;
use NextPDF\Enterprise\Security\Steganography\SteganographyConfig;
use NextPDF\Typography\FontMetrics;
use Psr\Log\LoggerInterface;
final readonly class LeakTracer
{
public function __construct(private LoggerInterface $logger) {}
/**
* Recover the embedded marker from a suspect document's content stream.
*
* Decoding returns null on a wrong key or a destroyed carrier rather than
* a wrong payload, so the caller treats null as "no marker recovered".
*
* @param string $contentStream The suspect content-stream bytes.
* @param non-empty-string $fontKey The font key used at generation.
* @param FontMetrics $metrics Font metrics with kerning pairs.
* @param string $secretKey The same secret key used to encode.
* @param SteganographyConfig $config The same configuration used to encode.
*
* @return string|null The recovered marker, or null when none is found.
*/
public function trace(
string $contentStream,
string $fontKey,
FontMetrics $metrics,
string $secretKey,
SteganographyConfig $config,
): ?string {
$marker = SteganographyDecoder::decodeFromContentStream(
$contentStream,
$fontKey,
$metrics,
$secretKey,
$config,
);
if ($marker === null) {
$this->logger->info('No steganographic marker recovered from content stream.');
}
return $marker;
}
}
  1. Encode sebuah payload yang diketahui ke dalam sebuah text run yang diketahui, lalu decode kembali dengan kunci dan konfigurasi yang sama; konfirmasikan payload yang dipulihkan cocok.
  2. Decode dengan kunci yang sengaja salah dan konfirmasikan hasilnya null, bukan payload yang salah — ini adalah jaminan integritas AEAD yang bekerja.
  3. Inspeksi halaman yang dirender dan konfirmasikan perubahan spasi tidak terlihat secara visual pada rasio deviasi yang dikonfigurasi.
  4. Ketika kompatibilitas PDF/A diperlukan, validasi keluaran terhadap profil PDF/A Anda dan konfirmasikan toleransi lebar tidak terpicu.
  • Enkripsi terautentikasi. Payload dienkripsi dengan AES-256-GCM atau ChaCha20-Poly1305. Carrier yang dirusak atau terpotong gagal autentikasi saat dekripsi; ia tidak menghasilkan payload yang salah.
  • IV per-enkripsi. Sebuah IV 12-byte acak yang segar dihasilkan untuk setiap enkripsi, memenuhi persyaratan keunikan AES-GCM sesuai NIST SP 800-38D §5.2.1.
  • Kunci turunan. Kunci enkripsi diturunkan dengan HKDF-SHA-256 dari rahasia Anda dan kunci font (RFC 5869 §2). Simpan rahasia di secret manager Anda; perlakukan seperti secret penandatanganan mana pun.
  • Penanda adalah konten dokumen. Byte yang tersemat adalah bagian dari konten halaman, bukan konten log. Jangan menulis payload atau kunci rahasia ke log.

Halaman ini menyangkut penyematan kriptografis. Setiap sumber normatif diparafrasakan; tidak ada teks normatif yang direproduksi. ### Pengungkapan ketahanan

Penanda dibawa dalam penyesuaian kerning. Ia mungkin hancur oleh pencetakan dan pemindaian ulang, oleh alat konversi PDF, oleh re-linearisasi, atau oleh penulisan-ulang content-stream apa pun yang menormalkan kerning. Teknik ini paling cocok untuk pelacakan kebocoran internal dokumen yang didistribusikan dalam bentuk hasil-pembuatannya. Ini bukan steganografi adversarial dan tidak bertahan melalui pemrosesan downstream sembarang. Jangan mengandalkannya sebagai satu-satunya kontrol di mana model ancaman mencakup pelucutan yang disengaja.

  • Payload terlalu besar. Encoder memunculkan error overflow bertipe ketika payload melampaui kapasitas teks. Perpendek payload atau perpanjang teks carrier.
  • Teks carrier terlalu sedikit. Teks yang lebih pendek dari dua karakter tidak menawarkan posisi carrier dan memunculkan error.
  • Kunci salah saat decode. Decoding mengembalikan null. Perlakukan null sebagai “tidak ada penanda yang dipulihkan”, bukan sebagai hasil parsial.
  • Ketidakcocokan konfigurasi. Encoding dan decoding harus memakai bit depth, rasio deviasi, cipher, dan flag PDF/A yang sama; ketidakcocokan menghasilkan tidak ada payload yang dipulihkan.

Halaman ini mendokumentasikan hanya perilaku yang dapat diamati secara eksternal dan permukaan public API yang didukung. Jalur namespace internal, kelas helper, tabel mekanisme, nama file runbook, dan prefix tiket berada di luar cakupan.