PAdES PDF Signer
On this page
- Sekilas
- Yang dikerjakannya
- A. Menandatangani PDF dengan stempel yang terlihat
- B. Menanamkan bukti bahwa tanda tangan itu sah
- C. Menyegel hasilnya dengan stempel waktu
- D. Memverifikasi PDF bertanda tangan
- E. Menjauhkan rahasia penanda tangan dari setiap antrean dan log
- Antarmuka
- Standar
- Di dalamnya
- Keputusan rancangan
- Spesifikasi
- Terkait
- Istilah
PAdES PDF Signer adalah service Python yang membubuhkan tanda tangan yang terlihat dan bermakna hukum pada PDF, dan memastikan tanda tangan itu masih bisa diverifikasi lama setelah semua sertifikat di belakangnya kedaluwarsa. Ia menandatangani sampai PAdES B-LTA — level arsip jangka panjang dari standar Eropa untuk tanda tangan PDF — sehingga dokumen membawa stempel waktunya sendiri, buktinya sendiri bahwa tak ada sertifikat di rantainya yang dicabut, dan stempel waktu arsip yang menaungi semuanya. Ia juga memverifikasi PDF dan melaporkan setiap tanda tangan di dalamnya.
Saya membangunnya karena tanda tangan yang hanya bisa dikonfirmasi lewat jaringan yang hidup adalah tanda tangan bertanggal kedaluwarsa. Pembaca yang membuka kontrak sepuluh tahun lagi bisa saja mendapati responder certificate authority sudah tiada dan sertifikat penanda tangan lama kedaluwarsa; tanda tangan itu tetap harus membuktikan siapa yang menandatangani, kapan, dan bahwa ia sah pada saat itu. Menaruh setiap keping bukti itu di dalam PDF adalah seluruh pekerjaan service ini.
Sekilas
| Bahasa & framework | Python, dengan FastAPI, pyHanko untuk tanda tangan PDF, dan aiohttp untuk transfer |
|---|---|
| Arsitektur | Transaction Script Service |
| Versi | 2.11.3 |
| Status | Stabil, berjalan di production |
| Bentuk | Service HTTP tanpa state, dikirim sebagai satu executable, dipanggil oleh aplikasi penanda tangan |
| Kode sumber | Privat |
Yang dikerjakannya
A. Menandatangani PDF dengan stempel yang terlihat
Service menerima PDF dan gambar stempel — sering kali QR code — menempatkan stempel di satu kotak pada halaman pilihan, lalu menandatangani dokumen dengan sertifikat milik penanda tangan sendiri. Tiap tanda tangan menjadi field baru dengan id unik, sehingga satu dokumen bisa ditandatangani beberapa orang secara bergantian tanpa mengusik tanda tangan sebelumnya.
B. Menanamkan bukti bahwa tanda tangan itu sah
Saat penandatanganan, service mengumpulkan setiap sertifikat di rantai beserta jawaban pencabutan yang menunjukkan tak satu pun dicabut, lalu menyimpannya di dalam PDF. Validator bertahun-tahun kemudian tak butuh jaringan untuk tahu bahwa tanda tangan itu baik saat dibuat.
C. Menyegel hasilnya dengan stempel waktu
Tanda tangannya sendiri distempel waktu oleh timestamp authority, yang membuktikan kapan ia dibuat; lalu document timestamp ditambahkan atas seluruh file, termasuk data validasinya. Stempel waktu arsip itulah yang membuat tanda tangan bisa hidup lebih lama dari algoritma dan sertifikat yang menopangnya.
D. Memverifikasi PDF bertanda tangan
Diberi PDF apa pun, service melaporkan setiap tanda tangan dan document timestamp di dalamnya: sah atau tidak, siapa yang menandatangani, kapan, untuk apa dan di mana, seberapa banyak dokumen berubah sesudahnya, dan apakah data validasi jangka panjangnya ada.
E. Menjauhkan rahasia penanda tangan dari setiap antrean dan log
Tak ada yang di hulu — antrean, job, log — yang pernah memegang passphrase penanda tangan dalam teks polos, dan passphrase itu hanya melayani satu tanda tangan yang menjadi alasan ia diberikan.
Antarmuka
| Kemampuan | Kegunaan |
|---|---|
| Tanda tangani | menandatangani PDF di balik satu presigned link sampai PAdES B-LTA dengan stempel yang terlihat, lalu meng-upload hasilnya ke link lain; mengembalikan id tanda tangan dan SHA-256 file yang ditandatangani |
| Verifikasi | melaporkan setiap tanda tangan dan document timestamp di PDF yang di-upload |
| Readiness | memeriksa certificate authority, timestamp authority, dan storage secara paralel, lalu menyebut mana yang gagal |
Request penandatanganan menyebut dokumennya, stempelnya, halaman dan kotak tempat stempel diletakkan, alasan dan lokasinya, serta ke mana hasilnya ditulis.
Standar
| Standar | Yang dijaminnya di sini |
|---|---|
| PAdES B-LTA (ETSI EN 319 142) | tanda tangan yang tetap bisa diverifikasi setelah sertifikatnya kedaluwarsa, diperiksa dengan ETSI conformance checker |
| Tanda tangan CMS di PDF (ISO 32000) | tanda tangan ditambahkan sebagai incremental update, sehingga tanda tangan sebelumnya tetap utuh |
| RFC 3161, Time-Stamp Protocol | stempel waktu tanda tangan dan stempel waktu arsip dari otoritas terpercaya |
| RFC 5280 dan RFC 6960 | daftar pencabutan dan jawaban OCSP dikumpulkan saat penandatanganan dan disimpan di dokumen |
| PKCS#12 | key dan rantai penanda tangan diterima sebagai satu bundel terlindung |
| W3C Trace Context dan OpenTelemetry | penandatanganan, stempel waktu, dan pengambilan sertifikat tampil sebagai langkah di trace pemanggil |
Di dalamnya
Service ini berbentuk Transaction Script Service: tiap endpoint adalah satu prosedur yang terbaca, berurutan, setiap langkah satu request — periksa pemanggil, buka key penanda tangan, ambil dokumen dan stempel, susun konteks validasi, tanda tangani, upload, catat — dan kerja tiap langkah tinggal di module yang dinamai menurut urusannya: persiapan, penandatanganan, trust, fetcher, verifikasi, kriptografi, telemetry. Ia dibundel menjadi satu executable, jadi container-nya tak membawa source code.
Keputusan rancangan
Level arsip adalah tujuannya, dan saya dua kali berganti bahasa untuk mencapainya. Versi pertama, dalam Python, sampai pada titik ketika pembaca PDF yang banyak dipakai menerima validasi jangka panjangnya, lalu tersendat di jalan menuju standar lengkapnya. Yakin bahwa jalan buntunya ada di tooling Python, saya memindahkan signer ke Node.js, dan di sana jumlah error di conformance checker turun dari tiga menjadi satu. Lalu batasnya terlihat: library Node.js hanya bisa menanamkan validasi jangka panjang dalam gaya Adobe yang lebih lama, bukan dalam struktur PAdES yang diwajibkan standar. Saya kembali ke Python dengan bekal pelajaran dari jalan memutar itu tentang cara data validasi harus dikumpulkan, dan versi berikutnya menandatangani sampai PAdES B-LTA penuh dengan nol error di laporan ETSI conformance checker.
Setiap keping bukti dikumpulkan sebelum menandatangani, tak diharapkan muncul belakangan. Dua kali validasi gagal saat penandatanganan karena jawaban pencabutan "terlalu baru" — lebih baru dari momen yang dipakai validator sebagai patokan. Perbaikan pertama: daftar pencabutan milik root, CA penanda tangan, dan timestamp authority diambil paralel sebelum menandatangani dan langsung diberikan ke konteks validasi; perbaikan kedua: toleransi kecil untuk selisih jam antar-service. Pemeriksaan pencabutan diatur wajib mendapat jawaban, jadi tak pernah ada tanda tangan yang ditanamkan dengan celah di buktinya. Sertifikat root tak dimasukkan ke dokumen, karena validator harus sudah memercayainya, bukan menerimanya dari file yang sedang dinilainya.
Tanda tangan menambah dokumen, tak pernah menulis ulang. Tiap tanda tangan ditulis sebagai incremental update, sehingga tanda tangan sebelumnya beserta perlindungannya tetap sama byte demi byte, dan satu dokumen bisa mengumpulkan tanda tangan dari beberapa orang. Writer-nya juga menerima PDF dengan tabel cross-reference campuran, jadi dokumen dari beragam tool bisa ditandatangani. Tiap tanda tangan mendapat field baru bernama UUIDv7 miliknya, dan nama itu sekaligus menjadi id tanda tangan yang dikembalikan ke pemanggil, sehingga catatan dan PDF selalu menunjuk tanda tangan yang sama. Stempel digambar tanpa border, supaya QR code tak berbingkai dua kali, dan kotaknya boleh dimulai dari nol, supaya bisa menempel rapat ke tepi halaman.
Rahasia penanda tangan tak pernah tersimpan di mana pun sepanjang jalan. Passphrase tetap terenkripsi sejak aplikasi memasukkan job ke antrean, jadi ia tak pernah mengendap di payload job atau log aktivitas. Service tak punya akses tetap miliknya sendiri ke certificate authority: otoritas itulah yang memutuskan, untuk tiap request dan tiap pemanggil, apakah key ini boleh dipakai, dan apa pun yang ditangani service demi satu tanda tangan tak bertahan lebih lama dari tanda tangan itu.
File berpindah lewat link, dan hanya ke storage yang dikenal service. Dokumen, stempel, dan tujuannya semuanya presigned link, jadi aplikasi tak pernah mengalirkan PDF melewati dirinya. Tiap link harus menunjuk persis origin storage dan bucket yang diharapkan — allowlist yang disimpan di source, bukan di konfigurasi — dan selain itu ditolak sebelum satu byte pun diambil. Respons membawa SHA-256 file yang ditandatangani, sehingga aplikasi bisa menemukan dokumen dari hash-nya.
Verifikasi ketat lebih dulu, dan menilai tiap tanda tangan pada momennya sendiri. Verifier mula-mula memeriksa bahwa yang di-upload memang PDF — header dan penanda akhirnya — dan menjawab file palsu dengan error client yang jelas, bukan kegagalan server. Tiap tanda tangan lalu divalidasi online secara ketat; bila gagal karena dunia sudah berubah sejak penandatanganan, ia dinilai ulang secara offline pada waktu penandatanganannya sendiri, dari data validasi yang tertanam di dokumen — persis bukti yang dijaga oleh level arsip. Trust root dibaca dari direktori yang di-mount, jadi memercayai root baru adalah perubahan deployment, bukan perubahan kode.
Telemetry harus dibuat layak dipercaya sebelum bisa dipercaya. Logging pindah dari menulis langsung ke Elasticsearch menjadi OpenTelemetry lewat collector, melanjutkan trace dari aplikasi yang memanggil service lalu meneruskannya ke timestamp authority dan certificate authority, sehingga satu tanda tangan tampil sebagai satu trace lintas empat service. Redaksi memeriksa nilai, bukan hanya nama field, jadi signature presigned link tak pernah sampai ke log apa pun nama field-nya. Tiga insiden membentuk sisanya. Kegagalan nyaris tak terlihat — 492 span tapi hanya 14 catatan log dalam setengah jam — jadi setiap request yang ditolak atau gagal kini melewati satu handler yang mencatatnya, dengan field alasan yang dijaga tetap string karena indeks pencarian sudah mengunci tipe field itu. Readiness probe menghasilkan 99,8 persen dari semua span, jadi ia dikeluarkan dari tracing. Dan di dalam executable hasil bundel, dua instrumentor mematikan dirinya diam-diam karena bundel itu tak membawa metadata paket yang mereka periksa; build kini menyalin metadata itu, dan pengambilan data pencabutan kembali tampil di trace. Metrics memakai delta temporality, yang diwajibkan exporter Elasticsearch milik collector.
Readiness memeriksa apa yang benar-benar dibutuhkan penandatanganan. Service baru siap bila root CA, CA penanda tangan, timestamp authority, dan storage semuanya menjawab, diperiksa paralel, dan jawaban belum siap menyebut mana yang gagal. Probe-nya langsung ke tiap service, bukan lewat proxy publik, sehingga tiap dependensi diukur di tempat ia sungguh berjalan.
Spesifikasi
| Masukan | Presigned link ke PDF, gambar stempel, dan tujuan; sertifikat penanda tangan dan passphrase-nya yang terlindungi; halaman, kotak, alasan, dan lokasi |
|---|---|
| Hasil | PDF bertanda tangan PAdES B-LTA yang di-upload ke tujuan; id tanda tangan dan SHA-256 untuk pemanggil; untuk verifikasi, laporan per tanda tangan |
| Tanda tangan | CMS di PDF, SHA-256, incremental update, stempel yang terlihat, stempel waktu tanda tangan dan arsip, sertifikat dan data pencabutan yang tertanam |
| Bergantung pada | CA penanda tangan untuk key penanda tangan dan data pencabutan, root CA, timestamp authority, dan storage kompatibel S3 |
| Diverifikasi dengan | ETSI conformance checker dan pembaca PDF yang banyak dipakai |
| Observability | Trace, log, dan metrics OpenTelemetry lewat OTLP |
| Berjalan sebagai | Satu executable yang dibangun di image container multi-stage, dengan konfigurasi dan trust root di-mount |
Terkait
Certificate authority yang memegang key setiap penanda tangan dan menjawab pertanyaan pencabutan yang tertanam di setiap tanda tangan.
Timestamp authority yang memberi tanggal setiap tanda tangan dan menyegel arsipnya.
Service storage yang menerbitkan link tempat dokumen, stempel, dan hasil tanda tangan berpindah.
Ke mana trace satu tanda tangan yang melintasi empat service berakhir.
Istilah
- PAdES
- PDF Advanced Electronic Signatures: standar Eropa untuk tanda tangan digital di PDF, dirumuskan dalam level dari dasar sampai arsip jangka panjang.
- B-LTA
- Level arsip jangka panjang PAdES: tanda tangan dengan stempel waktu, data validasi yang tertanam, dan stempel waktu arsip atas seluruh dokumen.
- Long-term validation
- Menanamkan sertifikat dan jawaban pencabutan yang akan dibutuhkan validator, supaya tanda tangan bisa diperiksa tanpa menghubungi siapa pun.
- Document timestamp
- Stempel waktu yang dikenakan pada seluruh PDF, bukan pada satu tanda tangan, dan melindungi semua yang ditambahkan sebelumnya.
- Incremental update
- Menambahkan perubahan di akhir PDF tanpa menulis ulang, sehingga isi dan tanda tangan sebelumnya tetap persis seperti semula.
- PKCS#12
- Format file yang membundel private key dengan sertifikat dan rantainya, dilindungi password.
Technologies covered
- Python
- FastAPI
- pyHanko
- OpenTelemetry
- OCSP
- PAdES