التوقيع الرقمي يسجل من قام بتوقيع المستند. يُسجل الطابع الزمني الموثوق متى، ويأتي هذا الوقت من سلطة طابع زمني مستقلة (TSA) بدلاً من ساعة جهاز الكمبيوتر الخاص بالموقع. يوضح هذا الدليل كيفية توقيع مستند Word بتوقيع XAdES‑T مُؤرّخ في Python، ثم تأكيد وجود الطابع الزمني في الملف.

النقاط الرئيسية

  • قم بتعيين كلا SignOptions.xml_dsig_level = XmlDsigLevel.X_AD_ES_T و SignOptions.timestamp_settings. أي منهما بمفرده ينتج توقيعًا بدون طابع زمني، ولا يُظهر أي خطأ ذلك.
  • Aspose.Words يطلب الطابع الزمني أثناء DigitalSignatureUtil.sign، لذا يحتاج هذا الاستدعاء إلى اتصال شبكة بـ TSA.
  • يمكن إضافة طابع زمني لملفات DOCX وDOC. لا يمكن ذلك لملفات ODT.
  • DigitalSignature.is_valid يتحقق من التوقيع، وليس من الطابع الزمني. تأكد من الطابع الزمني بشكل منفصل.

ما الذي يضيفه الطابع الزمني الموثوق إلى التوقيع

كل توقيع تقوم Aspose.Words بإنشائه يحمل وقت توقيع، يتم تعيينه بواسطة SignOptions.sign_time. هذه القيمة تأتي من جهاز الموقّع، لذا أي شخص يعترض على المستند يمكنه الاعتراض على الوقت أيضًا.

تضيف توقيع XAdES-T دليلًا مستقلاً. بعد توقيع المستند، Aspose.Words يرسل تجزئة قيمة التوقيع إلى TSA. تُعيد TSA رمز RFC 3161، موقّعًا بشهادتها الخاصة، الذي يربط التجزئة بوقت محدد. يتم تخزين هذا الرمز داخل التوقيع. يمكن للمُتحقق بعد ذلك إظهار أن التوقيع كان موجودًا في تلك اللحظة، وهو ما يهم أكثر عندما تنتهي صلاحية شهادة التوقيع لاحقًا أو تُسحب.

المتطلبات المسبقة

قبل تشغيل المثال، تأكد من أنك تمتلك:

pip install --upgrade "aspose-words>=26.9"
  • شهادة توقيع بتنسيق PKCS#12 (.pfx أو .p12) وكلمة المرور الخاصة بها.
  • عنوان URL لسلطة الطوابع الزمنية. يستخدم المثال FreeTSA (https://freetsa.org/tsr)، وهي خدمة TSA عامة مجانية ومناسبة للاختبار. للمستندات الإنتاجية، استخدم TSA التي توصي بها مؤسستك أو موفر الشهادة، لأن الأشخاص الذين يتحققون من مستنداتك يجب أن يثقوا بشهادة تلك الـ TSA.
  • بيانات اعتماد TSA، فقط إذا كانت الـ TSA الخاصة بك تتطلب المصادقة.

بدون ترخيص، يعمل Aspose.Words في وضع التقييم مع قيود. ترخيص مؤقت يزيلها أثناء الاختبار.

توقيع مستند Word بطابع زمني موثوق

النص التالي يوقع ملف DOCX بتوقيع XAdES‑T ويضمّن طابعًا زمنيًا من TSA.

import datetime
import aspose.words as aw

# Replace these values with your own files and credentials.
INPUT_DOC = "contract.docx"
OUTPUT_DOC = "contract-signed.docx"
CERT_FILE = "signing-cert.pfx"
CERT_PASSWORD = "your-pfx-password"

TSA_URL = "https://freetsa.org/tsr"
TSA_USER = ""       # Fill in only if your TSA requires authentication.
TSA_PASSWORD = ""

# Load the signing certificate from a PKCS#12 file.
cert_holder = aw.digitalsignatures.CertificateHolder.create(
    file_name=CERT_FILE, password=CERT_PASSWORD)

# Request an XAdES-T signature and point it at a timestamp authority.
sign_options = aw.digitalsignatures.SignOptions()
sign_options.xml_dsig_level = aw.digitalsignatures.XmlDsigLevel.X_AD_ES_T
sign_options.timestamp_settings = aw.digitalsignatures.DigitalSignatureTimestampSettings(
    server_url=TSA_URL,
    user_name=TSA_USER,
    password=TSA_PASSWORD,
    timeout=datetime.timedelta(seconds=60),  # Default is 100 seconds.
)

# Sign the document. Aspose.Words contacts the TSA during this call.
aw.digitalsignatures.DigitalSignatureUtil.sign(
    src_file_name=INPUT_DOC,
    dst_file_name=OUTPUT_DOC,
    cert_holder=cert_holder,
    sign_options=sign_options,
)
print(f"Signed with a trusted timestamp: {OUTPUT_DOC}")

كيف يعمل الكود

  • CertificateHolder.create يقرأ المفتاح الخاص وسلسلة الشهادات من ملف .pfx. كلمة مرور خاطئة تفشل هنا، قبل بدء أي توقيع.
  • XmlDsigLevel.X_AD_ES_T يخبر Aspose.Words بإنشاء توقيع XAdES‑T، وهو XAdES‑EPES مع طابع توقيع زمني.
  • DigitalSignatureTimestampSettings يحتوي على عنوان URL الخاص بـ TSA، واسم مستخدم وكلمة مرور اختياريين، ووقت انتظار اختياري. السلاسل الفارغة مقبولة لـ TSA الذي يقبل الطلبات المجهولة. إذا رد TSA بتحدي مصادقة HTTP، فإن Aspose.Words يرسل بيانات الاعتماد التي قدمتها.
  • DigitalSignatureUtil.sign يكتب نسخة موقعة إلى OUTPUT_DOC ويترك ملف الإدخال دون تغيير. توقيع مستند غير موقع: إذا كان الإدخال يحتوي بالفعل على توقيع، فإن الإخراج يحتوي على كل من التوقيع الموجود والتوقيع الجديد.

تحقق من أن الطابع الزمني تم تضمينه

الكائنات DigitalSignature التي تُعيدها Aspose.Words لا تعرض الطابع الزمني، ولا يتحقق is_valid منه. في الاختبار، وثيقة كان رمز الطابع الزمني الخاص بها قد تم إفساده عمدًا لا تزال تُظهر is_valid كـ True. لتأكيد الطابع الزمني، انظر داخل XML التوقيع المخزن في حزمة DOCX:

import base64
import re
import zipfile
import aspose.words as aw

SIGNED_DOC = "contract-signed.docx"

# 1. Check the signature itself.
for sig in aw.digitalsignatures.DigitalSignatureUtil.load_signatures(SIGNED_DOC):
    print(f"Signer: {sig.subject_name} | valid: {sig.is_valid}")

# 2. Check that a timestamp token was embedded, and save it for inspection.
with zipfile.ZipFile(SIGNED_DOC) as package:
    for part in package.namelist():
        if part.startswith("_xmlsignatures/sig") and part.endswith(".xml"):
            xml = package.read(part).decode("utf-8")
            match = re.search(r"<(?:\w+:)?EncapsulatedTimeStamp[^>]*>([^<]+)<", xml)
            if match:
                with open("timestamp-token.der", "wb") as f:
                    f.write(base64.b64decode(match.group(1)))
                print(f"{part}: timestamp embedded (saved to timestamp-token.der)")
            else:
                print(f"{part}: no timestamp found")

بالنسبة إلى ملف DOCX موقع، يجب أن ترى مخرجات مشابهة لهذا:

Signer: CN=Your Name | valid: True
_xmlsignatures/sig1.xml: timestamp embedded (saved to timestamp-token.der)

لقراءة الوقت الذي تم تصديقه من قبل TSA، مرّر الرمز المحفوظ إلى OpenSSL:

openssl ts -reply -token_in -in timestamp-token.der -token_out -text

سطر Time stamp يُظهر الوقت المعتمد بتوقيت جرينتش، وسطر TSA يحدد الجهة التي أصدرته.

يقرأ هذا الفحص تنسيق حزمة DOCX. يخزن ملف DOC توقيعه في حاوية ثنائية، لذا لا ينطبق البرنامج النصي القائم على ZIP عليه.

استكشاف الأخطاء وإصلاحها لتوقيع الأخطاء والطوابع الزمنية

العَرَضالسبب المحتملما الذي يجب فعله
نجاح التوقيع، لكن لم يتم تضمين طابع زمنيتم تعيين أحدهما فقط xml_dsig_level = X_AD_ES_T أو timestamp_settingsقم بتعيين كليهما قبل استدعاء sign. مع XML_D_SIG أو X_AD_ES_EPES، يتم تجاهل إعدادات الطابع الزمني.
RuntimeError يذكر (401) Unauthorizedيتطلب خادم الطوابع الزمنية (TSA) بيانات اعتماد، أو أن بيانات الاعتماد غير صحيحةقم بتمرير اسم المستخدم وكلمة المرور الصادرة عن مزود TSA الخاص بك.
RuntimeError يذكر رفض الاتصال أو خطأ في الوكيلعنوان URL الخاص بـ TSA غير صحيح، أو جدار حماية أو وكيل يحظر الطلبتحقق من عنوان URL وتأكد من أن الجهاز الذي يشغل البرنامج النصي يمكنه الوصول إلى TSA.
RuntimeError يذكر The operation has timed outلم يرد TSA ضمن مهلة الانتظارأعد المحاولة، أو مرّر قيمة timeout أطول إلى DigitalSignatureTimestampSettings.
يبقى ملف إخراج فارغ بعد حدوث خطأsign ينشئ ملف الوجهة قبل فشل طلب TSAاحذف ملف الوجهة قبل إعادة المحاولة، أو اكتب إلى مسار مؤقت وأعد تسميته بعد استدعاء ناجح.
RuntimeError يقول إن الطوابع الزمنية غير مدعومة بهذا تنسيق الملفالملف المدخل هو ملف ODTقم بطبع الطابع الزمني لملفات DOCX أو DOC، أو حوّل إلى PDF واستخدم طريقة توقيع PDF الموضحة أدناه.
No usable version of libssl was found، أو تعطل بسبب حزمة ICU مفقودة، على Linuxيتطلب وقت تشغيل .NET المدمج في حزمة Python OpenSSL 1.1 وإصدار ICU مدعومقم بتثبيت OpenSSL 1.1، أو تثبيت ICU مدعوم. إذا لم يكن تطبيقك يحتاج إلى تنسيق خاص بالثقافة، اضبط DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 لتجاوز خطأ ICU.

بديل: إضافة طابع زمني لتوقيع في مخرجات PDF

إذا كان المستلمون يحتاجون إلى ملف PDF بدلاً من ملف Word موقع، فلا تحتاج إلى DigitalSignatureUtil. قم بتوقيع وتوقيت PDF أثناء حفظه عن طريق تعيين PdfSaveOptions.digital_signature_details.timestamp_settings إلى كائن PdfDigitalSignatureTimestampSettings. هذا المسار متاح منذ فترة أطول بكثير من 26.9. يحتوي مرجع PdfDigitalSignatureTimestampSettings على مثال كامل.

الخطوات التالية

لإضافة خطوط التوقيع، أو التوقيع باستخدام صورة خط التوقيع، أو إزالة التوقيعات الحالية، راجع العمل مع التوقيعات الرقمية في وثائق Aspose.Words for Python.

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

  1. ما الذي يضيفه الطابع الزمني الموثوق إلى التوقيع الرقمي؟
    تقوم سلطة الطابع الزمني (TSA) بتوثيق الوقت الذي تم فيه إنشاء التوقيع. يأتي هذا الوقت من طرف ثالث مستقل بدلاً من ساعة جهاز الكمبيوتر الخاص بالموقع، ويسمح للمُتحقق بإظهار أن التوقيع كان موجودًا قبل انتهاء صلاحية شهادة التوقيع أو إلغاؤها.
  2. أي إصدار من Aspose.Words يدعم إضافة الطابع الزمني في DigitalSignatureUtil؟
    أضاف الإصدار 26.9 من Aspose.Words for Python via .NET الخاصية SignOptions.timestamp_settings، والقيمة XmlDsigLevel.X_AD_ES_T، وفئة DigitalSignatureTimestampSettings. الإصدارات السابقة لا يمكنها إلا إضافة طابع زمني للتوقيعات في مخرجات PDF.
  3. هل يجب ضبط كل من xml_dsig_level و timestamp_settings؟
    نعم. إذا تم ضبط أحدهما فقط، لا يزال Aspose.Words يوقع المستند لكنه لا يطلب أو يضمّن طابعًا زمنيًا، ولا يُطلق خطأً.
  4. ما هي صيغ الملفات التي يمكن إضافة طابع زمني لها؟
    الملفات بصيغة DOCX و DOC الموقعة باستخدام X_AD_ES_T تتلقى طابعًا زمنيًا. محاولة توقيع ملف ODT بطابع زمني يؤدي إلى ظهور خطأ يُشير إلى أن الصيغة لا تدعم إضافة الطابع الزمني.
  5. هل يتحقق is_valid من صحة الطابع الزمني؟
    لا. يتحقق DigitalSignature.is_valid من صحة التوقيع نفسه فقط. لتأكيد صحة الطابع الزمني، تحقق من أن XML الخاص بالتوقيع يحتوي على رمز طابع زمني وافحص هذا الرمز باستخدام أداة مثل OpenSSL.
  6. ماذا يحدث إذا تعذر الوصول إلى TSA؟
    يرفع DigitalSignatureUtil.sign استثناء من نوع RuntimeError يصف مشكلة الشبكة أو المصادقة أو انتهاء المهلة. قد يبقى مسار الوجهة كملف فارغ، لذا احذفه قبل إعادة المحاولة.

الحصول على ترخيص مجاني ودعم