الأمان والتشغيل في compat-legacy
لمحة سريعة
قسم بعنوان «لمحة سريعة»يستخدم المحوِّل نموذج الأمان الخاص بمحرِّك NextPDF، ويضيف بعض إجراءات التحصين المقصودة فوق TCPDF 6.2.13 القديم. توضِّح هذه الصفحة بدقة ما هو متاح وما هو غير متاح، من غير مبالغة. اقرأ قسم التوقيع بعناية؛ فنطاقه محدود عن قصد.
السلوكيات القديمة المُحصَّنة
قسم بعنوان «السلوكيات القديمة المُحصَّنة»يغيِّر المحوِّل ثلاثة سلوكيات تاريخية في TCPDF 6.2.13 لأسباب تتعلق بالسلامة. وهذه السلوكيات غير قابلة للضبط للرجوع إلى الصيغة غير الآمنة:
| المجال محل الاهتمام | TCPDF 6.2.13 القديم | المحوِّل |
|---|---|---|
| معالجة الأخطاء | يستدعي Error() الدالة die() وينهي العملية | يطرح Error() استثناء RuntimeException؛ ويمكن للمستدعِين رصد الفشل والتعامل معه، من غير إنهاء العملية بصمت. |
| تنفيذ HTML | يمكن لمنفذ التفلُّت أن يشغِّل PHP من الترميز | الثابت K_TCPDF_CALLS_IN_HTML مُثبَّت على false؛ ولا يمكن للترميز أن يطلق تنفيذ PHP. |
| الإخراج المباشر | يطبع Output() إلى مخزن الإخراج النشط | يمر الإخراج عبر جسر وجهة آمن، ولا يلوِّث مخزن إخراج يتحكم فيه المستدعِي. |
يضمن تغيير معالجة الأخطاء إمكانية رصد الفشل بدلاً من فقدان العملية بسبب الإنهاء. ينص معيار التحقق من أمان التطبيقات (ASVS) 5.0 الصادر عن مشروع أمان تطبيقات الويب المفتوح عالميًا (OWASP) في §16.5.3 على أن التطبيق ينبغي أن يفشل بسلاسة وبأمان، وأن يمنع حالات الفشل المفتوح. يطبِّق تغيير “الطرح بدلاً من الإنهاء” هذا المبدأ. ويزيل تحصين HTML منفذًا كان يتيح تنفيذ الشيفرة. عامِل الشيفرة القديمة التي اعتمدت على السلوك القديم باعتبارها خللاً يجب إصلاحه أثناء /integrations/tcpdf-compat/migration/. يوجد ملخص البند المثبَّت في مقدمة الصفحة citations.
التشفير
قسم بعنوان «التشفير»يكشف المحوِّل دالة SetProtection() الخاصة بـ TCPDF، ويفوِّض إلى معالج الأمان القياسي لمحرِّك NextPDF.
- يستخدم المعالج القياسي AES-256. يُقبَل المعامل القديم
$modeمن أجل توافق توقيع الدالة ويُتجاهَل؛ ولا توجد طريقة لاختيار شيفرة تشفير أضعف عبر هذه الدالة. عند تفعيل الوضع الصارم، يطرح$modeغير الافتراضي استثناءً، بحيث تُجبَر عملية الترحيل على الإقرار به (مؤكَّد فيtests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php). - إذا لم تُقدَّم كلمة مرور للمالك، يولِّد المحوِّل كلمة مرور مالك عشوائية وقوية تشفيريًا بدلاً من إعادة استخدام كلمة مرور المستخدم. يمنع هذا حائزي الوصول بمستوى المستخدم من الحصول على تحكُّم بمستوى المالك في المستند.
- لا يُجرى التشفير المستند إلى الشهادات (المفتاح العام) عبر
SetProtection()؛ إذ يتجاهل المحوِّل معاملها$pubkeys. استخدم نقطة دخول تشفير المفتاح العام الحديثة المكشوفة على المحوِّل (setPublicKeyEncryption())، فهي تفوِّض إلى المحرِّك.
يعكس سلوك التشفير معالج الأمان القياسي الموصوف في ISO 32000-2 §7. يعرِّف ذلك البند مدخلات قاموس التشفير ومعالج AES-256 القياسي الذي يستخدمه المحرِّك. لا يدّعي هذا التوثيق أن المُخرَج “آمن افتراضيًا” أو “مقاوم للعبث”. بل يوضِّح فقط شيفرة التشفير المستخدمة وسلوك كلمة مرور المالك الذي تنفِّذه الشيفرة. يوجد ملخص البند المثبَّت في مقدمة الصفحة citations.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->AddPage();$pdf->SetFont('helvetica', '', 12);$pdf->Cell(0, 10, 'Encrypted document');
// User password set; owner password auto-generated (strong, random).$pdf->SetProtection([], 'user-secret');
$pdf->Output(__DIR__ . '/encrypted.pdf', 'F');التوقيعات الرقمية — بيان النطاق
قسم بعنوان «التوقيعات الرقمية — بيان النطاق»اقرأ هذا القسم بحرفية. فهو محافظ عن قصد.
- دالتا TCPDF القديمتان
setSignature()وaddEmptySignatureAppearance()غير مُنفَّذتين في المحوِّل على المحرِّك الأساسي. في الوضع الافتراضي، لا تنفِّذان أي إجراء. في الوضع الصارم، تطرحانTcpdfNotImplementedException. - التوقيع الرقمي ليس قدرة من قدرات التوزيعة الأساسية عبر هذا المحوِّل. يتطلب دعم التوقيع الأساسي إصدارًا تجاريًا من NextPDF.
- إذا كان إصدار تجاري متاحًا، يكشف المحوِّل نقطة دخول توقيع حديثة (
setSignatureV2()) تفوِّض إلى المحرِّك. ملفه الافتراضي هو الملف الأساسي (B-B). - لا يقدِّم هذا التوثيق أي ادعاء بأن أي إصدار ينتج ملفات توقيع ذات طابع زمني أو ذات تحقُّق طويل الأمد أو أرشيفية عبر هذا المحوِّل. وتحديدًا، لا يؤكِّد سلوك B-T أو B-LT أو B-LTA. تعرِّف المواصفة الأساسية للتوقيعات الإلكترونية المتقدمة في PDF (PAdES) في §6.1 أربعة مستويات أساسية متمايزة: B-B وB-T وB-LT وB-LTA. ولكل منها متطلباته الخاصة. B-B هو المستوى الأساسي، أما المستويات الأعلى (الطابع الزمني، طويل الأمد، الأرشيفي) فهي ملفات منفصلة وأكثر تطلُّبًا. المستوى الأساسي B-B وحده يقع ضمن نطاق توثيق طبقة التوافق هذه. أما المستويات الأعلى فهي خارج النطاق صراحةً، ولا يُدَّعى بها لأي إصدار هنا. يوجد ملخص البند المثبَّت في مقدمة الصفحة
citations. - لا يقدِّم هذا التوثيق في أي موضع أي ادعاء بتوقيع “مُصدَّق” أو “مضمون” أو “صالح قانونيًا” أو “مؤهَّل وفق eIDAS”. صحة التوقيع، وسياسة مرتكز الثقة، والصلاحية القانونية مسؤولية إصدار التوقيع والبنية التحتية للمفتاح العام (PKI) الخاصة بالمستدعِي، وليست مسؤولية طبقة التوافق هذه.
إذا تطلَّب ترحيلك التوقيع، فعامِله باعتباره مسار عمل منفصلاً: اعتمد واجهة برمجة التطبيقات (API) الحديثة للتوقيع في إصدار تجاري، وتحقَّق من التوقيع الناتج باستخدام مُدقِّق مستقل. لا تعتمد على استدعاء TCPDF setSignature()؛ فهو بلا أثر هنا.
تُقبَل الدالة القديمة setTimeStamp() من أجل توافق توقيع الدالة وتُصدِر تنبيهًا؛ وهي لا تنتج توقيعًا ذا طابع زمني عبر هذا المحوِّل.
PDF/A والمطابقة
قسم بعنوان «PDF/A والمطابقة»يُقبَل علم pdfa في المُنشئ من أجل توافق توقيع الدالة. تتطلب مطابقة الأرشفة وفق PDF/A إصدارًا تجاريًا من NextPDF. يكشف المحوِّل enablePdfA()، التي تفوِّض إلى المحرِّك، ويعيد المحرِّك خطأ تهيئة قابلاً للمعالجة عند غياب الإصدار المطلوب. لا ينتج المحوِّل بصمت ملفًا غير مطابق مع ادعاء مطابقة PDF/A.
المُخرَج دائمًا PDF 2.0 (ISO 32000-2). يحدِّد ISO 32000-2 §7.5.2 أن الكاتب المطابق يعرِّف إصدار المستند بأنه 2.0، ولا يخفِّضه إلى إصدار أقدم عند الحفظ. ومن ثَمَّ، لا يمكن لـ setPDFVersion() أن يستهدف إصدارًا أقدم (انظر /integrations/tcpdf-compat/method-coverage/ §4). يوجد ملخص البند المثبَّت في مقدمة الصفحة citations.
الإرشادات التشغيلية
قسم بعنوان «الإرشادات التشغيلية»- لا إنهاء للعملية. لأن
Error()يطرح استثناءً بدلاً منdie()، غلِّف نقاط دخول العرض بـtry/catch، وحوِّل حالات الفشل إلى عقد الأخطاء في تطبيقك. لا تفترض أن فشل العرض ينهي الطلب. - سلامة مخزن الإخراج. يعيد
Output()معSبايتات؛ ومعFيكتب ملفًا؛ ومعEيعيد متن امتدادات بريد الإنترنت متعددة الأغراض (MIME) بترميز base64؛ ومعI/Dيوجِّه عبر مسار إخراج المحرِّك. فضِّلSأوFفي العمَّال ومعالِجات بروتوكول نقل النص التشعبي (HTTP) لتتحكم في الاستجابة بنفسك؛ انظر /integrations/tcpdf-compat/production-usage/. - الوضع الصارم ليس إعدادًا للإنتاج. اقصره على مهمة تكامل مستمر (CI) أو مهمة تدقيق. فالاستثناء في مسار عرض إنتاجي أسوأ من معامل مُتدنٍّ بصمت.
- نظافة الثوابت. عرِّف ثوابت
PDF_*/K_*قبل أول إنشاء للمحوِّل. لا يمكن تخفيف العلمين المُحصَّنين (K_TCPDF_CALLS_IN_HTMLوK_TCPDF_THROW_EXCEPTION_ERROR)؛ فلا تحاول تخفيفهما. - كلمات مرور المالك العشوائية. إذا كنت تعتمد على كلمة مرور مالك حتمية، فعيِّنها صراحةً. وإلا، تُولَّد كلمة قوية عشوائية لكل مستند ولا يمكن استرجاعها.
ملاحظات نموذج التهديد
قسم بعنوان «ملاحظات نموذج التهديد»- بالنسبة لدوال الصور، يرفض المحوِّل مسار غلاف الدفق قبل أي قراءة من نظام الملفات. يعامل كشف نوع الصورة (
TcpdfImages::getImageFileType) أي مسارscheme://، بما في ذلكphar://وphp://وغيرها من أغلفة دفق PHP، باعتباره غلافًا، ويتخطى فحصfile_get_contents/getimagesize، ثم يرجع إلى الاستدلال بالامتداد وحده. يُغلق هذا متجه فك تسلسل بيانات phar الوصفية على هدف النقل العكسي إلى PHP 7.4؛ ويرفض المحرِّك نفسه تضمين مسار الغلاف. - لا يضيف المحوِّل تحققًا من المسارات أو تطهيرًا لها لمسارات الملفات المُمرَّرة إلى دوال الصور أو الإخراج بما يتجاوز ما يفعله المحرِّك. عامِل المسارات وعناوين URL التي يقدِّمها المستدعِي باعتبارها غير موثوقة عند حدود تطبيقك.
- يعرض المحرِّك ما يُمرَّر من HTML إلى دوال HTML، وليس مُحلِّل HTML الخاص بـ TCPDF. منفذ تنفيذ PHP القديم مُغلق، لكن ينبغي لك مع ذلك أن تعامل ما يقدِّمه المستدعِي من HTML باعتباره مُدخلاً غير موثوق.
- يحمي التشفير سرية المستند أثناء سكونه في ظل المعالج القياسي. وهو ليس بديلاً عن أمان النقل أو التحكم في الوصول في تطبيقك.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- /integrations/tcpdf-compat/method-coverage/ — السلوك الدقيق لـ
SetProtection()وsetSignature() - /integrations/tcpdf-compat/configuration/ — العلمان المُحصَّنان غير القابلين للضبط
- /integrations/tcpdf-compat/production-usage/ — العمَّال، والمخازن، ومعالجة الفشل
docs/TCPDF_COVERAGE.md— مصفوفة التغطية المرجعية- ملف
NOTICEالخاص بالحزمة — بيان التنفيذ المستقل