كيفية إضافة توقيعات أمان PDF في Python

كيفية إضافة توقيعات أمان PDF في Python

Aspose.PDF FOSS لـ Python يتضمن كاشفاً لتعرّض التوقيع للخلل يقوم بفحص ملف PDF موقع مسبقاً للبحث عن نمط تلاعب محدد: بايتات ذات معنى تُضاف بعد نطاق البايتات الموقعة للتوقيع، وهو خطر فريد للملفات PDF التي تُحدَّث بشكل تدريجي. يضيف هذا الدليل هذا الفحص إلى سير عمل Python باستخدام فئتي SignaturesCompromiseDetector وCompromiseCheckResult. إنشاء أو تطبيق توقيعات رقمية جديدة هو جزء منفصل من المكتبة ولا يتم تغطيته هنا. تُثبت المكتبة بالأمر أدناه.

دليل خطوة بخطوة

الخطوة 1: تثبيت الحزمة

تثبيت حزمة Aspose.PDF FOSS:

git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .

تحقق من التثبيت عن طريق استيراد SignaturesCompromiseDetector وطباعة رسالة تأكيد:

from aspose_pdf import SignaturesCompromiseDetector
print("aspose-pdf-foss-for-python is ready.")

الخطوة 2: استيراد الفئات المطلوبة

from aspose_pdf import CompromiseCheckResult, SignaturesCompromiseDetector

الخطوة 3: إعداد كائن يعرض قائمة التواقيع

SignaturesCompromiseDetector لا يقوم بتحليل PDF بنفسه — مُنشئه يقبل أي كائن يعرض سمة signatures: قائمة من إدخالات التوقيع، كل واحدة تحمل valid، byte_range، وreference_data. PdfSignature — فئة بسيطة قابلة للبناء مباشرة — تتطابق مع هذا الشكل، لذا هي مفيدة لرؤية كيفية سلوك الفحص قبل ربطه بكائن المستند الخاص بك:

from types import SimpleNamespace
from aspose_pdf import PdfSignature

with open("signed.pdf", "rb") as handle:
    pdf_bytes = handle.read()

signature = PdfSignature(
    name="Signature1",
    contents=b"...",  # PKCS#7 signed-data blob from the signature dictionary
    byte_range=[0, 1024, 1040, len(pdf_bytes) - 1040],
    reference_data=pdf_bytes,
)

signed_document = SimpleNamespace(signatures=[signature])

استبدل signed_document بكائن المستند الخاص بك بمجرد أن يعرض قائمة signatures بنفس الشكل — أي كائن يحمل تلك السمة يعمل.


الخطوة 4: تشغيل فحص الاختراق

from aspose_pdf import SignaturesCompromiseDetector

detector = SignaturesCompromiseDetector(signed_document)
result = detector.check()

print(result.compromised)                # bool
print(result.has_compromised_signatures)  # bool -- same value as compromised
print(result.signatures_coverage)         # int -- number of signatures inspected
print(result.reasons)                     # list[str] -- human-readable findings

check() يتجول عبر كل توقيع في signed_document.signatures، باحثًا عن محتوى غير موقع مضاف بعد نطاق البايتات الموقعة لكل توقيع. CompromiseCheckResult يلخص النتيجة: compromised وhas_compromised_signatures يبلغان نفس القيمة المنطقية تحت اسميْن، signatures_coverage يوضح عدد التواقيع التي تم فحصها، وreasons يسرد شرحًا قابلًا للقراءة البشرية لكل مشكلة تم العثور عليها.


الخطوة 5: معالجة مستند لا يحتوي على تواقيع

قائمة signatures فارغة أو مفقودة ليست حالة خطأ — يتم الإبلاغ عنها بنفس الطريقة كما هو الحال مع مستند لا شيء ليتم فحصه:

from types import SimpleNamespace
from aspose_pdf import SignaturesCompromiseDetector

unsigned_document = SimpleNamespace(signatures=[])
detector = SignaturesCompromiseDetector(unsigned_document)
result = detector.check()

print(result.compromised)  # False
print(result.reasons)      # ["unsigned document"]

تمرير SignaturesCompromiseDetector(None) — القيمة الافتراضية للمنشئ — يتصرف بنفس الطريقة.

المشكلات الشائعة والحلول

compromised is False لملف PDF تعلم أنه تم تحريره بعد التوقيع

SignaturesCompromiseDetector يبحث تحديدًا عن بايتات غير موقعة مضافة بعد نطاق البايتات الموقعة للتوقيع — نمط شائع في التلاعب السطحي بالتحديثات المتزايدة. لا يقوم بإجراء تحقق كامل من التوقيع التشفيري. للقيام بذلك، استدعِ validate() على كائن PdfSignature الفردي.

compromised and has_compromised_signatures تبدو مكررة

هما نفس القيمة: compromised هي خاصية محسوبة تُعيد has_compromised_signatures. استخدم أيًا من الاسمين يقرأ بشكل أفضل في كودك.

لا يتم رفع أي استثناء عندما لا يحتوي المستند على signatures سمة على الإطلاق

SignaturesCompromiseDetector يتعامل مع مستند لا يحتوي على سمة signatures، أو document=None، كأنه مستند غير موقع — check() تُرجع نتيجة تحتوي على has_compromised_signatures=False وreasons=["unsigned document"] بدلاً من إلقاء استثناء.

ملف غير صالح PdfSignature لا يتم الإبلاغ عنه

check() يتخطى أي توقيع يكون byte_range الخاص به ليس قائمة مكوّنة من 4 عناصر، أو يكون reference_data الخاص به ليس bytes/bytearray، بدلاً من إلقاء استثناء أو الإبلاغ عنه كمخترق. يتم استبعاد التوقيع المبني بالشكل الخاطئ صامتًا من الفحص، دون وضع علامة.

خلط هذا الكاشف مع إنشاء التوقيع

SignaturesCompromiseDetector وCompromiseCheckResult يفحصان فقط التواقيع الموجودة بالفعل على المستند — لا يمتلكان طريقة لإنشاء أو تطبيق أو تضمين توقيع جديد.

الأسئلة المتكررة

ما الذي يُعد “مخترقًا” بالضبط هنا؟

بايتات ذات معنى، غير فارغة، تُضاف إلى ملف PDF بعد نطاق البايتات الموقَّعة للتوقيع — مع استثنائين يُراعهما الكاشف بالفعل: توقيع لاحق أو طابع زمني يغطي تلك البايتات بنفسه، وتحديث تدريجي يضيف فقط مادة تحقق (مثل /DSS) دون إضافة محتوى جديد مثل التعليقات التوضيحية.

هل يتحقق هذا من الصلاحية التشفيرية للتوقيع نفسه؟

لا. SignaturesCompromiseDetector يتحقق من أنماط التلاعب حول نطاق البايت الموقَّع. الصلاحية التشفيرية هي فحص منفصل، متاح عبر PdfSignature.validate().

ماذا يخبرني signatures_coverage؟

عدد التوقيعات التي فحصها الفحص فعليًا في المستند المُدخل — مفيد لتأكيد أن الكاشف رأى التوقيعات التي كنت تتوقعها قبل الوثوق بنتيجة نظيفة.

هل يمكنني فحص مستند يحتوي على توقيعات متعددة مرة واحدة؟

نعم. check() يكرر كل إدخال في signed_document.signatures ويعيد CompromiseCheckResult مجمّعًا يغطيها جميعًا.

هل أحتاج إلى إنشاء كائنات PdfSignature بنفسي في الاستخدام العادي؟

لا — إنشاء PdfSignature في الخطوة 3 مخصص لاستكشاف سلوك الكاشف مباشرة. في سير عمل حقيقي، مرّر أي كائن ينتجه رمز تحميل المستندات الخاص بك، طالما أنه يوفّر قائمة signatures من الإدخالات ذات الشكل PdfSignature.

انظر أيضاً

 العربية