Podpis cyfrowy rejestruje, kto podpisał dokument. Zaufany znacznik czasu rejestruje kiedy, a czas ten pochodzi od niezależnego urzędu znaczników czasu (TSA), a nie od zegara na komputerze podpisującego. Ten samouczek pokazuje, jak podpisać dokument Word podpisem XAdES‑T w języku Python, a następnie potwierdzić, że znacznik czasu znajduje się w pliku.

Kluczowe wnioski

  • Ustaw obie SignOptions.xml_dsig_level = XmlDsigLevel.X_AD_ES_T i SignOptions.timestamp_settings. Każde z nich osobno generuje podpis bez znacznika czasu, a żaden błąd cię o tym nie informuje.
  • Aspose.Words żąda znacznika czasu podczas DigitalSignatureUtil.sign, więc to wywołanie wymaga dostępu sieciowego do TSA.
  • DOCX i DOC można opatrzyć znacznikiem czasu. Pliki ODT nie mogą.
  • DigitalSignature.is_valid sprawdza podpis, a nie znacznik czasu. Potwierdź znacznik czasu osobno.

Co zaufany znacznik czasu dodaje do podpisu

Każdy podpis tworzony przez Aspose.Words zawiera czas podpisu, ustawiany przez SignOptions.sign_time. Wartość ta pochodzi z maszyny podpisującego, więc każdy kwestionujący dokument może również kwestionować czas.

Podpis XAdES‑T dodaje niezależny dowód. Po podpisaniu dokumentu, Aspose.Words wysyła skrót wartości podpisu do TSA. TSA zwraca token RFC 3161, podpisany własnym certyfikatem, który wiąże skrót z określonym czasem. Ten token jest przechowywany wewnątrz podpisu. Weryfikator może wtedy wykazać, że podpis istniał w tym momencie, co ma największe znaczenie, gdy certyfikat podpisującego później wygaśnie lub zostanie odwołany.

Wymagania wstępne

Zanim uruchomisz przykład, upewnij się, że masz:

pip install --upgrade "aspose-words>=26.9"
  • Certyfikat podpisujący w formacie PKCS#12 (.pfx lub .p12) oraz jego hasło.
  • Adres URL urzędu czasu. Przykład używa FreeTSA (https://freetsa.org/tsr), darmowego publicznego TSA, które jest wygodne do testów. Dla dokumentów produkcyjnych użyj TSA zalecanego przez Twoją organizację lub dostawcę certyfikatu, ponieważ osoby weryfikujące Twoje dokumenty muszą ufać certyfikatowi tego TSA.
  • Poświadczenia TSA, tylko jeśli Twój TSA wymaga uwierzytelnienia.

Bez licencji Aspose.Words działa w trybie ewaluacyjnym z ograniczeniami. Tymczasowa licencja usuwa je podczas testowania.

Podpisz dokument Word przy użyciu zaufanego znacznika czasu

Poniższy skrypt podpisuje plik DOCX podpisem XAdES‑T i osadza znacznik czasu z 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}")

How the Code Works

  • CertificateHolder.create odczytuje klucz prywatny i łańcuch certyfikatów z pliku .pfx. Nieprawidłowe hasło powoduje błąd w tym miejscu, zanim rozpocznie się jakiekolwiek podpisywanie.
  • XmlDsigLevel.X_AD_ES_T informuje Aspose.Words, aby utworzył podpis XAdES-T, który jest XAdES-EPES z dodatkowym znacznikiem czasu podpisu.
  • DigitalSignatureTimestampSettings przechowuje adres URL TSA, opcjonalną nazwę użytkownika i hasło oraz opcjonalny limit czasu. Puste ciągi znaków są w porządku dla TSA, które akceptuje anonimowe żądania. Jeśli TSA odpowie wyzwaniem uwierzytelnienia HTTP, Aspose.Words wyśle podane przez Ciebie poświadczenia.
  • DigitalSignatureUtil.sign zapisuje podpisaną kopię do OUTPUT_DOC i pozostawia plik wejściowy niezmieniony. Podpisz dokument niepodpisany: jeśli wejście już posiada podpis, wyjście zawiera zarówno istniejący podpis, jak i nowy.

Sprawdź, czy znacznik czasu został osadzony

Obiekty DigitalSignature zwracane przez Aspose.Words nie udostępniają znacznika czasu, a is_valid go nie sprawdza. W testach dokument, którego token znacznika czasu został celowo uszkodzony, nadal zgłaszał is_valid jako True. Aby potwierdzić znacznik czasu, spójrz na XML podpisu przechowywany w pakiecie 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")

W przypadku podpisanego DOCX powinieneś zobaczyć podobny wynik:

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

Aby odczytać czas certyfikowany przez TSA, przekaż zapisany token do OpenSSL:

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

Linia Time stamp pokazuje certyfikowany czas w GMT, a linia TSA identyfikuje organ, który go wydał.

To sprawdzenie odczytuje format pakietu DOCX. Plik DOC przechowuje swój podpis w kontenerze binarnym, więc skrypt oparty na ZIP nie ma zastosowania.

Rozwiązywanie problemów z podpisywaniem i błędami znaczników czasu

ObjawPrawdopodobna przyczynaCo zrobić
Podpisywanie zakończyło się sukcesem, ale znacznik czasu nie został osadzonyUstawiono tylko jedną z opcji xml_dsig_level = X_AD_ES_T i timestamp_settingsUstaw obie przed wywołaniem sign. Przy XML_D_SIG lub X_AD_ES_EPES ustawienia znacznika czasu są ignorowane.
RuntimeError wspominający o (401) UnauthorizedTSA wymaga danych uwierzytelniających lub dane są nieprawidłowePrzekaż nazwę użytkownika i hasło wydane przez dostawcę TSA.
RuntimeError wspominający o odrzuconym połączeniu lub błędzie proxyAdres URL TSA jest nieprawidłowy lub zapora sieciowa/proxy blokuje żądanieSprawdź adres URL i potwierdź, że maszyna uruchamiająca skrypt może dotrzeć do TSA.
RuntimeError wspominający o The operation has timed outTSA nie odpowiedziało w określonym czasieSpróbuj ponownie lub przekaż dłuższy timeout do DigitalSignatureTimestampSettings.
Po błędzie pozostaje pusty plik wyjściowysign tworzy plik docelowy przed niepowodzeniem żądania do TSAUsuń plik docelowy przed ponowną próbą lub zapisz do tymczasowej ścieżki i zmień nazwę po pomyślnym wywołaniu.
RuntimeError informujący, że znacznik czasu nie jest obsługiwany przez ten format plikuWejściowy plik jest w formacie ODTDodaj znacznik czasu do plików DOCX lub DOC, lub skonwertuj do PDF i użyj opisanej poniżej ścieżki podpisywania PDF.
No usable version of libssl was found, lub awaria związana z brakującym pakietem ICU, w systemie LinuxZestaw .NET dołączony do pakietu Pythona wymaga OpenSSL 1.1 oraz obsługiwanej wersji ICUZainstaluj OpenSSL 1.1 lub zainstaluj obsługiwaną wersję ICU. Jeśli aplikacja nie wymaga formatowania specyficznego dla kultury, ustaw DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 w celu rozwiązania błędu ICU.

Alternatywa: Znaczenie czasowe podpisu w wyjściu PDF

Jeśli odbiorcy potrzebują pliku PDF zamiast podpisanego pliku Word, nie potrzebujesz DigitalSignatureUtil. Podpisz i oznacz znaczkiem czasu plik PDF podczas zapisywania, ustawiając PdfSaveOptions.digital_signature_details.timestamp_settings na obiekt PdfDigitalSignatureTimestampSettings. Ta metoda jest dostępna od znacznie dłuższego czasu niż 26.9. Odnośnik PdfDigitalSignatureTimestampSettings reference zawiera kompletny przykład.

Kolejne kroki

Aby dodać linie podpisu, podpisać się przy użyciu obrazu linii podpisu lub usunąć istniejące podpisy, zobacz Work with Digital Signatures w dokumentacji Aspose.Words for Python.

Najczęściej zadawane pytania

  1. Co dodaje zaufany znacznik czasu do podpisu cyfrowego?
    Urząd certyfikujący znacznik czasu (TSA) potwierdza moment, w którym podpis został złożony. Ten czas pochodzi od niezależnej strony trzeciej, a nie od zegara komputera podpisującego, i pozwala weryfikatorowi wykazać, że podpis istniał przed wygaśnięciem lub odwołaniem certyfikatu podpisującego.

  2. Która wersja Aspose.Words obsługuje znacznik czasu w DigitalSignatureUtil?
    Wersja 26.9 Aspose.Words for Python via .NET dodała SignOptions.timestamp_settings, XmlDsigLevel.X_AD_ES_T oraz klasę DigitalSignatureTimestampSettings. Wcześniejsze wersje mogą jedynie znacznikować podpisy w wyjściu PDF.

  3. Czy muszę ustawić zarówno xml_dsig_level, jak i timestamp_settings?
    Tak. Jeśli ustawiony jest tylko jeden z tych parametrów, Aspose.Words nadal podpisuje dokument, ale nie żąda ani nie osadza znacznika czasu i nie generuje błędu.

  4. Jakie formaty plików mogą być znacznikowane?
    Pliki DOCX i DOC podpisane przy użyciu X_AD_ES_T otrzymują znacznik czasu. Próba znacznikowania pliku ODT skutkuje błędem informującym, że format nie obsługuje znaczników czasu.

  5. Czy is_valid potwierdza, że znacznik czasu jest ważny?
    Nie. DigitalSignature.is_valid sprawdza sam podpis. Aby potwierdzić znacznik czasu, należy zweryfikować, czy XML podpisu zawiera token znacznika czasu i zbadać ten token przy pomocy narzędzia takiego jak OpenSSL.

  6. Co się stanie, jeśli nie można połączyć się z TSA?
    DigitalSignatureUtil.sign zgłasza RuntimeError opisujący problem sieciowy, uwierzytelniania lub przekroczenia limitu czasu. Ścieżka docelowa może pozostać jako pusty plik, dlatego należy go usunąć przed ponowną próbą.

Uzyskaj darmową licencję i wsparcie