HotPDF memverifikasi tanda tangan CMS ML-DSA-44, ML-DSA-65, ML-DSA-87, Ed25519 dan Ed448 pada dokumen PDF yang dimuat, dan menandatangani melalui provider pluggable sehingga private key tidak pernah harus hidup di dalam proses Delphi Anda. Bagian kedua itulah yang paling dibutuhkan tim lebih dulu. Token perangkat keras, layanan penandatanganan remote, dan kartu eID nasional semuanya menolak menyerahkan kunci, dan sampai pipeline penandatanganan dipisahkan dari key store, tidak satu pun dari itu dapat digunakan sama sekali
Pemisahan itu adalah inti dari THPDFSignatureProvider. HotPDF mempertahankan bagian yang seharusnya dimilikinya — mem-parsing CMS, membangun SignedData, menata /ByteRange — dan mendelegasikan satu operasi yang tidak dapat dimilikinya, yaitu mengubah digest menjadi tanda tangan dengan kunci yang tidak diperbolehkan dilihatnya. Semua di bawah ini mengikuti dari pembagian itu
Kenapa tanda tangan ML-DSA yang valid gagal diverifikasi?
Karena HotPDF menolak ML-DSA pada dokumen yang dimuat yang tidak mendeklarasikan ekstensi untuknya. ML-DSA — skema tanda tangan berbasis lattice yang distandardisasi sebagai FIPS 204, dan alasan orang mengatakan "PDF pasca-kuantum" — belum memiliki registrasi ISO 32000-2. PDF yang membawanya menggunakan algoritma yang tidak dinamai oleh standar dasar, dan file yang diam-diam menggunakan algoritma tanpa nama adalah file yang vonisnya tidak dapat direproduksi oleh orang lain
Jadi HotPDF membuat klaim itu eksplisit. EnsureMLDSAExtensions meningkatkan dokumen ke PDF 2.0 bila diizinkan dan menulis /Extensions /HotPDF << /BaseVersion /2.0 /ExtensionLevel 1 >> ke dalam Catalog. Di sisi pembacaan, LoadedDocumentDeclaresMLDSAExtension melaporkan apakah deklarasi itu bertahan, dan VerifyLoadedSignatureWithOptions menerapkan pengujian yang sama sebelum akan menghormati Options.AllowMLDSA. Setel flag pada dokumen yang tidak dideklarasikan dan ia tetap mati — opsi dapat melonggarkan kebijakan, tidak pernah persyaratan struktural
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'contract-pq.pdf';
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 720, 0, 'Supply agreement 2026-114');
Pdf.EnsureMLDSAExtensions; // declare before the signature is written
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Panggil sebelum menyimpan, bukan setelah. Deklarasi adalah bagian dari byte range yang ditandatangani, dan Catalog yang ditambal setelahnya entah perubahan tidak bertanda tangan pada file yang ditandatangani atau revisi kedua yang akan dilaporkan validator sebagai modifikasi
Tiga keluarga algoritma, satu titik masuk verifikasi
Ketiga keluarga datang melalui VerifyLoadedSignatureWithOptions, yang mengambil indeks tanda tangan, stream sumber, record THPDFCMSVerifyOptions dan parameter out untuk detail tanda tangan. Record itu memiliki tepat tiga field, dan masing-masing menjawab pertanyaan yang dulu membutuhkan rebuild
SignatureProvider menggantikan provider built-in platform dengan provider Anda sendiri. OpenSSLLibraryPath memilih library OpenSSL 3, yang menyediakan verifikasi Ed25519 dan Ed448 pure-mode yang tidak ditawarkan Windows CNG di semua tempat. AllowMLDSA ikut serta dalam algoritma lattice, tunduk pada pemeriksaan ekstensi di atas. OID algoritma persis yang dikenali kembali di THPDFSignatureInfo.SignatureAlgorithmOID, sehingga log audit dapat mencatat apa yang diverifikasi alih-alih apa yang diminta
var
Opts: THPDFCMSVerifyOptions;
Info: THPDFSignatureInfo;
Status: THPDFSignatureVerifyStatus;
Src: TFileStream;
begin
Opts := THPDFCMSVerifyOptions.Default;
Opts.OpenSSLLibraryPath := 'C:\openssl3\libcrypto-3-x64.dll';
Opts.AllowMLDSA := Pdf.LoadedDocumentDeclaresMLDSAExtension;
Src := TFileStream.Create('contract-pq.pdf', fmOpenRead or fmShareDenyWrite);
try
Status := Pdf.VerifyLoadedSignatureWithOptions(0, Src, Opts, Info);
if Status = svValid then
Memo1.Lines.Add('signed with OID ' + string(Info.SignatureAlgorithmOID));
finally
Src.Free;
end;
end;
Ed25519 dan Ed448 tidak memerlukan deklarasi ekstensi, karena ISO 32000-2 sudah mengakuinya. Keduanya memerlukan provider yang mengimplementasikannya, yang pada sebagian besar deployment Windows berarti menunjuk OpenSSLLibraryPath ke library yang Anda kirimkan dan kendalikan alih-alih apa pun yang kebetulan ada di mesin
Apa yang sebenarnya dijanjikan oleh provider penandatanganan?
Provider berjanji satu hal: diberikan request, kembalikan status dan, ketika menandatangani, byte. THPDFSignatureProviderRequest membawa algoritma dan OID-nya, OID digest, panjang salt PSS, apakah input adalah pesan atau digest yang sudah dihitung, input itu sendiri, kunci publik atau sertifikat, pengenal kunci dan pengenal operasi. Tidak ada apa pun di record itu yang spesifik HotPDF — itu adalah kosakata yang sudah dituturkan oleh driver token atau layanan penandatanganan
Tiga implementasi dikirim dengan library. THPDFCallbackSignatureProvider membungkus anonymous method, yang merupakan jalur terpendek dari rutin penandatanganan in-house yang ada menjadi tanda tangan PDF yang berfungsi. THPDFRemoteSignatureProvider membungkus callback transport dengan batas retry, registri pembatalan dan batas pada ukuran input dan tanda tangan, sehingga HSM yang menggantung tidak bisa menjadi aplikasi yang menggantung. THPDFPKCS11SignatureProvider menserialisasikan operasi RSA terhadap sesi PKCS#11 milik pemanggil yang sudah terautentikasi dan handle private-key — HotPDF tidak pernah login, tidak pernah melihat PIN, dan tidak pernah menutup sesi yang tidak dibukanya
var
Provider: THPDFRemoteSignatureProvider;
begin
Provider := THPDFRemoteSignatureProvider.Create(
function(const Req: THPDFSignatureProviderRequest; Attempt: Integer;
out Signature: TBytes): THPDFSignatureProviderStatus
begin
// POST Req.Input to the signing service; Req.KeyIdentifier selects the key
if PostToSigningService(Req.KeyIdentifier, Req.Input, Signature) then
Result := spsValid
else
Result := spsProviderError;
end,
3, // RetryLimit
1048576, // MaxInputBytes
65536); // MaxSignatureBytes
try
// hand Provider to the signing call
finally
Provider.Free;
end;
end;
Kenapa enum status memiliki enam nilai alih-alih boolean
THPDFSignatureProviderStatus membedakan spsValid, spsInvalid, spsUnsupported, spsMalformed, spsProviderError dan spsCancelled, dan menggabungkannya membuat Anda kehilangan kemampuan untuk bertindak dengan benar. Tanda tangan yang secara kriptografis salah (spsInvalid) adalah peristiwa keamanan. Algoritma yang tidak diimplementasikan provider (spsUnsupported) adalah celah deployment. Kegagalan transport (spsProviderError) layak dicoba ulang, dan prompt token yang dibatalkan pengguna (spsCancelled) tidak layak dicoba ulang sama sekali
Aturan untuk penandatanganan sempit: provider penandatanganan mengembalikan spsValid hanya dengan tanda tangan tidak kosong. Provider verifikasi mengembalikan spsValid atau spsInvalid, dan empat lainnya tetap berbeda di kedua jalur. Jika Anda menulis provider, tahan godaan untuk memetakan semua yang tidak Anda kenali ke spsInvalid — itu mengubah DLL yang hilang menjadi laporan bahwa tanda tangan pelanggan dipalsukan
Di mana tanda tangan benar-benar mendarat di file
Dua fungsi menghubungkan provider ke byte PDF nyata. HPDFCMSBuildSignedDataWithProvider membangun detached CMS dari digest SHA-256 dokumen, yang merupakan titik masuk yang tepat ketika workflow Anda menghitung digest di tempat lain. HPDFCMSSignPDFStreamWithProvider menandatangani placeholder tanda tangan yang ada di stream PDF dan mempertahankan pipeline /ByteRange standar, yang merupakan titik masuk yang tepat ketika HotPDF sendiri menata placeholder itu
Mempertahankan pipeline itu lebih penting dari yang terdengar. Konvensi /ByteRange — dua rentang yang melewati jendela tanda tangan hex — adalah apa yang diperiksa validator pertama kali, dan jalur berbasis provider yang menulisnya ulang akan merusak kepatuhan PAdES betapa pun kuatnya kriptografi. HotPDF menjaga layout identik dengan jalur penandatanganan built-in, jadi dokumen yang ditandatangani melalui token PKCS#11 diverifikasi dengan kode verifikasi tanda tangan yang sama seperti yang ditandatangani dari file PFX. Untuk aturan profil yang berada di atas pilihan algoritma, lihat panduan tanda tangan baseline PAdES di Delphi, dan untuk jebakan encoding khusus ECDSA yang mendahului model provider ini, catatan tentang verifikasi CMS ECDSA dan format tanda tangan P1363
Urutan migrasi yang tidak meninggalkan dokumen Anda terdampar
Kesiapan pasca-kuantum adalah masalah jadwal, bukan sakelar. Hampir tidak ada viewer PDF yang dideploy yang memvalidasi ML-DSA hari ini, jadi dokumen yang ditandatangani dengannya saja, dari sudut pandang pembaca, adalah dokumen dengan tanda tangan yang tidak dapat diverifikasi. Urutan yang bertahan dari kontak dengan arsip nyata adalah: pertahankan RSA atau ECDSA sebagai tanda tangan yang akan dinilai validator, tambahkan deklarasi ekstensi dan tanda tangan ML-DSA kedua di mana kebijakan menuntut bukti tahan-kuantum, dan pindahkan tanda tangan utama hanya ketika sistem konsumen telah mengejar
Apa yang diberikan HotPDF kepada Anda hari ini adalah kemampuan untuk menulis dan memverifikasi keduanya, dari kode yang sama, dengan algoritma yang dicatat dengan jujur di file dan di hasil verifikasi. HotPDF adalah komponen PDF VCL native untuk Delphi dan C++Builder tanpa runtime PDF eksternal, jadi jalur penandatanganan dan verifikasi dikirim di dalam executable Anda alih-alih di sampingnya — lihat halaman komponen PDF Delphi HotPDF untuk daftar fitur lengkap dan unduhan trial