חתימה דיגיטלית מתעדת מי חתם על המסמך. חותמת זמן מהימנה מתעדת מתי, והזמן הזה מגיע מרשות חותמות זמן עצמאית (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 מחזיק את כתובת ה‑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 מציגה את הזמן המאושר ב‑GMT, והקו 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 שמזכיר חיבור שנדחה או שגיאת פרוקסיכתובת ה‑TSA שגויה, או חומת אש או פרוקסי חוסמים את הבקשהבדוק את הכתובת ואשר שהמחשב שמריץ את הסקריפט שלך יכול להגיע ל‑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, בלינוקסה‑runtime של .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 reference כולל דוגמה מלאה.

הצעדים הבאים

כדי להוסיף קווי חתימה, לחתום עם תמונת קו חתימה, או להסיר חתימות קיימות, ראה עבודה עם חתימות דיגיטליות בתיעוד של 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 המתאר בעיית רשת, אימות או פקיעת זמן. נתיב היעד עשוי להישאר כקובץ ריק, ולכן יש למחוק אותו לפני ניסיון חוזר.

קבל רישיון חינמי ותמיכה