تخطَّ إلى المحتوى

وقّع ملف 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⁩ بإضافة ⁨signature-time-stamp⁩ واحد وفق ⁨RFC 3161. B-T⁩ هو ⁨B-B⁩ مضافًا إليه طابع زمني واحد؛ وهو ليس فئة توقيع منفصلة. حدود الثقة صريحة: إنتاج التوقيع لا يعادل قرار جهة التحقق بأنه صالح.

تنبيه ⁨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⁩)، وحلقة الطابع الزمني الأرشيفي) خارج نطاق هذه الوصفة وليسا جزءًا من واجهة التوقيع في ⁨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 سلسلة سداسية عشرية محشوّة فوق مُلخّص نطاق البايتات (⁨ISO 32000-2⁩ §12.8.1). يغطّي المُلخّص الملف ويستثني قيمة التوقيع نفسها (⁨ISO 32000-2⁩ §12.8.1).

يضيف ⁨PAdES⁩ ⁨B-T⁩ ⁨signature-time-stamp⁩ واحدًا بالضبط وفق ⁨RFC 3161.⁩ بصمة رسالة الطابع الزمني هي تجزئة بايتات قيمة توقيع SignerInfo، دون أي بادئة وسم أو طول من ⁨Abstract Syntax Notation One⁩ (⁨ASN.1⁩) (⁨ETSI EN 319 122-1⁩ §5.3؛ ⁨RFC 3161 Appendix A⁩). يُدرَج الرمز كسمة غير موقّعة id-aa-timeStampToken، بمُعرّف الكائن (⁨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⁩ سوى الطابع الزمني. تُعرَّف شهادة ⁨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⁩: الطابع الزمني للتوقيع لا يضيف مادة تحقّق ولا طابعًا زمنيًا أرشيفيًا؛ تلك مستويات منفصلة أعلى لا تُنتَج هنا.

يعرض المخطّط أدناه تسلسل ⁨B-B⁩ ثم ⁨B-T⁩ بالترتيب الذي يستخدمه المحرّك. يُحسَب ByteRange بعد كتابة الملف بأكمله فقط، بحيث لا يمكن للإزاحات النهائية أن تغيّر البايتات التي ستُجزّأ. ثم يُلحِق ⁨B-T⁩ رمزًا واحدًا وفق ⁨RFC 3161⁩ كسمة غير موقّعة، تاركًا مُلخّص ⁨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 غير فارغ؛ وإنشاء موقّع ⁨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');

مثل output() وgetPdfData()، يكتب save() مدخل /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⁩) الموصوف في النظرة المفاهيمية؛ وتمرير TsaClient هو الفرق الوحيد عن ⁨B-B.⁩

استخدم شرح 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⁩ الزائف المرفق في المستودع للاختبار. يُعيد عميل ⁨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⁩):

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.⁩ إنشاء ⁨B-T⁩ DigitalSigner دون TsaClient يرمي SignatureException (⁨TSA⁩ مطلوب لأجل ⁨B-T⁩). تحقّق من إعداد ⁨TSA⁩ قبل التوقيع.
  • قابلية الوصول إلى ⁨TSA.⁩ يؤدّي ⁨B-T⁩ رحلة ذهاب وإياب حيّة وفق ⁨RFC 3161⁩ لكل توقيع. انقطاع ⁨TSA⁩ يعني عدم وجود توقيع ⁨B-T.⁩ استخدم قاطع دائرة واتفاقية مستوى خدمة (⁨SLA⁩) لـ ⁨TSA⁩ تناسب معدل المعالجة لديك؛ ويقبل TsaClient قاطع دائرة.
  • تحصين عميل ⁨HTTP⁩ الخاص بـ ⁨TSA.⁩ وجّه TsaClient إلى عميل ⁨PSR-18⁩ يثبّت ⁨SubjectPublicKeyInfo⁩ (⁨SPKI⁩) الخاص بـ ⁨TSA⁩ بصيغة ⁨RFC 7469⁩ ويحلّ ⁨Domain Name System⁩ (⁨DNS⁩) بأمان؛ ويشتقّ TsaClient::extractPublicKeyPin() التثبيت من شهادة ⁨TSA.⁩
  • ⁨B-T⁩ ليس ⁨B-LT/B-LTA.⁩ الطابع الزمني للتوقيع لا يضمّن مادة تحقّق (شهادات، ⁨Online Certificate Status Protocol⁩ (⁨OCSP⁩)، ⁨certificate revocation list⁩ (⁨CRL⁩)) ولا طابعًا زمنيًا أرشيفيًا. تلك هي مستويات ⁨B-LT/B-LTA⁩ ولا تُنتَج بهذه الوصفة.
  • تعارض الخطّية. 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 محميًا بقاطع دائرة.

لا يصبح التوقيع المُنتَج موثوقًا تلقائيًا. تحقّق التوقيع يتوقّف على الشهادة، ومرتكز الثقة الخاص بها، وسياسة جهة التحقق، وكلها تقع خارج هذه المكتبة. يحمي التشفير السرّية لا السلامة؛ ويحمي التوقيع السلامة والأصالة لا السرّية. عامِل حفظ المفتاح بوصفه الخطر الأساسي: المفتاح البرمجي في ذاكرة العملية آمن فقط بقدر أمان المضيف.

إقامة البيانات وتخفيف مخاطر الـ ⁨PII⁩

قسم بعنوان «إقامة البيانات وتخفيف مخاطر الـ ⁨PII⁩»

تعمل عملية التوقيع داخل العملية؛ ولا تغادر بايتات المستند والمفتاح الخاص المضيف إلا في رحلة ذهاب وإياب ⁨B-T⁩ الخاصة بـ ⁨TSA⁩، التي ترسل فقط بصمة الرسالة (تجزئة قيمة التوقيع)، ولا ترسل محتوى المستند أبدًا (⁨RFC 3161⁩ §2.4.1 MessageImprint). لا يُرسَل أي نص مستند أو معلومات تعريف شخصية (⁨PII⁩) إلى الـ ⁨TSA.⁩ اختر ⁨TSA⁩ تتوافق ولايتها القضائية مع سياسة إقامة بياناتك.

القياس الآمن وتنقية السجلّات

قسم بعنوان «القياس الآمن وتنقية السجلّات»

يقبل DigitalSigner مُسجِّلًا اختياريًا من نوع ⁨PSR-3.⁩ يسجّل الخوارزمية والمستوى، لا مادة المفتاح ولا بايتات التوقيع. مُعاملات password على CertificateInfo وTsaClient مُعلَّمة بـ #[SensitiveParameter]، فتُحجَب عبارات المرور من تتبّعات المكدّس. لا تسجّل SignatureResult::$cmsSignedData ولا $timestampToken.

ما أُخذ في الحسبان: العبث بالمدخل بعد التوقيع (يكتشفه مُلخّص نطاق البايتات)، وتعرّض المفتاح للاختراق (خارج نطاق المكتبة لأن حفظ المفتاح مسؤولية المُدمِج)، وانتحال ⁨TSA⁩ (يخفّفه تثبيت ⁨SPKI⁩ على عميل ⁨HTTP⁩ الخاص بـ ⁨TSA⁩)، والخفض بين المستويات (تعداد المستوى صريح؛ ولا يخفض المحرّك ⁨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 لطابع زمني للمستند يحمل ⁨TimeStampToken.⁩⁨ISO 32000-2⁩§12.8.1
Contents سلسلة سداسية عشرية محشوّة فوق مُلخّص نطاق البايتات.⁨ISO 32000-2⁩§12.8.1
بصمة ⁨signature-time-stamp⁩ هي تجزئة بايتات قيمة توقيع ⁨SignerInfo⁩ (دون وسم/طول ⁨tag/length⁩ من ⁨ASN.1⁩).⁨ETSI EN 319 122-1⁩§5.3
قيمة ⁨signature-time-stamp⁩ هي ⁨SignatureTimeStampToken.⁩⁨ETSI EN 319 122-1⁩§6
MessageImprint ::= SEQUENCE { hashAlgorithm, hashedMessage }.⁨RFC 3161⁩§2.4.1
بصمة الطابع الزمني للتوقيع هي تجزئة حقل توقيع ⁨SignerInfo⁩؛ SignatureTimeStampToken ::= TimeStampToken.⁨RFC 3161⁩⁨App. A⁩
مُعرّف ⁨OID⁩ لـ id-aa-timeStampToken هو 1.2.840.113549.1.9.16.2.14.⁨RFC 3161⁩⁨App. A⁩
SignerInfo يحمل unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL.⁨RFC 5652⁩§5.3
السمات غير الموقّعة غير محميّة بالتوقيع؛ ومُلخّص ⁨B-B⁩ الموقّع دون تغيير.⁨RFC 5652⁩§5.4
⁨RFC 5816⁩ يحدّث ⁨RFC 3161⁩؛ ⁨ESSCertIDv2⁩ يعرّف شهادة ⁨TSA⁩ دون ⁨SHA-1.⁩⁨RFC 5816⁩§1

تصف هذه الوصفة كيف يُنتج ⁨NextPDF⁩ توقيع ⁨B-B⁩ وتوقيع ⁨B-T.⁩ ولا تؤكّد أن أي توقيع ناتج صالح قانونيًا ولا أن مطابقة ⁨PAdES⁩ متحقّقة؛ بل جهة تحقّق مستقلة تتخذ تلك القرارات.

⁨PAdES B-LT⁩ و⁨B-LTA⁩ (مواد التحقق في ⁨DSS⁩ وحلقة الطابع الزمني الأرشيفي) وحفظ مفاتيح ⁨HSM⁩ عبر ⁨PKCS⁩#11 تتوفر في إصداري ⁨Pro⁩ و ⁨Enterprise.⁩ تغطّي هذه الوصفة ⁨B-B⁩ و⁨B-T⁩ فقط؛ فالمستويات الأعلى قدرات متمايزة يُتحقَّق منها على حدة وهي خارج النطاق هنا.