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_TiSignOptions.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_validsprawdza 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:
- Aspose.Words for Python via .NET 26.9 lub później. Zainstaluj lub zaktualizuj z PyPI:
pip install --upgrade "aspose-words>=26.9"
- Certyfikat podpisujący w formacie PKCS#12 (
.pfxlub.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.createodczytuje 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_Tinformuje Aspose.Words, aby utworzył podpis XAdES-T, który jest XAdES-EPES z dodatkowym znacznikiem czasu podpisu.DigitalSignatureTimestampSettingsprzechowuje 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.signzapisuje podpisaną kopię doOUTPUT_DOCi 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
| Objaw | Prawdopodobna przyczyna | Co zrobić |
|---|---|---|
| Podpisywanie zakończyło się sukcesem, ale znacznik czasu nie został osadzony | Ustawiono tylko jedną z opcji xml_dsig_level = X_AD_ES_T i timestamp_settings | Ustaw obie przed wywołaniem sign. Przy XML_D_SIG lub X_AD_ES_EPES ustawienia znacznika czasu są ignorowane. |
RuntimeError wspominający o (401) Unauthorized | TSA wymaga danych uwierzytelniających lub dane są nieprawidłowe | Przekaż nazwę użytkownika i hasło wydane przez dostawcę TSA. |
RuntimeError wspominający o odrzuconym połączeniu lub błędzie proxy | Adres URL TSA jest nieprawidłowy lub zapora sieciowa/proxy blokuje żądanie | Sprawdź adres URL i potwierdź, że maszyna uruchamiająca skrypt może dotrzeć do TSA. |
RuntimeError wspominający o The operation has timed out | TSA nie odpowiedziało w określonym czasie | Spróbuj ponownie lub przekaż dłuższy timeout do DigitalSignatureTimestampSettings. |
| Po błędzie pozostaje pusty plik wyjściowy | sign tworzy plik docelowy przed niepowodzeniem żądania do TSA | Usuń 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 pliku | Wejściowy plik jest w formacie ODT | Dodaj 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 Linux | Zestaw .NET dołączony do pakietu Pythona wymaga OpenSSL 1.1 oraz obsługiwanej wersji ICU | Zainstaluj 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
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.Która wersja Aspose.Words obsługuje znacznik czasu w DigitalSignatureUtil?
Wersja 26.9 Aspose.Words for Python via .NET dodałaSignOptions.timestamp_settings,XmlDsigLevel.X_AD_ES_Toraz klasęDigitalSignatureTimestampSettings. Wcześniejsze wersje mogą jedynie znacznikować podpisy w wyjściu PDF.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.Jakie formaty plików mogą być znacznikowane?
Pliki DOCX i DOC podpisane przy użyciuX_AD_ES_Totrzymują znacznik czasu. Próba znacznikowania pliku ODT skutkuje błędem informującym, że format nie obsługuje znaczników czasu.Czy is_valid potwierdza, że znacznik czasu jest ważny?
Nie.DigitalSignature.is_validsprawdza 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.Co się stanie, jeśli nie można połączyć się z TSA?
DigitalSignatureUtil.signzgłaszaRuntimeErroropisują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ą.
