Цифровий підпис фіксує, хто підписав документ. Довірчий мітка часу фіксує коли, і цей час надходить від незалежного органу часових міток (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 показує сертифікований час у GMT, а рядок TSA вказує на орган, який його видав.

Ця перевірка читає формат пакету DOCX. Файл DOC зберігає свій підпис у бінарному контейнері, тому скрипт, заснований на ZIP, не застосовується до нього.

Усунення проблем підпису та помилок міток часу

СимптомЙмовірна причинаЩо робити
Підпис успішний, але мітка часу не вбудованаБуло встановлено лише одне з xml_dsig_level = X_AD_ES_T та timestamp_settingsВстановіть обидва перед викликом sign. При XML_D_SIG або X_AD_ES_EPES параметри мітки часу ігноруються.
RuntimeError, що містить (401) UnauthorizedTSA вимагає облікові дані, або дані неправильніПередайте ім’я користувача та пароль, видані вашим постачальником TSA.
RuntimeError, що містить відмову з’єднання або помилку проксіURL TSA неправильний, або брандмауер чи проксі блокує запитПеревірте URL і переконайтеся, що машина, на якій виконується скрипт, може досягти TSA.
RuntimeError, що містить The operation has timed outTSA не відповіла протягом встановленого часуПовторіть спробу або передайте довший timeout у DigitalSignatureTimestampSettings.
Після помилки залишається порожній вихідний файлsign створює файл призначення до того, як запит до TSA зазнає збоюВидаліть файл призначення перед повторною спробою або запишіть у тимчасовий шлях і перейменуйте його після успішного виклику.
RuntimeError, який повідомляє, що мітка часу не підтримується цим форматом файлуВхідний файл у форматі ODTДодавайте мітку часу до файлів DOCX або DOC, або конвертуйте у PDF і використайте шлях підпису PDF, описаний нижче.
No usable version of libssl was found, або збій через відсутній пакет ICU, у LinuxВбудований у Python пакет .NET runtime потребує 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, який описує проблему мережі, автентифікації або тайм‑ауту. Шлях призначення може залишитися порожнім файлом, тому його слід видалити перед повторною спробою.

Отримайте безкоштовну ліцензію та підтримку