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

ลงนาม PDF ด้วย PAdES B-B และขยายเป็น PAdES B-T

ใช้สูตรนี้เพื่อสร้างลายเซ็น Portable Document Format (PDF) Advanced Electronic Signatures (PAdES) B-B ซึ่งเป็น Cryptographic Message Syntax (CMS) SignedData ที่มีแอตทริบิวต์แบบลงนาม (content-type, message-digest, signing-time) จากนั้นขยายลายเซ็นเดียวกันเป็น PAdES B-T ด้วยการเพิ่ม RFC 3161 signature-time-stamp หนึ่งรายการ โดย B-T คือ B-B ที่มี timestamp เพิ่มหนึ่งรายการ ไม่ใช่คลาสลายเซ็นแยกต่างหาก ขอบเขตความเชื่อถือมีความชัดเจน: การสร้างลายเซ็นไม่เท่ากับการที่ผู้ตรวจสอบตัดสินว่าลายเซ็นนั้นถูกต้อง

ข้อควรระวัง U-1 NextPDF ไม่ยืนยันว่ามีการรับรอง ETSI EN 319 142-1 แบบอิสระใด ๆ สำหรับ PAdES B-T นั้น EN 319 142-1 ไม่อยู่ในคลังข้อมูลสำหรับการตรวจสอบ ข้อกำหนด B-T signature-time-stamp ได้รับการตรวจสอบเทียบกับ ETSI EN 319 122-1 §5.3 ร่วมกับ RFC 3161, RFC 5652, RFC 5816 และ ISO 32000-2 §12.8 การรองรับโปรไฟล์ B-T ไม่ใช่การรับรองความสอดคล้องหรือ การรับรองความถูกต้องตามกฎหมาย ผู้ตรวจสอบอิสระเป็นผู้ ตัดสินเรื่องดังกล่าว

B-LT และ B-LTA (วัสดุการตรวจสอบ Document Security Store (DSS) และลูปการประทับเวลาแบบจัดเก็บถาวร) อยู่นอกขอบเขตของสูตรนี้ และไม่ใช่ส่วนหนึ่งของขอบเขต API การลงนาม Core/Pro ที่ครอบคลุมในที่นี้

Terminal window
composer require nextpdf/core:^3

ext-openssl ต้องเปิดใช้งานเพราะ CertificateInfo แยกวิเคราะห์คีย์ผ่าน OpenSSL สำหรับ B-T ยังต้องมีปลายทาง RFC 3161 Time Stamping Authority (TSA) ที่เข้าถึงได้และไคลเอนต์ HTTP แบบ PHP Standards Recommendation (PSR)-18

ลายเซ็น PAdES B-B เก็บ CMS SignedData ที่เข้ารหัสแบบ Distinguished Encoding Rules (DER) ไว้ในรายการ Contents ของดิกชันนารีลายเซ็น ค่า Contents เป็นสตริงฐานสิบหกที่เติม padding ครอบคลุมไดเจสต์ของช่วงไบต์ (ISO 32000-2 §12.8.1) ไดเจสต์ช่วงไบต์ครอบคลุมไฟล์และไม่รวมค่าลายเซ็นเอง (ISO 32000-2 §12.8.1)

PAdES B-T เพิ่ม RFC 3161 signature-time-stamp เพียงหนึ่งรายการ โดย message imprint ของ timestamp คือแฮชของออกเทตของค่าลายเซ็น SignerInfo และไม่มีแท็กหรือคำนำหน้าความยาว Abstract Syntax Notation One (ASN.1) (ETSI EN 319 122-1 §5.3; RFC 3161 Appendix A) token ถูกบรรจุเป็นแอตทริบิวต์ที่ไม่ลงนาม id-aa-timeStampToken object identifier (OID) 1.2.840.113549.1.9.16.2.14 (RFC 3161 Appendix A) และวางอยู่ใน SignerInfo.unsignedAttrs [1] IMPLICIT (RFC 5652 §5.3) เนื่องจากแอตทริบิวต์ที่ไม่ลงนามไม่ได้รับการปกป้องโดยลายเซ็น (RFC 5652 §5.4) ไดเจสต์ที่ลงนามของ B-B, /ByteRange และไบต์ลายเซ็น B-B จึงไม่เปลี่ยนแปลง — B-T เป็นเพียงการต่อท้าย timestamp เท่านั้น ระบุใบรับรอง TSA ด้วย ESSCertIDv2 (RFC 5816 ปรับปรุง RFC 3161)

ข้อควรระวัง U-1 (ระบุซ้ำที่การกล่าวอ้าง B-T) NextPDF ไม่ยืนยันว่ามีการรับรอง ETSI EN 319 142-1 แบบอิสระใด ๆ สำหรับ PAdES B-T นั้น EN 319 142-1 ไม่อยู่ในคลังข้อมูลสำหรับการตรวจสอบ ข้อกำหนด B-T signature-time-stamp ได้รับการตรวจสอบเทียบกับ ETSI EN 319 122-1 §5.3 ร่วมกับ RFC 3161, RFC 5652, RFC 5816 และ ISO 32000-2 §12.8 การรองรับโปรไฟล์ B-T ไม่ใช่ การรับรองความสอดคล้องหรือความถูกต้องตามกฎหมาย ผู้ตรวจสอบอิสระ เป็นผู้ตัดสินเรื่องดังกล่าว

SignatureLevel::PAdES_B_T มีอยู่ใน Core: SignatureLevel::PAdES_B_T->requiresTimestamp() เป็น true, ->isAvailableInEnvironment() เป็น true และ ->requiresDss() เป็น false — B-T ไม่ต้องใช้ Document Security Store B-T ≠ B-LT ≠ B-LTA: signature timestamp ไม่เพิ่มวัสดุการตรวจสอบหรือ archival timestamp ซึ่งเป็นระดับที่สูงกว่าและแยกต่างหากที่ไม่ได้สร้างขึ้นในที่นี้

แผนภาพด้านล่างแสดงโฟลว์จาก B-B ไป B-T ตามลำดับที่เอนจินใช้ ByteRange จะถูกคำนวณหลังจากเขียนทั้งไฟล์เสร็จแล้วเท่านั้น ดังนั้นออฟเซ็ตสุดท้ายจึงเปลี่ยนไบต์ที่กำลังถูกแฮชไม่ได้ จากนั้น B-T จะต่อท้าย RFC 3161 token หนึ่งรายการเป็นแอตทริบิวต์ที่ไม่ลงนาม และปล่อยให้ไดเจสต์ที่ลงนามของ B-B ไม่ถูกแตะต้อง

RFC 3161 TSANextPDF DigitalSignerRFC 3161 TSANextPDF DigitalSignerReserve fixed-width /Contents slotand /ByteRange placeholderByteRange covers the whole fileexcluding the /Contents valuePAdES B-B completeB-T = B-B + 1 timestampB-B signed digest unchangedalt[level == PAdES B-T]Callersign — level B-B or B-T1Write the complete PDF incl. xref + EOF2Compute the two real ByteRange offsets3Hash the two concatenated segments4Build CMS SignedData with signed attrs5Hash the SignerInfo signature value — message imprint6TimeStampReq — message imprint + fresh nonce7TimeStampToken — signed, echoes imprint + nonce8Verify token — status, nonce, imprint, signature, time9Embed token in SignerInfo.unsignedAttrs10Signed PDF — /Contents = DER CMS SignedData11Caller
Diagram

จุดเข้าใช้งานสำหรับการกำหนดค่าคือ Document::setSignature(CertificateInfo $certInfo, SignatureLevel $level = SignatureLevel::PAdES_B_B, ?TsaClient $tsaClient = null) การเรียกนี้บันทึกเจตนาในการลงนามไว้บนเอกสาร เอนจินการลงนาม PAdES ของ Core (NextPDF\Security\Signature\DigitalSigner) เป็นผู้สร้างลายเซ็นเข้ารหัสลับ เนื่องจากชุดทดสอบการรวมระบบใช้งานเอนจินนี้ และตัวอย่างที่รันได้เรียกใช้โดยตรง ผลลัพธ์จึงเป็นออบเจ็กต์ CMS จริงที่แยกวิเคราะห์ได้ SignatureLevel::PAdES_B_T ต้องการ TsaClient ที่ไม่เป็น null; การสร้างตัวลงนาม B-T โดยไม่มีตัวนี้จะโยน SignatureException

API ระดับสูง — เรียกครั้งเดียวแล้วได้ผลลัพธ์ที่ลงนามแล้ว

หัวข้อที่มีชื่อว่า “API ระดับสูง — เรียกครั้งเดียวแล้วได้ผลลัพธ์ที่ลงนามแล้ว”

เส้นทางที่เร็วที่สุดคือ API ระดับสูง: กำหนดค่าลายเซ็นบนเอกสาร แล้วจึงซีเรียลไลซ์เอกสาร เบื้องหลังจะรันเอนจิน PAdES ของ Core ตัวเดียวกัน (DigitalSigner) นี่เป็นเพียงทางลัดที่ครอบการใช้งานระดับล่างด้านล่าง ไม่ใช่เส้นทางโค้ดแยกต่างหาก

<?php
declare(strict_types=1);
use NextPDF\Core\Document;
use NextPDF\Security\Signature\CertificateInfo;
use NextPDF\Security\Signature\SignatureLevel;
use NextPDF\Security\Timestamp\TsaClient;
$certInfo = CertificateInfo::fromPkcs12(
p12Path: __DIR__ . '/signer.p12',
password: 'p12-passphrase',
);
// PAdES B-B end to end: configure, then serialise.
$doc = Document::createStandalone();
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'Signed end to end.', newLine: true);
$doc->setSignature(certInfo: $certInfo, level: SignatureLevel::PAdES_B_B);
$doc->save(__DIR__ . '/signed.pdf'); // or output() to stream, getPdfData() for bytes
// PAdES B-T: pass a TsaClient on the same call — one RFC 3161
// signature-time-stamp is added (see the TsaClient hardening notes below).
$doc->setSignature(
certInfo: $certInfo,
level: SignatureLevel::PAdES_B_T,
tsaClient: $tsa,
);
$doc->save(__DIR__ . '/signed-bt.pdf');

save() เช่นเดียวกับ output() และ getPdfData() จะเขียนรายการ /Contents เป็น CMS SignedData ที่เข้ารหัสแบบ DER ภายใต้ SubFilter ETSI.CAdES.detached (ISO 32000-2 §12.8, §12.7.5.5; RFC 5652) ผลลัพธ์ตรวจสอบได้ในระดับ CMS — เป็นออบเจ็กต์ CMS SignedData ที่มีรูปแบบถูกต้องและตัวแยกวิเคราะห์ CMS อ่านได้ — ซึ่งไม่เหมือนกับการสอดคล้องกับโปรไฟล์พื้นฐาน ETSI EN 319 142-1 หรือความถูกต้องตามกฎหมาย ผู้ตรวจสอบอิสระเป็นผู้ตัดสินประเด็นเหล่านั้น (ดูข้อควรระวัง U-1 ด้านบน) สำหรับ B-T การเรียกระดับสูงจะเพิ่ม RFC 3161 signature-time-stamp รายการเดียวตามที่อธิบายไว้ในภาพรวมเชิงแนวคิด ความแตกต่างเดียวจาก B-B คือการส่ง TsaClient

ใช้การใช้งาน DigitalSigner ระดับล่างด้านล่างเมื่อคุณต้องการควบคุมอัลกอริทึม ข้อมูลช่วงไบต์ หรือ SignatureResult โดยตรง

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Security\Signature\CertificateInfo;
use NextPDF\Security\Signature\DigitalSigner;
use NextPDF\Security\Signature\SignatureAlgorithm;
use NextPDF\Security\Signature\SignatureLevel;
$certInfo = CertificateInfo::fromPkcs12(
p12Path: __DIR__ . '/signer.p12',
password: 'p12-passphrase',
);
// PAdES B-B — a CMS SignedData, no timestamp.
$signer = new DigitalSigner(
certInfo: $certInfo,
level: SignatureLevel::PAdES_B_B,
algorithm: SignatureAlgorithm::Pkcs1v15,
);
$result = $signer->sign($byteRangeData);
echo $result->hasTimestamp() ? "B-T\n" : "B-B (no timestamp)\n";

โปรแกรมแบบครบในตัวนี้รันภายใต้ฮาร์เนสของ cookbook และสะท้อน examples/36-sign-pades-b-b-and-b-t.php โปรแกรมจะสร้างเอกสาร กำหนดค่าให้รองรับลายเซ็น PAdES แล้วลงนามเป็น B-B และอีกครั้งเป็น B-T ด้วยไคลเอนต์ TSA ในโปรดักชัน ให้ชี้ TsaClient ไปยังปลายทาง RFC 3161 จริงผ่านไคลเอนต์ PSR-18 ที่เสริมความแข็งแกร่ง: ไคลเอนต์ HTTP ที่คำนึงถึงความปลอดภัยซึ่งปักหมุด SubjectPublicKeyInfo (SPKI) ของ TSA และแก้ไข Domain Name System (DNS) อย่างปลอดภัย เพื่อให้โปรแกรมนี้ทำงานแบบออฟไลน์และให้ผลลัพธ์แน่นอน โปรแกรมจะฉีดไคลเอนต์ TSA ปลอมจาก test-support ของรีโพซิทอรี ไคลเอนต์ TSA ปลอมจะคืน RFC 3161 TimeStampResp ที่ถูกต้องเชิงโครงสร้าง

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Security\Signature\CertificateInfo;
use NextPDF\Security\Signature\DigitalSigner;
use NextPDF\Security\Signature\SignatureAlgorithm;
use NextPDF\Security\Signature\SignatureLevel;
use NextPDF\Security\Timestamp\TsaClient;
use NextPDF\Tests\Support\FakeTsaHttpClient;
// In your application, build CertificateInfo from your own signing material:
// CertificateInfo::fromPkcs12($p12Path, $passphrase) — a .p12/.pfx bundle
// CertificateInfo::fromFiles($certPem, $keyPem, $pass) — separate PEM files
// This program uses the repository RSA-2048 test fixtures so it is offline.
$certDir = __DIR__ . '/tests/Fixtures/Certificates';
$certPath = $certDir . '/test-rsa-2048-cert.pem';
$keyPath = $certDir . '/test-rsa-2048-key.pem';
if (!is_file($certPath) || !is_file($keyPath)) {
fwrite(STDERR, "Certificate fixtures absent. Run tests/Fixtures/Certificates/generate.sh\n");
exit(1);
}
$certInfo = new CertificateInfo(
certificate: (string) file_get_contents($certPath),
privateKey: (string) file_get_contents($keyPath),
);
// Build the document and record the signing intent on it. The ByteRange
// digest input is the document bytes with the /Contents placeholder
// excluded (ISO 32000-2 §12.8); getPdfData() yields the bytes to hash.
$doc = Document::createStandalone();
$doc->setTitle('Signed Invoice 2026-0042');
$doc->setAuthor('NextPDF Cookbook');
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'This document is configured for a PAdES signature.', newLine: true);
$doc->setSignature(certInfo: $certInfo, level: SignatureLevel::PAdES_B_B);
$byteRangeData = $doc->getPdfData();
// --- PAdES B-B: a CMS SignedData, no timestamp ---
$bb = (new DigitalSigner(
certInfo: $certInfo,
level: SignatureLevel::PAdES_B_B,
algorithm: SignatureAlgorithm::Pkcs1v15,
))->sign($byteRangeData);
// --- PAdES B-T: B-B + one RFC 3161 signature-time-stamp ---
// In production, build the TsaClient with your TSA endpoint and a hardened
// PSR-18 client (use the security-aware HTTP client for SSRF/DNS pinning):
// $tsa = new TsaClient(
// tsaUrl: 'https://tsa.example.com/timestamp',
// httpClient: $hardenedPsr18Client,
// );
// Here the offline fake TSA client keeps the program network-free.
$tsa = new TsaClient(
tsaUrl: 'https://tsa.example.com/timestamp',
httpClient: new FakeTsaHttpClient(),
);
$bt = (new DigitalSigner(
certInfo: $certInfo,
tsaClient: $tsa,
level: SignatureLevel::PAdES_B_T,
algorithm: SignatureAlgorithm::Pkcs1v15,
))->sign($byteRangeData);
// B-T = B-B + a single timestamp token. The B-B signed digest is unchanged;
// $bt->timestampToken holds the DER-encoded RFC 3161 token.
printf("PAdES B-B CMS: %d bytes, timestamp=%s\n", $bb->getSize(), $bb->hasTimestamp() ? 'yes' : 'no');
printf(
"PAdES B-T CMS: %d bytes, timestamp=%s (%d-byte RFC 3161 token)\n",
$bt->getSize(),
$bt->hasTimestamp() ? 'yes' : 'no',
strlen($bt->timestampToken),
);
echo "B-T = B-B + one RFC 3161 signature-time-stamp (unsigned attribute).\n";
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script under the
// semantic profile (the signed CMS/timestamp bytes are inherently
// non-reproducible and are asserted by the PHPUnit harness, not a byte hash).
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
file_put_contents($out !== false && $out !== '' ? $out : __DIR__ . '/signed-invoice.pdf', $byteRangeData);

ค่าที่คาดหวังจาก STDOUT (ขนาดจะแตกต่างกันไปตามใบรับรองและ TSA token):

PAdES B-B CMS: <n> bytes, timestamp=no
PAdES B-T CMS: <n> bytes, timestamp=yes (<m>-byte RFC 3161 token)
B-T = B-B + one RFC 3161 signature-time-stamp (unsigned attribute).

ข้อควรระวัง U-1 (แนบกับการกล่าวอ้าง B-T ในโปรดักชัน) NextPDF ไม่ ยืนยันว่ามีการรับรอง ETSI EN 319 142-1 แบบอิสระใด ๆ สำหรับ PAdES B-T นั้น EN 319 142-1 ไม่อยู่ในคลังข้อมูลสำหรับการตรวจสอบ ข้อกำหนด B-T signature-time-stamp ได้รับการตรวจสอบเทียบกับ ETSI EN 319 122-1 §5.3 ร่วมกับ RFC 3161, RFC 5652, RFC 5816 และ ISO 32000-2 §12.8 การรองรับโปรไฟล์ B-T ไม่ใช่การรับรองความสอดคล้องหรือความถูกต้องตามกฎหมาย ผู้ตรวจสอบอิสระเป็นผู้ตัดสินเรื่องดังกล่าว

  • B-T โดยไม่มีไคลเอนต์ TSA การสร้าง DigitalSigner สำหรับ B-T โดยไม่มี TsaClient จะโยน SignatureException (จำเป็นต้องมี TSA สำหรับ B-T) ตรวจสอบการกำหนดค่า TSA ก่อนลงนาม
  • การเข้าถึง TSA B-T ต้องสื่อสารไป-กลับกับ TSA ตาม RFC 3161 แบบสดต่อหนึ่งลายเซ็น หาก TSA ขัดข้อง จะสร้างลายเซ็น B-T ไม่ได้ ใช้ circuit breaker และข้อตกลงระดับการให้บริการ (SLA) ของ TSA ที่เหมาะสมกับปริมาณงานของคุณ; TsaClient รองรับ circuit breaker
  • การเสริมความแข็งแกร่งให้ไคลเอนต์ HTTP ของ TSA ชี้ TsaClient ไปยังไคลเอนต์ PSR-18 ที่ปักหมุด SubjectPublicKeyInfo (SPKI) ของ TSA (รูปแบบ RFC 7469) และแก้ไข Domain Name System (DNS) อย่างปลอดภัย; TsaClient::extractPublicKeyPin() ดึงค่า pin จากใบรับรอง TSA
  • B-T ไม่ใช่ B-LT/B-LTA signature timestamp ไม่ฝังวัสดุการตรวจสอบ (ใบรับรอง, Online Certificate Status Protocol (OCSP), certificate revocation list (CRL)) หรือ archival timestamp สิ่งเหล่านั้นเป็นระดับ B-LT/B-LTA และไม่ได้สร้างขึ้นโดยสูตรนี้
  • ความขัดแย้งของ Linearization enableLinearization() และลายเซ็นที่กำหนดค่าไว้ใช้ร่วมกันไม่ได้ — การเรียกอย่างใดอย่างหนึ่งจะโยน InvalidConfigException เมื่ออีกอย่างถูกตั้งค่าไว้แล้ว
  • คีย์ HSM สำหรับคีย์ที่เก็บใน hardware security module (HSM) ให้สร้าง CertificateInfo ด้วย CertificateInfo::fromHsm(); คีย์ส่วนตัวจะไม่เข้าสู่หน่วยความจำของกระบวนการ สัญญาอินเทอร์เฟซตัวลงนาม PKCS#11 อยู่ใน Core; ผู้ให้บริการที่ใช้งานได้จริงอยู่ใน Premium

ลายเซ็น B-B เป็นการดำเนินการ CMS ในเครื่อง B-T เพิ่มการสื่อสารไป-กลับ HTTP ตาม RFC 3161 แบบซิงโครนัสไปยัง TSA ต่อหนึ่งลายเซ็น วางแผนรองรับเวลาแฝงและขีดจำกัดอัตราของ TSA ในเวิร์กโหลดแบบแบตช์ ใช้ TsaClient ที่มี circuit breaker ป้องกัน

การสร้างลายเซ็นได้ไม่ได้หมายความว่าลายเซ็นนั้นเชื่อถือได้โดยอัตโนมัติ การที่ลายเซ็นจะตรวจสอบผ่านหรือไม่ขึ้นอยู่กับ trust anchor ของใบรับรองและนโยบายของผู้ตรวจสอบ ซึ่งอยู่นอกไลบรารีนี้ การเข้ารหัสลับปกป้องความลับ ไม่ใช่ความสมบูรณ์; การลงนามปกป้องความสมบูรณ์และความเป็นของแท้ ไม่ใช่ความลับ ให้ถือว่าการเก็บรักษาคีย์เป็นความเสี่ยงหลัก: คีย์ซอฟต์แวร์ในหน่วยความจำของกระบวนการปลอดภัยได้เพียงเท่าที่โฮสต์ปลอดภัย

ถิ่นที่อยู่ของข้อมูลและการบรรเทาความเสี่ยง PII

หัวข้อที่มีชื่อว่า “ถิ่นที่อยู่ของข้อมูลและการบรรเทาความเสี่ยง PII”

การดำเนินการลงนามทำงานภายในกระบวนการ; ไบต์ของเอกสารและคีย์ส่วนตัวจะไม่ออกจากโฮสต์ ยกเว้นการสื่อสารไป-กลับกับ TSA สำหรับ B-T ซึ่งส่งเฉพาะ message imprint (แฮชของค่าลายเซ็น) เท่านั้น ไม่ส่งเนื้อหาเอกสารเลย (RFC 3161 §2.4.1 MessageImprint) ไม่มีการส่งเนื้อความในเอกสารหรือข้อมูลที่ระบุตัวบุคคลได้ (PII) ไปยัง TSA เลือก TSA ที่เขตอำนาจตรงกับนโยบายถิ่นที่อยู่ของข้อมูลของคุณ

DigitalSigner รับ logger แบบ PSR-3 ได้เป็นตัวเลือก โดยจะบันทึกอัลกอริทึมและระดับ ไม่ใช่วัสดุคีย์หรือไบต์ลายเซ็น พารามิเตอร์ password บน CertificateInfo และ TsaClient ถูกทำเครื่องหมายเป็น #[SensitiveParameter] ดังนั้น passphrase จึงถูกปกปิดจาก stack trace อย่าบันทึก SignatureResult::$cmsSignedData หรือ $timestampToken เด็ดขาด

ที่พิจารณาแล้ว: อินพุตที่ถูกดัดแปลงหลังลงนาม (ตรวจพบโดยไดเจสต์ช่วงไบต์), การรั่วไหลของคีย์ (อยู่นอกขอบเขตของไลบรารีเพราะการเก็บรักษาคีย์เป็นความรับผิดชอบของผู้รวมระบบ), การปลอมตัวเป็น TSA (บรรเทาด้วยการปักหมุด SPKI บนไคลเอนต์ HTTP ของ TSA) และการลดระดับระหว่างระดับต่าง ๆ (enum ของระดับระบุชัดเจน; เอนจินไม่ลดระดับ B-T ลงเป็น B-B โดยไม่แจ้ง) สิ่งที่ไม่ได้ยืนยัน: การปราศจากช่องโหว่ หรือว่าลายเซ็นใด ๆ ที่ได้นั้นถูกต้องตามกฎหมาย

พรีมิทีฟสำหรับการลงนามมาจาก OpenSSL บนบิลด์ OpenSSL ที่ผ่านการตรวจรับรอง Federal Information Processing Standards (FIPS) การดำเนินการ RSA/ECDSA และ SHA-256 จะทำงานผ่านผู้ให้บริการ FIPS; NextPDF ไม่ยืนยันการตรวจรับรอง FIPS ด้วยตัวเอง CryptoCapabilities รายงานพรีมิทีฟที่โฮสต์มีอยู่; ตรวจสอบเชนผู้ให้บริการ OpenSSL ในการติดตั้งใช้งานของคุณ

ข้อความระบุข้อกำหนดข้อย่อยรหัสอ้างอิง (reference_id)
ไดเจสต์ช่วงไบต์ครอบคลุมไฟล์และไม่รวมค่าลายเซ็นISO 32000-2§12.8.1
Contents เก็บ DER CMS SignedData; Contents ของ document-timestamp เก็บ TimeStampTokenISO 32000-2§12.8.1
Contents เป็นสตริงฐานสิบหกที่เติม padding ครอบคลุมไดเจสต์ช่วงไบต์ISO 32000-2§12.8.1
imprint ของ signature-time-stamp คือแฮชของออกเทตค่าลายเซ็น SignerInfo (ไม่มีแท็ก/ความยาว ASN.1 tag/length)ETSI EN 319 122-1§5.3
ค่าของ signature-time-stamp เป็น SignatureTimeStampTokenETSI EN 319 122-1§6
MessageImprint ::= SEQUENCE { hashAlgorithm, hashedMessage }RFC 3161§2.4.1
imprint ของ signature timestamp คือแฮชของฟิลด์ลายเซ็น SignerInfo; SignatureTimeStampToken ::= TimeStampToken ตามนิยามRFC 3161App. A
id-aa-timeStampToken มี OID เป็น 1.2.840.113549.1.9.16.2.14RFC 3161App. A
SignerInfo มี unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONALRFC 5652§5.3
แอตทริบิวต์ที่ไม่ลงนามไม่ได้รับการปกป้องโดยลายเซ็น; ไดเจสต์ที่ลงนามของ B-B ไม่เปลี่ยนแปลงRFC 5652§5.4
RFC 5816 ปรับปรุง RFC 3161; ESSCertIDv2 ระบุใบรับรอง TSA โดยไม่ใช้ SHA-1RFC 5816§1

สูตรนี้อธิบายวิธีที่ NextPDF สร้างลายเซ็น B-B และ B-T แต่ไม่ได้ยืนยันว่าลายเซ็นใด ๆ ที่ได้นั้นถูกต้องตามกฎหมายหรือสอดคล้องกับ PAdES; ผู้ตรวจสอบอิสระเป็นผู้ตัดสินประเด็นเหล่านั้น

PAdES B-LT และ B-LTA (วัสดุการตรวจสอบ DSS และลูปการประทับเวลาแบบจัดเก็บถาวร) และการเก็บรักษาคีย์ PKCS#11 HSM มีอยู่ในรุ่น Pro และ Enterprise สูตรนี้ครอบคลุมเฉพาะ B-B และ B-T เท่านั้น; ระดับที่สูงกว่าเป็นความสามารถที่แตกต่าง ต้องตรวจสอบแยกต่างหาก และอยู่นอกขอบเขตในที่นี้