Lewati ke konten

Bagaimana tanda tangan berada di dalam PDF

Spec: ETSI EN 319 142-1 Spec: RFC 5652 Evidence: Standard-backed

Tanda tangan PDF tidak membungkus berkas dari luar. Tanda tangan itu berada di dalam berkas: sebuah kamus yang menamai tanda tangan, serta digest yang dihitung atas rentang byte yang dideklarasikan dan sengaja mengecualikan nilai tanda tangan itu sendiri. Halaman ini menjelaskan mekanisme tersebut dan, yang sama pentingnya, batas hal yang tidak dijanjikannya.

“Dokumen ini telah ditandatangani” adalah kalimat yang dipakai orang untuk mengambil keputusan. Mereka mengaitkannya dengan pembayaran, persetujuan, atau kewajiban hukum. Jika Anda tidak tahu persis byte mana yang dicakup oleh suatu tanda tangan, Anda tidak dapat menyatakan apa yang sebenarnya dibuktikan oleh hasil yang valid. Sebuah PDF dapat membawa tanda tangan yang sepenuhnya valid, tetapi tetap menampilkan konten kepada pembaca yang tidak pernah dilihat oleh penanda tangan, karena konten itu ditambahkan setelah penandatanganan, di wilayah yang tidak pernah diklaim oleh tanda tangan tersebut. Memahami di mana otoritas tanda tangan dimulai dan berakhir adalah perbedaan antara keputusan yang dapat dipertanggungjawabkan dan keputusan yang hanya berdasar harapan.

  • Tanda tangan PDF berada dalam sebuah kamus tanda tangan dan sebuah bidang tanda tangan di dalam dokumen, bukan sebagai amplop eksternal.
  • Byte yang ditandatangani dideklarasikan oleh sebuah larik ByteRange: dua segmen (offset, length) yang bersama-sama mencakup seluruh berkas kecuali nilai tanda tangan heksadesimal yang disimpan pada entri Contents.
  • Digest dari kedua segmen yang digabungkan itulah yang sebenarnya dilindungi oleh tanda tangan kriptografis.
  • Apa pun yang kemudian ditambahkan dalam revisi baru berada di luar byte-range asli. Tanda tangan asli tetap valid; ia tidak pernah membuat klaim apa pun atas byte yang baru.
  • Tanda tangan persetujuan dan tanda tangan sertifikasi berbeda cakupannya: sertifikasi (DocMDP) membatasi perubahan apa yang boleh dilakukan kemudian; persetujuan tidak.

NextPDF membangun tanda tangan sesuai dengan model format tersebut, dalam urutan yang tetap, sehingga byte-range presisi dan bukan perkiraan.

Saat mesin menulis tanda tangan, ia terlebih dahulu menyediakan slot berukuran tetap untuk nilai Contents dan menulis sebuah penampung (placeholder) ByteRange berlebar tetap. Mesin menunggu hingga seluruh dokumen selesai ditulis, termasuk tabel rujukan-silang dan penanda akhir-berkas. Baru setelah itu mesin menghitung kedua offset yang sebenarnya, menuliskannya kembali ke dalam penampung tanpa menggeser satu byte pun, menghitung hash kedua segmen tersebut, lalu menempatkan objek CMS yang dihasilkan ke dalam slot yang telah disediakan. Penampung diisi nol (zero-padded) hingga panjang yang konstan agar pengisian angka yang sebenarnya tidak menggeser byte yang sedang di-hash. Ini adalah satu-satunya urutan yang menghasilkan tanda tangan yang konsisten dengan dirinya sendiri. Mesin memperlakukan kegagalan apa pun dalam urutan ini sebagai galat keras, bukan fallback yang diam-diam.

Untuk profil PDF 2.0, objek tanda tangan itu sendiri adalah struktur CMS SignedData yang terlepas (detached). Kamus PDF menyatakan di mana dan bagaimana; objek CMS membawa siapa dan bukti kriptografisnya.

  1. Step 1 of 4: ISO 32000-2 §12.8.1 — ByteRange digest & signature dictionary
  2. Step 2 of 4: ISO 32000-2 §12.8.3.3 — ETSI.CAdES.detached SubFilter
  3. Step 3 of 4: ETSI EN 319 142-1 PAdES baseline profile
  4. Step 4 of 4: RFC 5652 CMS SignedData in Contents
Di mana tanda tangan PDF didefinisikan, dari format kontainer hingga objek kriptografis: ISO 32000-2 menetapkan kamus dan mekanisme byte-range, ETSI EN 319 142-1 memprofilkannya untuk PAdES, dan RFC 5652 mendefinisikan objek CMS SignedData yang ditempatkan dalam Contents.

Evidence: Standard-backed Mekanisme ini didefinisikan oleh Spec: ISO 32000-2, §12.8.1 . Sebuah digest byte-range dihitung dari rentang byte yang ditunjukkan oleh entri ByteRange. Rentang itu seharusnya mencakup seluruh berkas termasuk kamus tanda tangan namun tidak termasuk nilai tanda tangan — entri Contents. ByteRange adalah sebuah larik berisi pasangan bilangan bulat: offset awal dan panjang. Rentang yang tidak bersambungan digunakan khusus agar digest dapat mengecualikan nilai tanda tangan itu sendiri.

Untuk profil PDF 2.0, Spec: ISO 32000-2, §12.8.3.3 menetapkan bahwa ketika SubFilter bernilai ETSI.CAdES.detached, nilai Contents adalah objek CMS SignedData berenkode DER — struktur yang sama Spec: RFC 5652 mendefinisikannya — dan profil PAdES dari objek tersebut adalah profil yang diuraikan oleh Spec: ETSI EN 319 142-1 .

Cakupan berbeda di antara berbagai tanda tangan. Spec: ISO 32000-2, §12.7.4.5 mendefinisikan izin MDP: nilai 0 menjadikan tanda tangan sebagai tanda tangan persetujuan, sedangkan nilai 13 menjadikannya tanda tangan sertifikasi yang membatasi modifikasi berikutnya yang tetap menjaga dokumen konforman. Mekanisme byte-range yang sama; janji yang berbeda tentang masa depan.

Mesin NextPDF menerapkan persis hal ini: penampung ByteRange berlebar tetap, digest gabungan dua segmen, dan objek CMS terlepas (detached) dalam slot Contents yang disediakan, yang difinalisasi hanya setelah berkas selesai.

Anda jarang membangun ByteRange secara manual. Tujuan contoh ini adalah menunjukkan bentuk hasilnya agar Anda dapat mengenalinya saat memeriksa berkas yang ditandatangani.

<?php
declare(strict_types=1);
use NextPDF\Security\Signature\ByteRangeCalculator;
// Offsets the engine knows only after the whole PDF is written:
// $contentsStart — byte just before the '<' of the hex signature
// $contentsEnd — byte just after the '>' that closes it
// $fileLength — total file size in bytes
$range = ByteRangeCalculator::calculate(
contentsStart: $contentsStart,
contentsEnd: $contentsEnd,
fileLength: $fileLength,
);
// $range === [0, $contentsStart, $contentsEnd, $fileLength - $contentsEnd]
// Segment 1: file start → just before the signature value
// Segment 2: just after the signature value → end of file
// The signature value itself is the gap. It is never hashed.
$signedMessage = ByteRangeCalculator::extractSignedData($pdfBytes, $range);
// $signedMessage is segment 1 concatenated with segment 2 — exactly the
// bytes the cryptographic digest is computed over.

Celah di antara kedua segmen tersebut adalah nilai tanda tangan. Nilai itu tidak dapat menjadi bagian dari digest-nya sendiri; karena itu rentangnya terdiri dari dua bagian, bukan satu.

Jebakannya adalah meyakini bahwa tanda tangan yang valid berarti seluruh berkas yang sedang Anda lihat itulah yang ditandatangani. Ternyata tidak. Artinya, byte di dalam rentang yang dideklarasikan masih utuh. Revisi berikutnya dapat secara sah menambahkan konten — tanda tangan kedua, data formulir, materi validasi — di luar rentang itu. Tanda tangan pertama tetap valid, dan ia tidak menyatakan apa pun tentang penambahan tersebut. Penampil yang benar memberi tahu Anda bahwa tanda tangan mencakup “dokumen sebagaimana adanya pada saat penandatanganan,” bukan “setiap byte di layar.” Menyamakan keduanya membuat sebuah dokumen yang ditandatangani memperoleh konten tak bertanda tangan yang tampak seolah-olah ditandatangani.

Halaman ini menjelaskan struktur, bukan kepercayaan. Objek ByteRange dan CMS yang terbentuk dengan benar memberi tahu Anda bahwa byte masih utuh dan kunci mana yang menandatanganinya. Keduanya, dengan sendirinya, tidak memberi tahu Anda apakah kunci itu milik orang yang Anda maksud, apakah sertifikatnya valid pada saat penandatanganan, atau apakah sertifikat itu kemudian dicabut. Itu adalah pekerjaan jalur sertifikat dan pencabutan, yang dibahas dalam Memvalidasi tanda tangan dengan benar. Halaman ini juga tidak membahas kapan penandatanganan terjadi dengan otoritas independen mana pun. Waktu penandatanganan yang dinyatakan sendiri bukanlah waktu terpercaya — lihat Stempel waktu dan waktu terpercaya. NextPDF membangun struktur yang diuraikan di sini; sertifikat, jangkar kepercayaan (trust anchor), dan otoritas stempel waktu disediakan oleh implementasi Anda, bukan oleh mesin.

Yang disediakan mesin per tingkatan (tier) adalah kemampuan membangun struktur:

PAdES signature structure (byte range, signature dictionary, detached CMS) — edition availability
Edition Availability
Core

PAdES B-B: kamus tanda tangan, ByteRange berlebar tetap, dan objek CMS SignedData terlepas (detached) yang diuraikan di halaman ini.

Pro

Menambahkan PAdES B-T — stempel waktu terpercaya pada nilai tanda tangan — di atas struktur yang sama.

Enterprise

Menambahkan profil jangka panjang (B-LT, B-LTA): materi validasi tertanam dan stempel waktu dokumen yang dilapiskan di atas fondasi byte-range yang sama.

  • Kamus tanda tangan — kamus PDF yang menamai handler tanda tangan, SubFilter, ByteRange, dan nilai Contents.
  • ByteRange — sebuah larik berisi pasangan bilangan bulat (offset, length) yang mendeklarasikan persis byte yang dicakup oleh digest tanda tangan.
  • Contents — entri heksadesimal yang menyimpan nilai tanda tangan (untuk PDF 2.0, sebuah objek CMS SignedData terlepas); ia dikecualikan dari digest-nya sendiri.
  • CMS SignedData — struktur Cryptographic Message Syntax (RFC 5652) yang membawa sertifikat penanda tangan dan byte tanda tangan.
  • PAdES — PDF Advanced Electronic Signatures: profil ETSI untuk tanda tangan CMS dalam PDF, yang didefinisikan dalam seri ETSI EN 319 142.
  • Tanda tangan persetujuan — tanda tangan dengan izin MDP bernilai 0; ia menegaskan konten tanpa membatasi perubahan berikutnya.
  • Tanda tangan sertifikasi — tanda tangan dengan izin DocMDP (MDP 13) yang membatasi modifikasi berikutnya yang tetap menjaga dokumen konforman.