ข้ามไปยังเนื้อหา
getnextpdf.com

การลงนามในระดับขนาดใหญ่ โดยไม่ลดทอน

Spec: ISO 32000-2, §12.8Spec: ETSI EN 319 142-1Spec: RFC 5652, §5.1

การลงนามเอกสารหนึ่งฉบับเป็นการดำเนินการเชิงวิทยาการรหัสลับ การลงนามหนึ่งแสนฉบับภายใต้เส้นตายคือการดำเนินการเดียวกันที่ทำซ้ำ ซึ่งความล้มเหลวที่อันตรายไม่ได้อยู่ที่ “มันช้า” อีกต่อไป แต่อยู่ที่ “หนึ่งในนั้นออกไปโดยไม่ได้ลงนามและไม่มีใครสังเกตเห็น” หน้านี้ว่าด้วยการทำสิ่งที่สองโดยไม่ละทิ้งสิ่งแรก: การลงนามแบบจำนวนมากและพร้อมกันที่ทุกลายเซ็นยังคงถูกต้อง การรันปฏิเสธที่จะ emit ไฟล์ที่มันลงนามไม่ได้ และงานขนาดใหญ่ทำงานต่อจากเดิมแทนที่จะเริ่มใหม่ทั้งหมด

ลายเซ็นเป็นข้อเท็จจริงเฉพาะของแต่ละเอกสาร digest ของมันถูกคำนวณบนช่วงไบต์ที่ประกาศไว้ซึ่งไม่รวมค่าลายเซ็นเอง (Spec: ISO 32000-2, §12.8) ดังนั้นจึงไม่มีวิธีที่ซื่อตรงในการลงนามเอกสารหนึ่งพันฉบับ “แบบเป็น batch” ในคราวเดียว — แต่ละฉบับพกพา CMS SignedData ของตัวเองบนไบต์ของตัวเอง (Spec: RFC 5652, §5.1) ขนาดที่ใหญ่ขึ้นจึงเพิ่มโอกาสที่จะมีสิ่งหนึ่งสิ่งใดผิดพลาดไปอย่างเงียบๆพอดี: key handle ที่ล้มเหลวชั่วครู่ ผู้ออกการประทับเวลาที่หมดเวลา worker ที่ตายไปขณะถือไฟล์ที่เขียนค้างไว้

ผลลัพธ์ที่มีราคาแพงไม่ใช่การ crash การ crash นั้นเสียงดังและคุณก็ลองใหม่ได้ ผลลัพธ์ที่มีราคาแพงคือผลลัพธ์ แบบเงียบ — PDF ที่ไม่ได้ลงนามซึ่งดูเหมือนเสร็จสมบูรณ์นั่งอยู่ในที่จัดเก็บถาวร ถูกค้นพบหลายเดือนต่อมาโดย validator ของผู้ตรวจสอบ เมื่ออยู่ในปริมาณมาก “ลงนามแล้วเกือบหมด” แทบแยกไม่ออกจาก “ลงนามแล้ว” จนกระทั่งฉบับที่สำคัญถูกตรวจสอบ หัวใจทั้งหมดของการลงนามในระดับขนาดใหญ่คือการทำให้ผลลัพธ์นั้นเป็นไปไม่ได้เชิงโครงสร้าง ไม่ใช่เพียงเกิดขึ้นได้ยากในเชิงสถิติ

  • ทุกเอกสารถูกลงนามเป็นรายฉบับ บนช่วงไบต์ของตัวเอง Batch เป็นคำเชิงการจัดตาราง เวลา ไม่ใช่คำเชิงวิทยาการรหัสลับ ไม่มีลายเซ็นที่ใช้ร่วมกัน
  • ระดับเป็นสัญญา ไม่ใช่คำใบ้ คุณระบุชื่อระดับเบสไลน์ของ PAdES และเอนจินผลิต ระดับนั้นตรงตามนั้นให้ทุกเอกสาร หรือไม่ก็ทำให้เอกสารนั้นล้มเหลวอย่างเสียงดัง (Spec: ETSI EN 319 142-1)
  • ไปป์ไลน์เป็นแบบ fail-closed เอกสารที่ลงนามอย่างถูกต้องไม่ได้จะไม่ถูกส่งผ่าน ไปในรูปไบต์ดิบ แต่จะถูกกักไว้ ไม่ใช่ส่งต่อ
  • ความขนานเป็นรายเอกสาร และปลอดภัยโดยการออกแบบ หน่วยการลงนามไม่ใช้สถานะที่ เปลี่ยนแปลงได้ร่วมกัน worker สองตัวจึงไม่สามารถทำให้เอาต์พุตของกันและกันเสียหายได้
  • การรันขนาดใหญ่มีความคงทน เอาต์พุตที่ commit แล้วจะไม่ถูก emit ซ้ำเมื่อ ทำงานต่อ; การรันที่ crash จะดำเนินต่อจาก checkpoint ล่าสุดแทนที่จะลงนามทุกอย่าง ใหม่หมด

การออกแบบตั้งอยู่บนการแยกส่วนเพียงข้อเดียว: การผลิตลายเซ็นเป็นขั้นตอนเล็กๆแบบ deterministic ต่อเอกสาร; การรันมันนับพันครั้งอย่างปลอดภัยเป็นขั้นตอนของการ orchestration การแยกทั้งสองส่วนนี้ออกจากกันคือสิ่งที่ทำให้แต่ละส่วนยังคงเรียบง่าย

ขั้นตอนการลงนามคือขั้นตอนที่ต้องไม่มีวันลดทอน คุณร้องขอระดับหนึ่ง — กรณีของ enum SignatureLevel ไม่ใช่ string ที่เอนจินต้องตีความ — และระดับนั้นถูกปฏิบัติในฐานะสัญญาสำหรับ เอกสารนั้น เอนจินผลิตระดับที่ร้องขอหรือหยุดพร้อมข้อผิดพลาดที่ดำเนินการแก้ไขได้ มันจะไม่ลงนามในระดับต่ำกว่าอย่างเงียบๆแล้วปล่อยให้บันทึกอ้างว่าเป็นระดับที่สูงกว่า ความถูกต้องไม่ผ่อนคลายเพียงเพราะมีเอกสารตามมาอีกมาก ลายเซ็นฉบับที่หนึ่งแสนถูกคำนวณอย่างพิถีพิถันเท่ากับฉบับแรกทุกประการ

กฎ fail-closed คือสิ่งที่ทำให้สิ่งนั้นน่าเชื่อถือเมื่ออยู่ในปริมาณมาก เส้นทางการลงนามของ NextPDF ปฏิเสธที่จะ emit สิ่งประดิษฐ์ที่ดูเหมือนน่าเชื่อถือแต่ไม่ได้ลงนามแทนสิ่งที่คุณร้องขอ เส้นทางแอปพลิเคชันที่รองรับคือ Document API ระดับสูง: คุณกำหนดค่าลายเซ็นด้วย Document::setSignature() แล้วร้องขอไบต์ด้วย Document::getPdfData() (หรือ save() / output()) และการเขียนผ่านเดียวนั้นจะ emit PDF ที่ลงนามอย่างถูกต้อง หรือ throw ก่อน ที่จะส่งไบต์กลับมา — ไม่ใช่ไฟล์ที่ไม่ได้ลงนามซึ่งผู้เรียกเชื่อว่าลงนามแล้ว เมื่อนำไปใช้ทั่วทั้ง batch นี่คือกฎที่เปลี่ยน “หนึ่งฉบับหลุดออกไปโดยไม่ได้ลงนาม” จากข้อบกพร่องแฝงแบบเงียบ ให้กลายเป็นงานหนึ่งที่ล้มเหลวและลองใหม่ได้

  1. Warm the signing material onceOn worker boot, open the key/certificate source and the timestamp client. This cost is paid once per worker, not once per document.
  2. Enqueue the documentsA queue holds the per-document jobs. The queue is the throughput dial — signing workers scale horizontally behind it.
  3. Render and sign one documentA disposable unit renders the document, then signs it over its own byte range at the requested PAdES level. Nothing is shared with the next document.
  4. Commit on success, hold on failureA correctly-signed file commits once. A document that could not be signed is failed and retried — never emitted as unsigned bytes.
  5. Checkpoint, and resume on crashA durable run records what has committed. After a crash it continues from the last checkpoint instead of re-signing the whole batch.
A high-volume signing run end to end: shared signing material is warmed once; each document is rendered and signed individually on a disposable unit; a correctly-signed result commits exactly once, while any failure is held for retry, never passed on as unsigned bytes; a crashed run resumes from its checkpoint.

Core มอบความถูกต้องเชิงวิทยาการรหัสลับให้คุณ: การลงนาม CMS ด้วยซอฟต์แวร์และ PAdES B-B (พร้อม B-T ผ่าน timestamp client) ที่แต่ละเอกสารถูกลงนามเป็นรายฉบับและ fail-closed ส่วน การ orchestration ที่ทำให้การรันขนาดใหญ่มีความคงทน ทำงานพร้อมกัน และเป็น exactly-once — เอนจินเรนเดอร์ที่ปราศจาก side-effect บวกกับ committer, checkpoint, idempotency และ dead-letter store — คือโมดูล Stream ในเอดิชันขั้นสูง; การลงนามที่หนุนด้วยฮาร์ดแวร์ผ่าน HSM หรือ cloud KMS ก็เป็น seam ของเอดิชันขั้นสูงเช่นกัน Core พิสูจน์ว่าแต่ละลายเซ็นถูกต้อง; เอดิชันขั้นสูงทำให้หนึ่งล้านลายเซ็นนั้นอยู่รอดได้

รูปทรงด้านล่างคือหน่วยการลงนามต่อเอกสารภายในลูป batch แต่ละรอบลงนามเอกสารหนึ่งฉบับที่ระดับซึ่งระบุชื่อไว้ และให้ผลลัพธ์ที่ลงนามอย่างถูกต้อง หรือทำให้งานนั้นล้มเหลว — มันไม่เคยส่งคืนไบต์ที่ไม่ได้ลงนามแต่งตัวให้ดูเหมือนผลลัพธ์

<?php
declare(strict_types=1);
use NextPDF\Contracts\DocumentFactoryInterface;
use NextPDF\Security\Signature\CertificateInfo;
use NextPDF\Security\Signature\SignatureLevel;
use NextPDF\Exception\SignatureException;
use Psr\Log\LoggerInterface;
/**
* One signing-batch iteration: render, sign at a named level, commit or fail.
*
* The factory and the certificate source ($certInfo, the warmed signing
* material) are process-lifetime singletons; the document is disposable. A
* document that cannot be signed at the requested level fails this job loudly —
* it is never committed unsigned.
*
* @param iterable<int, callable(\NextPDF\Core\Document): \NextPDF\Core\Document> $jobs
*/
function signBatch(
DocumentFactoryInterface $factory,
CertificateInfo $certInfo,
LoggerInterface $logger,
iterable $jobs,
): void {
// The level is an explicit, ordered contract — not a flag we hope is honoured.
$level = SignatureLevel::PAdES_B_T;
foreach ($jobs as $jobId => $build) {
// Fresh, disposable unit — shares the warmed signing material only.
$doc = $factory->create();
$doc = $build($doc);
try {
// Sign over this document's own byte range, at exactly $level,
// or throw. There is no "signed lower, reported higher" path.
$doc->setSignature(certInfo: $certInfo, level: $level);
$signed = $doc->getPdfData();
} catch (SignatureException $e) {
// Fail-closed: this document does NOT continue as unsigned bytes.
// The job is failed and left for retry / dead-letter handling.
$logger->error('pdf.sign.failed', ['job_id' => $jobId, 'reason' => $e->getMessage()]);
continue;
}
// Only a correctly-signed result reaches the commit step.
commitSignedOutput($jobId, $signed);
unset($doc, $signed); // release per-document state before the next iteration
$logger->info('pdf.sign.committed', ['job_id' => $jobId, 'level' => $level->value]);
}
}

catch คือบรรทัดที่รับน้ำหนัก มันคือความแตกต่างระหว่างการรันที่กักเอกสารที่มันลงนามไม่ได้เอาไว้ กับการรันที่ส่งมันออกไปอยู่ดี continue ไม่ได้กลบเกลื่อนความล้มเหลว — งานนั้นถูกบันทึกไว้และถูกทิ้งไว้ให้ลองใหม่ ดังนั้น batch จึงเสร็จสิ้นพร้อมรายการที่ทราบและครบถ้วนว่าฉบับใดลงนามแล้วและฉบับใดยังไม่ ไม่มีวันมีช่องว่างแบบเงียบๆ

ความเข้าใจผิดประการแรกคือ “batch signing” หมายถึงลายเซ็นหนึ่งที่นำไปใช้กับหลายไฟล์ มันไม่ใช่ และระบบใดก็ตามที่อ้างเช่นนั้นก็ไม่ได้กำลังผลิตลายเซ็น PAdES ที่ถูกต้อง — digest ของแต่ละเอกสารผูกอยู่กับไบต์ของตัวเอง (Spec: ISO 32000-2, §12.8) Batch เป็นเรื่องเกี่ยวกับ จำนวนเท่าใด และ เร็วเพียงใด ล้วนๆ ไม่เคยเกี่ยวกับการใช้หน่วยเชิงวิทยาการรหัสลับร่วมกัน

ประการที่สองคือการคิดว่าความขนานหมายถึงการผ่อนคลายความถูกต้องเพื่อความเร็ว — ว่าตัวลงนามที่เร็วต้องตัดมุมที่ตัวลงนามที่พิถีพิถันไม่ตัด มันไม่เป็นเช่นนั้น เพราะหน่วยการลงนามไม่ใช้สถานะที่เปลี่ยนแปลงได้ร่วมกัน การรันมันแบบขนานจึงเปลี่ยนตารางเวลา ไม่ใช่ไบต์ ลายเซ็นแบบขนานแต่ละตัวถูกคำนวณด้วยความเข้มงวดเท่ากับลายเซ็นเดี่ยว ความขนานอยู่ใน orchestration ที่ห่อหุ้มพวกมัน

ประการที่สามคือการคิดว่าความคงทนเป็นสิ่งที่คุณมาแปะติดทีหลังจากการรันข้ามคืนที่ล้มเหลวครั้งแรก เมื่อถึงตอนนั้นคุณก็เสียการรันนั้นไปแล้ว ไปป์ไลน์ที่ทำงานต่อได้ต้องรู้เป็นรายเอกสารว่าสิ่งใด commit แล้วและสิ่งใดยังไม่ ก่อน ที่จะ crash — ซึ่งเป็นสิ่งที่ checkpoint และ idempotency store มีอยู่เพื่อบันทึกไว้พอดี

  • แต่ละลายเซ็นเป็นรายเอกสารและผูกพันกับมาตรฐาน; ไม่มีทางลัดแบบ batch ปริมาณ เปลี่ยนการจัดตารางเวลา ไม่ใช่หน่วยเชิงวิทยาการรหัสลับ NextPDF ลงนามทุกเอกสาร บนช่วงไบต์ของตัวเอง
  • Core ทำการลงนาม CMS ด้วยซอฟต์แวร์และ PAdES B-B (B-T ผ่าน timestamp client) ส่วนเอนจินเรนเดอร์และลงนามที่คงทน ทำงานพร้อมกัน และ exactly-once คือโมดูล Stream ในเอดิชันขั้นสูง; การดูแลครอบครองคีย์ที่หนุนด้วย HSM/KMS เป็น seam ของ เอดิชันขั้นสูง หน้านี้ไม่ได้อ้างว่าการ orchestration นั้นเป็น Core
  • Fail-closed เป็นพฤติกรรมของเอนจิน ไม่ใช่การรับประกันเกี่ยวกับการเดินสายของคุณ NextPDF ปฏิเสธที่จะ emit ไฟล์ที่ไม่ได้ลงนามแต่ถูกเชื่อว่าลงนามแล้ว และนำเสนอ เส้นทางการลงนามที่รองรับ ไปป์ไลน์ที่ดักข้อผิดพลาดที่เกิดขึ้นแล้ว commit ต่อไป อยู่ดี ได้เลือกที่จะทำลายการรับประกันนั้น — กรอบที่ catch/continue ใน ตัวอย่างมีอยู่เพื่อป้องกัน
  • ระดับ PAdES ถูกบังคับใช้เป็นรายเอกสาร ไม่ใช่ถูกรับรองสำหรับทั้งการรัน เอนจิน ผลิตระดับเบสไลน์ที่ร้องขอหรือไม่ก็ล้มเหลว; นั่นคือการบังคับใช้เชิงโครงสร้าง ไม่ใช่ คำตัดสินความสอดคล้องจากบุคคลที่สามสำหรับไฟล์ที่ผลิตออกมา ลำดับการไล่ระดับเองนั้น กล่าวถึงใน โปรไฟล์เบสไลน์ของ PAdES
  • คิว การดูแลครอบครองคีย์ ผู้ออกการประทับเวลา และ object store เป็นของคุณ NextPDF จัดหาความถูกต้องของการลงนามต่อเอกสาร และในเอดิชันขั้นสูงก็จัดหา primitive ของ การ orchestration ที่คงทน มันไม่ได้รันโครงสร้างพื้นฐานของคุณหรือรับประกัน TSA ของคุณ
High-volume and concurrent signing — edition availability
EditionAvailability
Core

การลงนาม CMS ด้วยซอฟต์แวร์ต่อเอกสาร PAdES B-B (B-T พร้อม timestamp client) ลงนามเป็นรายฉบับบนช่วงไบต์ของแต่ละเอกสาร fail-closed ป้องกันเอาต์พุตที่ไม่ได้ ลงนามแบบเงียบ การลงนามต่อเอกสารแบบธรรมดาไม่จำเป็นต้องใช้ระดับเชิงพาณิชย์

Pro

เพิ่มโมดูล Stream: เอนจินเรนเดอร์ที่ปราศจาก side-effect บวกกับ committer, checkpoint, idempotency และ dead-letter store ที่คงทน — การรัน batch ที่ ทำงานพร้อมกัน ปลอดภัยต่อ crash และ exactly-once ซึ่งทำงานต่อจากเดิมแทนที่จะ เริ่มใหม่

Enterprise

เพิ่มการดูแลครอบครองคีย์ที่หนุนด้วยฮาร์ดแวร์ (HSM ผ่าน PKCS#11 หรือ cloud KMS) เพื่อให้คีย์ส่วนตัวไม่เคยออกจากอุปกรณ์ และระดับ PAdES ระยะยาว (B-LT, B-LTA) ที่ทำให้คลังเก็บถาวรปริมาณสูงตรวจสอบยืนยันได้นานหลายทศวรรษ

  • การสร้างเอกสารปริมาณสูง — โมเดล batch แบบเข้าคิวที่มีหน่วยความจำในขอบเขตจำกัด ซึ่งหน้านี้ลงนามต่อยอด จากมัน; อ่านก่อนเพื่อทำความเข้าใจวินัยด้าน throughput และการวัดผล
  • โปรไฟล์เบสไลน์ของ PAdES — สิ่งที่ แต่ละระดับ (B-B ถึง B-LTA) เพิ่มเข้ามา เพื่อให้คุณลงนามที่ระดับซึ่งข้อผูกพันต้องการ
  • ลายเซ็นอยู่ใน PDF อย่างไร — รากฐานด้าน byte-range และพจนานุกรมที่ทำให้ลายเซ็นเป็นรายเอกสาร
  • การลงนามที่หนุนด้วย HSM — จุดที่ขอบเขต ของคีย์ส่วนตัวอยู่เมื่อวัสดุการลงนามอยู่ในฮาร์ดแวร์
  • Stream (Pro) — เอนจินเรนเดอร์ที่คงทน ทำงาน พร้อมกัน และ exactly-once ที่เปลี่ยนหน่วยการลงนามเดียวให้เป็นการรันที่ทำงาน ต่อได้
  • Batch signing — การลงนามเอกสารจำนวนมากตามกำหนดเวลา เป็นแนวคิดเชิงการจัด ตารางเวลา; แต่ละเอกสารยังคงถูกลงนามเป็นรายฉบับบนไบต์ของตัวเอง
  • Fail-closed — เมื่อเกิดความล้มเหลวที่มิฉะนั้นจะสร้างเอาต์พุตที่ไม่ได้ลงนาม หรือผิด ไปป์ไลน์จะกักเอกสารไว้และรายงาน แทนที่จะส่งต่อมันไปในรูปไบต์ดิบ
  • Exactly-once commit — คุณสมบัติของไปป์ไลน์ที่คงทนซึ่งเอาต์พุตที่ลงนามอย่าง ถูกต้องถูกเผยแพร่หนึ่งครั้งและไม่ถูก emit ซ้ำเมื่อการรันที่ crash ทำงานต่อ
  • Checkpoint — บันทึกที่คงทนต่อเอกสารว่าสิ่งใด commit แล้ว เพื่อให้การรัน ดำเนินต่อจากจุดที่หยุดได้แทนที่จะลงนามทุกอย่างใหม่
  • CMS SignedData — คอนเทนเนอร์เชิงวิทยาการรหัสลับสำหรับลายเซ็นบนเนื้อหา (สามารถพกพาผู้ลงนามได้หลายราย); ไปป์ไลน์นี้ผลิตลายเซ็น PDF ของผู้ลงนามหนึ่งราย ต่อเอกสาร ซึ่งคือหน่วยต่อเอกสารที่ batch ผลิตขึ้น
  • PAdES — PDF Advanced Electronic Signatures ชุดโปรไฟล์ของ ETSI EN 319 142 สำหรับการลงนาม PDF; ระดับเบสไลน์ของมันไล่ตั้งแต่ B-B ถึง B-LTA