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

Enterprise الإصدار

القوائم الموثوقة (TSL)

يبدأ التحقق من التوقيع في الاتحاد الأوروبي من حقيقة منشورة: أي مزوّدين يحملون الحالة المؤهلة. تعيش هذه الحقيقة في القوائم الموثوقة (⁨TSLs⁩) — مستندات ⁨XML⁩ موقَّعة تنشرها كل دولة عضو، مُفهرَسة عبر قائمة القوائم الموثوقة للاتحاد الأوروبي (⁨LOTL⁩). يحوّل ⁨NextPDF\Enterprise\Security\Tsl\TslPolicyEnforcer⁩ عنوان ⁨URL⁩ لقائمة ⁨TSL⁩ أو ⁨XML⁩ الخام إلى ⁨TslDocument⁩ يمكنك الاعتماد عليه. فهو يجلب عبر ⁨HTTPS⁩ محمي، ويتحقق من توقيع ⁨XMLDSig⁩ مقابل مراسٍ تُثبِّتها، ويحلّل ⁨XML⁩ مُحصَّناً، ويرفض القوائم القديمة. مكالمة إضافية واحدة، ⁨TslTrustAnchorProvider::buildBundle()⁩، تحوّل خدمات ⁨CA/QC⁩ النشطة إلى حزمة مراسي ثقة مُصدَّرة الإصدار. كل بوابة تفشل مغلقة؛ وكل رفض هو استثناء مُصنَّف النوع.

تختصّ هذه الصفحة باستيعاب القوائم واشتقاق المراسي. يوجد التحقق من مسار الشهادة في التحقق من التوقيع. يوجد ربط مستويات ضمان ⁨eIDAS⁩ في مستويات ضمان eIDAS. يوجد ربط ثقة الحاوية في ربط ثقة ASiC.

تُشحَن هذه القدرة ضمن ⁨NextPDF Enterprise⁩ (⁨nextpdf/enterprise⁩) وتُفعَّل بمِظروف ترخيص من فئة ⁨Enterprise⁩. النشر الذي يفتقر إلى ذلك الاستحقاق لا يُحمِّل أصناف القدرة. قارن الإصدارات واحصل على ترخيص.

Terminal window
composer require nextpdf/enterprise

يتطلّب التفعيل مِظروف ترخيص ⁨Enterprise⁩ الخاص بك. راجع التثبيت والمصادقة. توجد أصناف هذه الصفحة تحت ⁨NextPDF\Enterprise\Security\Tsl⁩؛ وتوجد أنواع سياسة الشبكة تحت ⁨NextPDF\Enterprise\Security⁩. يحتاج الجلب عبر الإنترنت إضافةً إلى أي عميل ⁨PSR-18⁩ ومصنع ⁨PSR-17⁩ (على سبيل المثال ⁨guzzlehttp/guzzle⁩).

بموجب المادة 22 من ⁨eIDAS⁩، تنشر كل دولة عضو قائمة موثوقة بمزوّدي خدمات الثقة المؤهلين لديها، موقَّعة أو مختومة للمعالجة الآلية. يعرّف ⁨ETSI TS 119 612⁩ تنسيق ⁨XML⁩. القائمة موثوقة بقدر ما تجعلها ثلاثة فحوص فقط: توقيعها، وبنيتها، وحداثتها. يشغّل ⁨NextPDF⁩ هذه الفحوص بذلك الترتيب، كخطّ أنابيب واحد:

  1. الجلب — يسترجع ⁨TslFetcher⁩ ملف ⁨XML⁩ عبر ⁨HTTPS⁩ فقط. يتحقق حارس ⁨SSRF⁩ من المضيف قبل أي خروج. الاستجابات محدودة الحجم، وتُمكِّن ذاكرة ⁨PSR-16⁩ المؤقتة إعادة التحقق عبر ⁨ETag⁩ والقراءات في البيئات المعزولة.
  2. التحقق — يفحص ⁨TslSignatureVerifier⁩ توقيع ⁨XMLDSig⁩ المُغلَّف. يجب أن تتسلسل شهادة التوقيع إلى مرساة ثقة ثبَّتَّها خارج النطاق؛ ولا يُوثَق بأي شيء داخل المستند بمفرده.
  3. التحليل — يستخرج ⁨TslXmlParser⁩ معلومات المخطط وكل خدمة ⁨TSP⁩ إلى ⁨TslDocument⁩ غير قابل للتغيير. تُرفَض المستندات الحاملة لـ ⁨DOCTYPE⁩ قبل بناء أي جدول كيانات.
  4. الفرض — يجب ألّا تكون لحظة ⁨NextUpdate⁩ للقائمة قد مضت. تُهمَل القائمة القديمة، ولا تُستهلَك أبداً.

يجمع ⁨TslPolicyEnforcer⁩ الأربعة كلها؛ و⁨TslDocument⁩ الصادر عنه قد اجتاز كل بوابة. ومن هناك، يرشّح ⁨TslTrustAnchorProvider::buildBundle()⁩ الخدمات التي هي في آنٍ واحد بحالة granted ومن نوع ⁨CA/QC⁩، ويُصدِر ⁨EnterpriseCaTrustAnchorBundle⁩: مراسي ⁨PEM⁩ مُثبَّتة، وإصدار ⁨tsl-<territory>-seq<N>⁩، وملخّص سلامة ⁨SHA-256⁩. تلك الحزمة هي ما يستهلكه التحقق من المسار وربط ثقة ⁨ASiC⁩.

تغطي الآلية نفسها سير عمل ⁨LOTL⁩. تحقّق من ⁨LOTL⁩ مقابل مرساة مُثبَّتة يدوياً؛ ثم تحقّق من كل قائمة ⁨TSL⁩ لدولة عضو مقابل شهادات التوقيع التي يعلنها ⁨LOTL⁩ لها.

القرار الحامل للثقل هو ملف تحقق ثابت وأدنى بدلاً من ⁨XMLDSig⁩ العام. معالجة توقيع ⁨XML⁩ المرنة — سلاسل تحويل عشوائية، ومراجع ⁨ID⁩ يعلنها المهاجم، ومرونة الخوارزميات — هي حيث ينكسر المتحققون تاريخياً. لذا يقبل المتحقق نموذج معالجة واحداً بالضبط: ⁨exclusive C14N⁩، ومرجع يغطي الجذر، وخطّ الأنابيب ثنائي التحويل ⁨[enveloped-signature, exclusive-C14N]⁩، مع رفض كل ما عداه فشلاً مغلقاً. لا تنطلق الثقة أبداً من المستند نفسه: شهادات ⁨KeyInfo⁩ تتسلسل فقط إلى مراسٍ أعددتها. تعيش الحداثة على ⁨TslDocument⁩ نفسه، بحيث يفرضها كل مسار مستهلِك بدلاً من متعاون اختياري واحد. والنتيجة نواة صغيرة قابلة للاختبار وحتمية وصادقة بشأن ما ترفضه.

خلفية التصميم: التوقيعات المؤهلة، بشرح مبسّط.

نقطة الدخول المنسّقة: الجلب والتحقق والتحليل وفحص الحداثة في مكالمة واحدة.

public function __construct(
private readonly TslFetcher $fetcher,
private readonly TslSignatureVerifier $verifier,
private readonly TslXmlParser $parser,
) {}
public function fetchAndVerify(string $url): TslDocument
public function verifyXml(string $xml): TslDocument

يُطلِق أو يفشل بـ:TslFetchException⁩ و⁨NextPDF\Enterprise\Security\NetworkPolicyViolation⁩ من مرحلة الجلب؛ و⁨TslSignatureException⁩ من التحقق من التوقيع؛ و⁨TslParseException⁩ من التحليل، أو من قيمة ⁨NextUpdate⁩ غير قانونية الصيغة، أو من قائمة قديمة. تُرجِع كلتا الطريقتين ⁨TslDocument⁩ فقط عندما تجتاز كل بوابة. تقارن بوابة القِدَم هنا ⁨NextUpdate⁩ مقابل ساعة النظام الحالية.

جالب ⁨HTTP⁩ مع تخزين مؤقت قائم على ⁨ETag⁩ وبوابة سياسة شبكة.

public function __construct(
private readonly ClientInterface $httpClient,
private readonly RequestFactoryInterface $requestFactory,
private readonly ?CacheInterface $cache = null,
private readonly int $defaultTtlSeconds = 3600,
private readonly int $maxBytes = 16_777_216,
private readonly NetworkPolicy $networkPolicy = NetworkPolicy::ONLINE,
) {}
public function fetch(string $url): string

يُطلِق أو يفشل بـ:TslFetchException⁩ عند عنوان ⁨URL⁩ غير ⁨HTTPS⁩، أو مضيف مرفوض (⁨SSRF⁩)، أو حالة خطأ ⁨HTTP⁩، أو استجابة مفرطة الحجم، أو جسم فارغ؛ و⁨NetworkPolicyViolation⁩ عندما تكون ⁨NetworkPolicy::STRICT_OFFLINE⁩ نشطة ولا يوجد جسم مُخزَّن مؤقتاً. تفي الأجسام المُخزَّنة مؤقتاً بإعادة التحقق ⁨304 Not Modified⁩ وهي الأجسام الوحيدة المُقدَّمة تحت ⁨STRICT_OFFLINE⁩. تعيش مُدخَلات التخزين المؤقت لمدة ⁨$defaultTtlSeconds⁩.

مُتحقِّق ⁨XMLDSig⁩ للقوائم الموثوقة الموقَّعة.

public function __construct(
private readonly array $trustAnchorsPem,
private readonly int $clockTolerance = 0,
)
public function verify(string $xml): string

تُرجِع ⁨verify()⁩ صيغة ⁨PEM⁩ لشهادة التوقيع، مع إثبات تسلسلها إلى إحدى ⁨$trustAnchorsPem⁩. يُطلِق المُنشئ ⁨InvalidArgumentException⁩ عندما تكون قائمة المراسي فارغة. يوسّع ⁨$clockTolerance⁩ نافذة صلاحية الشهادة بشكل متناظر، بالثواني.

الملف المقبول ثابت. خوارزميات التوقيع: قائمة السماح ⁨ALLOWED_SIG_ALG⁩ (⁨rsa-sha256/384/512⁩، ⁨ecdsa-sha256/384/512⁩). الملخّصات: قائمة السماح ⁨ALLOWED_DIGEST_ALG⁩ (⁨SHA-256⁩، ⁨SHA-384⁩، ⁨SHA-512⁩). التقنين: ⁨exclusive C14N 1.0⁩ فقط. تُرفَض ⁨SHA-1⁩ و⁨MD5⁩ بوصفها ⁨unsupported_algorithm⁩.

يُطلِق أو يفشل بـ:TslSignatureException⁩، حاملاً ⁨reason⁩ قابلاً للقراءة آلياً:

رمز السببالمعنى
missing_signatureلا يحتوي المستند على عنصر ⁨ds:Signature⁩.
untrusted_signerلا تتسلسل شهادة ⁨KeyInfo⁩ إلى مرساة مُعدَّة.
invalid_signatureعيب بنيوي، أو فشل فحص ⁨RSA/ECDSA⁩.
digest_mismatchلا يطابق ملخّص المرجع المستند المُقنَّن.
unsupported_algorithmخوارزمية توقيع أو ملخّص خارج قائمة السماح.
unsupported_transformتقنين أو خطّ أنابيب تحويل خارج الملف الثابت.
expired_anchorشهادة في السلسلة خارج نافذة صلاحيتها، أو صلاحيتها غير قابلة للتحليل.

محلّل بنيوي لا يكترث بالتوقيع. يجب على المستدعين التحقق قبل الوثوق بمخرجاته؛ ويفرض ⁨TslPolicyEnforcer⁩ ذلك الترتيب نيابةً عنك.

public function parse(string $xml): TslDocument

يُطلِق أو يفشل بـ:TslParseException⁩ عندما يعلن ⁨XML⁩ عن ⁨DOCTYPE⁩ (تحصين ضد ⁨XXE⁩ وتوسّع الكيانات)، أو يتعذّر تحليله، أو يفتقر إلى جذر ⁨TrustServiceStatusList⁩، أو يحمل ⁨TSLSequenceNumber⁩ غير صالح. يكشف الصنف عن ثوابت مساحة الأسماء ⁨NS_TSL⁩ و⁨NS_DSIG⁩ و⁨NS_TSL_X⁩.

TslDocument⁩ كائن قيمة غير قابل للتغيير: ⁨schemeTerritory⁩ و⁨schemeOperatorName⁩ و⁨tslType⁩ و⁨sequenceNumber⁩ و⁨issueDateTime⁩ و⁨nextUpdate⁩ و⁨tspServices⁩ و⁨rawXmlSha256⁩ (تجزئة دليل على البايتات الخام).

public function isStale(DateTimeImmutable $now): bool
public function assertFresh(DateTimeImmutable $now): void
public function servicesOfType(string $serviceTypeIdentifier): array
public function activeServices(): array

يُطلِق أو يفشل بـ: تُطلِق ⁨isStale()⁩ و⁨assertFresh()⁩ الاستثناء ⁨TslParseException⁩ عندما لا تكون ⁨nextUpdate⁩ قيمة ⁨dateTime⁩ قانونية بتوقيت ⁨UTC⁩ مع ⁨Z⁩ صريح أو إزاحة رقمية؛ والقائمة القديمة تجعل ⁨assertFresh()⁩ تُطلِق استثناءً. تُرجِع ⁨activeServices()⁩ الخدمات ذات الحالة granted فقط. ترشّح ⁨servicesOfType()⁩ بحسب ⁨URI⁩ نوع خدمة ⁨ETSI⁩.

يكشف كل مُدخَل ⁨TspService⁩ عن ⁨tspName⁩ و⁨serviceName⁩ و⁨serviceTypeIdentifier⁩ و⁨serviceStatus⁩ و⁨statusStartingTime⁩ و⁨serviceCertificatePem⁩ و⁨qualifiers⁩ و⁨additionalServiceInformation⁩، بالإضافة إلى:

public function isGranted(): bool
public function isQualifiedCa(): bool

ثوابت مفيدة: ⁨TspService::STATUS_GRANTED⁩ و⁨TspService::STATUS_WITHDRAWN⁩ و⁨TspService::TYPE_CA_QC⁩ و⁨TspService::TYPE_OCSP_QC⁩ و⁨TspService::TYPE_TSA_QTST⁩. تظهر معرّفات ⁨URI⁩ للمؤهِّلات (على سبيل المثال ⁨TspServiceQualifier::FOR_ESIG⁩ و⁨FOR_ESEAL⁩ و⁨QSCD_STATEMENT⁩ و⁨NO_QSCD⁩) على ⁨TspServiceQualifier⁩ لأجل طبقة ربط ⁨eIDAS⁩.

TslTrustAnchorProvider وحزمة المراسي

قسم بعنوان «TslTrustAnchorProvider وحزمة المراسي»
public function buildBundle(TslDocument $tsl, DateTimeImmutable $now): EnterpriseCaTrustAnchorBundle

يُطلِق أو يفشل بـ:TslParseException⁩ عندما تكون قائمة ⁨TSL⁩ قديمة عند ⁨$now⁩، أو عندما لا تكون ⁨nextUpdate⁩ قيمة ⁨UTC⁩ قانونية، أو عندما لا تحتوي القائمة على أي خدمات ⁨CA/QC⁩ نشطة.

ملاحظة توافق للخلف — قاعدة حداثة ⁨buildBundle($now)⁩. تتطلّب ⁨buildBundle()⁩ لحظة التحقق وتستدعي ⁨TslDocument::assertFresh($now)⁩ قبل استخراج أي مرساة واحدة. كان بإمكان المراجعات السابقة اشتقاق المراسي من ⁨TslDocument⁩ ناتج عن المحلّل دون أي فحص حداثة. يجب على المستدعين الذين يغذّون قوائم مُخزَّنة مؤقتاً أو مؤرشفة تمرير اللحظة التي يجري عندها تحققهم الآن؛ والقائمة القديمة عند تلك اللحظة تُطلِق استثناءً بدلاً من زرع مراسي الثقة بصمت.

EnterpriseCaTrustAnchorBundle⁩ المُرجَعة كائن قيمة للقراءة فقط: ⁨anchorsPem⁩ (مراسي ⁨PEM⁩)، و⁨bundleVersion⁩ (⁨tsl-<territory>-seq<N>⁩)، و⁨bundleSha256⁩ (ملخّص سلامة على تسلسل ⁨PEM⁩ المُقنَّن). احصل عليها من ⁨buildBundle()⁩؛ ولا تُنشئها يدوياً — يُطلِق المُنشئ ⁨InvalidArgumentException⁩ عند عدم تطابق الملخّص أو تشوّه ⁨PEM⁩.

public function containsFingerprint(string $anchorDerSha256Hex): bool
public static function computeBundleSha256(array $anchorsPem): string

صادِق واستهلك قائمة موثوقة مُنعكِسة محلياً. لا حاجة لأي اعتماد على ⁨HTTP⁩ في هذا المسار: تحقّق، وحلّل، ثم بوّب الحداثة عند لحظة تحققك.

tsl-verify-quickstart.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Tsl\TslParseException;
use NextPDF\Enterprise\Security\Tsl\TslSignatureException;
use NextPDF\Enterprise\Security\Tsl\TslSignatureVerifier;
use NextPDF\Enterprise\Security\Tsl\TslXmlParser;
// The list-signing certificate, pinned OUT-OF-BAND. Never take it from the list itself.
$pinnedAnchorPem = (string) file_get_contents(__DIR__ . '/tsl-signer-anchor.pem');
// A trusted-list XML document you mirrored locally.
$tslXml = (string) file_get_contents(__DIR__ . '/member-state-tsl.xml');
try {
// 1. Authenticate: XMLDSig must verify AND the signer must chain to the pinned anchor.
(new TslSignatureVerifier(trustAnchorsPem: [$pinnedAnchorPem]))->verify($tslXml);
// 2. Parse the now-authenticated bytes.
$tsl = (new TslXmlParser())->parse($tslXml);
// 3. Freshness: refuse a list whose NextUpdate has passed.
$tsl->assertFresh(new DateTimeImmutable('now', new DateTimeZone('UTC')));
} catch (TslSignatureException $e) {
fwrite(STDERR, "TSL rejected ({$e->reason}): {$e->getMessage()}" . PHP_EOL);
exit(1);
} catch (TslParseException $e) {
fwrite(STDERR, 'TSL unusable: ' . $e->getMessage() . PHP_EOL);
exit(1);
}
echo "Territory: {$tsl->schemeTerritory}\n";
echo "Sequence: {$tsl->sequenceNumber}\n";
echo 'Active services: ' . count($tsl->activeServices()) . "\n";

المخرجات المتوقعة (تختلف القيم حسب القائمة):

Territory: DE
Sequence: 127
Active services: 143

اربط خطّ الأنابيب الكامل عبر الإنترنت: جلب محمي مع تخزين مؤقت، والتحقق من التوقيع، والتحليل، والحداثة، ثم اشتقاق حزمة المراسي. يُلتقَط كل صنف فشل ويُبلَّغ عنه على نحو متمايز.

tsl-anchor-bundle-production.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use NextPDF\Enterprise\Security\NetworkPolicy;
use NextPDF\Enterprise\Security\NetworkPolicyViolation;
use NextPDF\Enterprise\Security\Tsl\TslFetchException;
use NextPDF\Enterprise\Security\Tsl\TslFetcher;
use NextPDF\Enterprise\Security\Tsl\TslParseException;
use NextPDF\Enterprise\Security\Tsl\TslPolicyEnforcer;
use NextPDF\Enterprise\Security\Tsl\TslSignatureException;
use NextPDF\Enterprise\Security\Tsl\TslSignatureVerifier;
use NextPDF\Enterprise\Security\Tsl\TslTrustAnchorProvider;
use NextPDF\Enterprise\Security\Tsl\TslXmlParser;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Psr16Cache;
// Any PSR-18 client, PSR-17 factory, and PSR-16 cache work; these are examples.
$enforcer = new TslPolicyEnforcer(
fetcher: new TslFetcher(
httpClient: new Client(),
requestFactory: new HttpFactory(),
cache: new Psr16Cache(new FilesystemAdapter('tsl')),
defaultTtlSeconds: 3600,
maxBytes: 16_777_216,
networkPolicy: NetworkPolicy::ONLINE,
),
verifier: new TslSignatureVerifier(
trustAnchorsPem: [(string) file_get_contents(__DIR__ . '/tsl-signer-anchor.pem')],
clockTolerance: 300,
),
parser: new TslXmlParser(),
);
// Use the official publication URL for your scheme territory (HTTPS required).
$tslUrl = 'https://trusted-lists.example.eu/member-state-tsl.xml';
$now = new DateTimeImmutable('now', new DateTimeZone('UTC'));
try {
$tsl = $enforcer->fetchAndVerify($tslUrl);
$bundle = (new TslTrustAnchorProvider())->buildBundle($tsl, $now);
} catch (NetworkPolicyViolation $e) {
// Air-gapped posture: egress forbidden and no cached body available.
fwrite(STDERR, 'Network policy: ' . $e->getMessage() . PHP_EOL);
exit(75);
} catch (TslFetchException $e) {
// Transport layer: SSRF-rejected URL, HTTP error, oversized or empty body.
fwrite(STDERR, 'Fetch failed: ' . $e->getMessage() . PHP_EOL);
exit(1);
} catch (TslSignatureException $e) {
// Authentication layer: treat as a potential attack, not a retry case.
fwrite(STDERR, "Signature rejected ({$e->reason}): {$e->getMessage()}" . PHP_EOL);
exit(1);
} catch (TslParseException $e) {
// Structure or freshness: stale list, malformed NextUpdate, no active CA/QC services.
fwrite(STDERR, 'List unusable: ' . $e->getMessage() . PHP_EOL);
exit(1);
}
printf(
"Anchor bundle %s: %d anchors (sha256 %s...)\n",
$bundle->bundleVersion,
count($bundle->anchorsPem),
substr($bundle->bundleSha256, 0, 12),
);

المخرجات المتوقعة (تختلف القيم حسب القائمة):

Anchor bundle tsl-de-seq127: 96 anchors (sha256 4b0e2a9f31c8...)

سجّل ⁨bundleVersion⁩ و⁨bundleSha256⁩ مع كل تحقق تجريه مقابل الحزمة. فهما يُسمّيان مجموعة المراسي الدقيقة وراء كل حُكم.

  • بوابة الحداثة في المُنفِّذ تستخدم الساعة الحالية. ترفض ⁨fetchAndVerify()⁩ و⁨verifyXml()⁩ أي قائمة مضت لحظة ⁨NextUpdate⁩ الخاصة بها. للتحقق التاريخي مقابل قائمة مؤرشفة، شغّل ⁨TslSignatureVerifier⁩ و⁨TslXmlParser⁩ مباشرةً، ثم استدعِ ⁨assertFresh()⁩ باللحظة الماضية التي يدعمها دليلك.
  • buildBundle()⁩ تعيد التأكيد على الحداثة عند ⁨$now⁩ الخاص بك. القائمة التي اجتازت المُنفِّذ يمكن أن تُرفَض هنا مع ذلك إن كانت لحظة تحققك لاحقة. راجع ملاحظة التوافق للخلف أعلاه.
  • لا تزرع أبداً ⁨trustAnchorsPem⁩ من القائمة التي تتحقق منها. يجب أن تأتي المرساة من مصدر مُثبَّت خارج النطاق (لأجل ⁨LOTL⁩) أو من قائمة أصل مُتحقَّق منها مسبقاً (لأجل قوائم ⁨TSL⁩ لدول أعضاء). أي شيء آخر يجعل التحقق دائرياً.
  • وجود ⁨DOCTYPE⁩ في أي مكان قاتل. قوائم ⁨TSL⁩ المطابِقة لا تحمل أبداً ⁨DTD⁩، لذا يرفض المحلّل أي ⁨DOCTYPE⁩ قبل أن يبني ⁨libxml⁩ جدول كيانات. هذا تحصين مقصود، وليس قيداً في المحلّل.
  • الحقول البنيوية المفقودة تتدهور بأمان. الخدمة التي بلا حالة قابلة للقراءة تُعامَل كأنها مسحوبة، فلا يمكنها أبداً أن تصبح مرساة. إقليم المخطط المفقود يُحلَّل كـ ⁨unknown⁩. الإعدادات الافتراضية فاشلة-الإغلاق تُبقي المُدخَلات المشوّهة خارج مادة الثقة.
  • يجب أن تكون الوسائط سلطات تصديق حقيقية. أثناء بناء السلسلة، يُتخطّى أي مُصدِر مرشّح بلا ⁨basicConstraints cA=TRUE⁩ (أو يؤكّد ⁨keyUsage⁩ دون ⁨keyCertSign⁩). شهادة كيان طرفي مُهرَّبة إلى ⁨KeyInfo⁩ لا يمكن أن تعمل كوسيط مسار. تُحدَّد السلاسل بعمق 8.
  • يجب أن تكون ⁨NextUpdate⁩ بتوقيت ⁨UTC⁩ قانوني. القيمة التي بلا ⁨Z⁩ صريح أو إزاحة رقمية تُطلِق ⁨TslParseException⁩. ولا يُعاد تفسيرها أبداً في المنطقة الزمنية المحلية للخادم.
  • القوائم الكبيرة وسقف البايتات. تُقرأ الاستجابات حتى ⁨$maxBytes⁩ (الافتراضي 16 ⁨MiB⁩). ارفع السقف في المُنشئ إن كانت قائمة مخططك أكبر؛ يظهر البتر بوصفه فشلاً في التوقيع، لا قبولاً صامتاً أبداً.
  • clockTolerance⁩ توسّع فقط. فهي تضيف تراخياً متناظراً إلى فحوص صلاحية الشهادة. ولا ترخي بوابة الحداثة على مستوى القائمة.
  • تحقّق قبل التحليل، دائماً.TslXmlParser⁩ لا يكترث بالتوقيع بحكم التصميم. يرتّب ⁨TslPolicyEnforcer⁩ التحقق أولاً؛ وإن ركّبت القطع بنفسك، فاحفظ ذلك الترتيب.
  • دفاع ⁨SSRF⁩ متعدد الطبقات. تتطلّب ⁨fetch()⁩ ⁨https://⁩ وتتحقق من المضيف مقابل نطاقات خاصة، وحلقة راجعة، ومحلية-الوصلة، و⁨CGN⁩، وبيانات-تعريف السحابة، مع تحليل ⁨DNS⁩ للسجلّين ⁨A⁩ و⁨AAAA⁩ للتخفيف من إعادة الربط. عنوان ⁨URL⁩ المرفوض يُطلِق استثناءً قبل أي خروج.
  • تحصين ضد ⁨XXE⁩ وتوسّع الكيانات. تُرفَض المستندات الحاملة لـ ⁨DOCTYPE⁩ قبل وجود جدول الكيانات ومرة أخرى بعد التحميل. تحميل كيانات الشبكة مُعطَّل؛ ولا تُستبدَل الكيانات الخارجية أبداً.
  • ملف ⁨XMLDSig⁩ صارم. ⁨exclusive C14N⁩ فقط؛ وبالضبط زوج التحويل ⁨[enveloped-signature, exclusive-C14N]⁩؛ ويجب أن يغطي المرجع المُتحقَّق منه جذر المستند؛ ويزيل تحويل ⁨enveloped⁩ التوقيع المُتحقَّق منه فقط، مع الحفاظ على التوقيعات الشقيقة. تُرفَض الخوارزميات المهملة (⁨SHA-1⁩، ⁨MD5⁩).
  • انضباط السلسلة. يُفحَص كل رابط في السلسلة — المُوقِّع، والوسائط، وحالة المرساة المباشرة — للتحقق من الصلاحية الزمنية، فشلاً مغلقاً عند حدود صلاحية غير قابلة للتحليل. تُكتشَف الحلقات؛ ويُحدَّد العمق.
  • وضعية العزل الشبكي. تحت ⁨NetworkPolicy::STRICT_OFFLINE⁩، لا يُجري مسار الجلب أي خروج صادر على الإطلاق؛ ولا يمكن تقديم سوى جسم مُخزَّن مؤقتاً سابقاً، وأي شيء آخر يُطلِق ⁨NetworkPolicyViolation⁩ فشلاً سريعاً.
  • ملخّصات الحزمة تكتشف التلف، لا العبث. يُتحقَّق من ⁨bundleSha256⁩ عند الإنشاء ويكتشف انحراف النسخ. وعندما يُشتَق الملخّص من المراسي نفسها التي يحميها، فهو ليس دليل عبث مستقلاً. ثبّت الملخّصات خارج النطاق عند نقل الحزم بين الأنظمة.

يستهلك خطّ الأنابيب القوائم الموثوقة كما يعرّفها ⁨ETSI TS 119 612⁩: فهو يصادق على توقيع مشغّل المخطط (⁨§5.7⁩)، ويحلّل معلومات المخطط وبنى قائمة المزوّدين (⁨§5.3⁩، ⁨§5.4⁩، ⁨§5.5⁩)، ويفرض قواعد ⁨dateTime⁩ بتوقيت ⁨UTC⁩ (⁨§5.1.3⁩)، ويُهمِل القوائم التي مضت لحظة ⁨NextUpdate⁩ الخاصة بها (⁨§5.3.15⁩). هذا يدعم نموذج المادة 22 من ⁨eIDAS⁩ للقوائم الموثوقة الموقَّعة القابلة للمعالجة الآلية. يطبّق بناء السلسلة بوابات القيود الأساسية واستخدام المفتاح في ⁨RFC 5280⁩ على المُصدِرين المرشّحين.

الدعم ليس مطابقة، والمطابقة ليست اعتماداً. ينفّذ ⁨NextPDF⁩ الفحوص التي تصفها هذه الصفحة؛ ولم يُعتمَد مقابل ⁨ETSI TS 119 612⁩ أو ⁨eIDAS⁩ أو أي معيار آخر من قِبل أي جهة، ولا يحمل ⁨NextPDF⁩ أي اعتماد ولا يمنح أياً منه. استهلاك قائمة موثوقة عبر واجهة ⁨API⁩ هذه لا يجعل التوقيع بحد ذاته «مؤهلاً» أو ساري المفعول قانونياً. وأما ما إذا كانت عملية التحقق الكاملة لديك تفي بمتطلب قانوني أو متطلب مشتريات فهو قرار يعود إلى مُقيِّميك.

يشغّل التحقق من توقيع ⁨TSL⁩ فحوص ⁨RSA⁩ و⁨ECDSA⁩ داخل العملية عبر مكتبة التعمية المُضمَّنة. ولا يُوجَّه عبر حارس زمن التشغيل لوضع ⁨FIPS⁩ في ⁨Enterprise⁩، وتفعيل وضع ⁨FIPS⁩ لا يغيّر سلوكه. وهو ليس خدمة تعمية مُصدَّقة بـ ⁨FIPS⁩، ولا يُدَّعى أي اعتماد ⁨FIPS 140⁩. يجب على عمليات النشر ذات التزامات ⁨FIPS⁩ تحديد نطاق واجهة ⁨API⁩ هذه وفقاً لذلك ومراجعة سياسة التعمية FIPS 140-2/3.

  • تُجري ⁨fetch()⁩ خروجاً فقط لعناوين ⁨URL⁩ من نوع ⁨HTTPS⁩ التي تجتاز تحقق ⁨SSRF⁩، وتقرأ ⁨$maxBytes⁩ كحد أقصى، وتحترم ⁨NetworkPolicy⁩ المُعدَّة؛ وتحت ⁨STRICT_OFFLINE⁩ لا يُرجَع سوى جسم مُخزَّن مؤقتاً على الإطلاق.
  • لا تصبح أي مخرجات محلّل مادةَ ثقة قبل نجاح ⁨verify()⁩؛ ويضمن ⁨TslPolicyEnforcer⁩ ذلك الترتيب.
  • تُرجِع ⁨verify()⁩ صيغة ⁨PEM⁩ للمُوقِّع فقط عندما يُثبَت صحة الملخّص والتوقيع تحت الملف الثابت ويتسلسل المُوقِّع، ضمن عمق 8 ومع صلاحية زمنية لكل رابط، إلى مرساة مُعدَّة.
  • يرفض المُنفِّذ أي قائمة مضت لحظة ⁨NextUpdate⁩ الخاصة بها عند الساعة الحالية؛ وتعيد ⁨buildBundle()⁩ التأكيد على الحداثة عند اللحظة التي يوفّرها المستدعي قبل اشتقاق المراسي.
  • تُشتَق المراسي حصراً من الخدمات ذات حالة granted من نوع خدمة ⁨CA/QC⁩؛ والمجموعة النشطة الفارغة تُطلِق استثناءً بدلاً من إنتاج حزمة فارغة.
  • كل فشل هو استثناء مُصنَّف النوع (⁨TslFetchException⁩، و⁨NetworkPolicyViolation⁩، و⁨TslSignatureException⁩ برمز سبب، و⁨TslParseException⁩)؛ ولا تُرجِع أي طريقة مستنداً جزئياً أو غير مُتحقَّق منه.

يتحقق ⁨NextPDF Core⁩ من توقيعات ⁨PDF⁩ مقابل مراسي ثقة تثبّتها صراحةً عبر عقده ⁨CaTrustAnchorBundle⁩ — راجع أمان Core. لا يملك ⁨Core⁩ أي قدرة على القوائم الموثوقة: لا جلب ⁨TSL⁩، ولا مصادقة قوائم ⁨XMLDSig⁩، ولا تحليل ⁨ETSI TS 119 612⁩، ولا اشتقاق مراسٍ من مُدخَلات الخدمة المؤهلة. مع ⁨Core⁩ وحده تحافظ على مجموعة مراسيك يدوياً؛ واشتقاقها من قوائم الاتحاد الأوروبي الموثوقة المُصادَق عليها يتطلّب ⁨NextPDF Enterprise⁩.

توثّق هذه الصفحة السلوك القابل للملاحظة خارجياً وواجهة ⁨API⁩ العامة المدعومة فقط. أما مسارات مساحات الأسماء الداخلية، والأصناف المساعِدة، وجداول الآليات، وأسماء ملفات كتيّبات التشغيل، وبادئات التذاكر فهي خارج النطاق.