Eine digitale Signatur zeichnet auf, wer ein Dokument unterschrieben hat. Ein vertrauenswürdiger Zeitstempel zeichnet wann auf, und dieser Zeitpunkt stammt von einer unabhängigen Zeitstempelbehörde (TSA) und nicht von der Uhr des Rechners des Unterzeichners. Dieses Tutorial zeigt, wie man ein Word‑Dokument mit einer zeitgestempelten XAdES‑T‑Signatur in Python signiert und anschließend bestätigt, dass der Zeitstempel in der Datei enthalten ist.
Wichtige Erkenntnisse
- Setzen Sie beide
SignOptions.xml_dsig_level = XmlDsigLevel.X_AD_ES_TundSignOptions.timestamp_settings. Jede einzelne erzeugt eine Signatur ohne Zeitstempel, und es gibt keinen Fehler, der Sie darauf hinweist. - Aspose.Words fordert den Zeitstempel während
DigitalSignatureUtil.signan, sodass dieser Aufruf Netzwerkzugriff auf den TSA benötigt. - DOCX und DOC Dateien können mit einem Zeitstempel versehen werden. ODT-Dateien nicht.
DigitalSignature.is_validprüft die Signatur, nicht den Zeitstempel. Bestätigen Sie den Zeitstempel separat.
Was ein vertrauenswürdiger Zeitstempel zu einer Signatur hinzufügt
Jede von Aspose.Words erstellte Signatur enthält eine Signaturzeit, die durch SignOptions.sign_time festgelegt wird. Dieser Wert stammt vom Rechner des Unterzeichners, sodass jeder, der das Dokument anzweifelt, auch die Zeit anzweifeln kann.
Eine XAdES‑T‑Signatur fügt unabhängige Beweise hinzu. Nachdem das Dokument signiert wurde, sendet Aspose.Words einen Hash des Signaturwerts an einen TSA. Der TSA gibt ein RFC‑3161‑Token zurück, das mit seinem eigenen Zertifikat signiert ist und den Hash an einen bestimmten Zeitpunkt bindet. Dieses Token wird innerhalb der Signatur gespeichert. Ein Prüfer kann dann nachweisen, dass die Signatur zu diesem Zeitpunkt existierte, was besonders wichtig ist, wenn das Signaturzertifikat später abläuft oder widerrufen wird.
Voraussetzungen
Bevor Sie das Beispiel ausführen, stellen Sie sicher, dass Sie Folgendes haben:
- Aspose.Words for Python via .NET 26.9 oder neuer. Installieren oder aktualisieren Sie von PyPI:
pip install --upgrade "aspose-words>=26.9"
- Ein Signaturzertifikat im PKCS#12-Format (
.pfxoder.p12) und dessen Passwort. - Eine Zeitstempel-Authority-URL. Das Beispiel verwendet FreeTSA (
https://freetsa.org/tsr), einen kostenlosen öffentlichen TSA, der für Tests praktisch ist. Für Produktionsdokumente verwenden Sie den TSA, den Ihre Organisation oder Ihr Zertifikatanbieter empfiehlt, da die Personen, die Ihre Dokumente prüfen, dem Zertifikat dieses TSA vertrauen müssen. - TSA-Anmeldeinformationen, nur wenn Ihr TSA eine Authentifizierung erfordert.
Ohne eine Lizenz läuft Aspose.Words im Evaluierungsmodus mit Einschränkungen. Eine temporäre Lizenz entfernt diese, während Sie testen.
Ein Word-Dokument mit einem vertrauenswürdigen Zeitstempel signieren
Das folgende Skript signiert eine DOCX-Datei mit einer XAdES‑T-Signatur und bettet einen Zeitstempel vom TSA ein.
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}")
Wie der Code funktioniert
CertificateHolder.createliest den privaten Schlüssel und die Zertifikatskette aus der.pfx‑Datei. Ein falsches Passwort schlägt hier fehl, bevor irgendeine Signatur beginnt.XmlDsigLevel.X_AD_ES_Tweist Aspose.Words an, eine XAdES‑T‑Signatur zu erstellen, die XAdES‑EPES plus einen Signaturzeitstempel ist.DigitalSignatureTimestampSettingsenthält die TSA‑URL, einen optionalen Benutzernamen und ein Passwort sowie ein optionales Timeout. Leere Zeichenketten sind in Ordnung für eine TSA, die anonyme Anfragen akzeptiert. Wenn die TSA mit einer HTTP‑Authentifizierungsaufforderung antwortet, sendet Aspose.Words die von Ihnen bereitgestellten Anmeldeinformationen.DigitalSignatureUtil.signschreibt eine signierte Kopie nachOUTPUT_DOCund lässt die Eingabedatei unverändert. Signieren Sie ein unsigniertes Dokument: Wenn die Eingabe bereits eine Signatur enthält, enthält die Ausgabe sowohl die vorhandene Signatur als auch die neue.
Überprüfen Sie, dass der Zeitstempel eingebettet wurde
Die DigitalSignature-Objekte, die Aspose.Words zurückgibt, stellen den Zeitstempel nicht bereit, und is_valid prüft ihn nicht. Bei Tests meldete ein Dokument, dessen Zeitstempel‑Token absichtlich beschädigt wurde, immer noch is_valid als True. Um den Zeitstempel zu bestätigen, schauen Sie in das Signatur‑XML, das im DOCX‑Paket gespeichert ist:
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")
Für ein signiertes DOCX sollten Sie eine ähnliche Ausgabe sehen:
Signer: CN=Your Name | valid: True
_xmlsignatures/sig1.xml: timestamp embedded (saved to timestamp-token.der)
Um die vom TSA zertifizierte Zeit auszulesen, übergeben Sie das gespeicherte Token an OpenSSL:
openssl ts -reply -token_in -in timestamp-token.der -token_out -text
Die Zeile Time stamp zeigt die zertifizierte Zeit in GMT an, und die Zeile TSA gibt die Behörde an, die sie ausgestellt hat.
Dieser Check liest das DOCX‑Paketformat. Eine DOC‑Datei speichert ihre Signatur in einem Binärcontainer, sodass das ZIP‑basierte Skript nicht darauf anwendbar ist.
Fehlerbehebung bei Signatur- und Zeitstempel-Fehlern
| Symptom | Wahrscheinliche Ursache | Was zu tun ist |
|---|---|---|
| Signatur ist erfolgreich, aber kein Zeitstempel ist eingebettet | Nur einer von xml_dsig_level = X_AD_ES_T und timestamp_settings war gesetzt | Setzen Sie beide, bevor Sie sign aufrufen. Bei XML_D_SIG oder X_AD_ES_EPES werden die Zeitstempel‑Einstellungen ignoriert. |
RuntimeError mit Hinweis auf (401) Unauthorized | Der TSA erfordert Anmeldeinformationen, oder die Anmeldeinformationen sind falsch | Geben Sie den Benutzernamen und das Passwort an, die Ihr TSA‑Anbieter bereitgestellt hat. |
RuntimeError mit Hinweis auf eine verweigerte Verbindung oder einen Proxy‑Fehler | Die TSA‑URL ist falsch, oder eine Firewall bzw. ein Proxy blockiert die Anfrage | Überprüfen Sie die URL und stellen Sie sicher, dass die Maschine, auf der Ihr Skript läuft, den TSA erreichen kann. |
RuntimeError mit Hinweis auf The operation has timed out | Der TSA hat nicht innerhalb des Zeitlimits geantwortet | Versuchen Sie es erneut oder übergeben Sie ein längeres timeout an DigitalSignatureTimestampSettings. |
| Nach einem Fehler bleibt eine leere Ausgabedatei zurück | sign erstellt die Zieldatei, bevor die TSA‑Anfrage fehlschlägt | Löschen Sie die Zieldatei vor einem erneuten Versuch, oder schreiben Sie in einen temporären Pfad und benennen Sie ihn nach einem erfolgreichen Aufruf um. |
RuntimeError mit Hinweis, dass Zeitstempel für dieses Dateiformat nicht unterstützt werden | Die Eingabedatei ist eine ODT-Datei | Zeitstempeln Sie DOCX- oder DOC-Dateien, oder konvertieren Sie in PDF und verwenden Sie den unten beschriebenen PDF‑Signatur‑Weg. |
No usable version of libssl was found oder ein Absturz wegen eines fehlenden ICU‑Pakets unter Linux | Die im Python‑Paket enthaltene .NET‑Runtime benötigt OpenSSL 1.1 und eine unterstützte ICU‑Version | Installieren Sie OpenSSL 1.1 oder eine unterstützte ICU. Wenn Ihre Anwendung keine kulturspezifische Formatierung benötigt, setzen Sie DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 für den ICU‑Fehler. |
Alternative: Zeitstempel einer Signatur im PDF-Ausgabe
Wenn Ihre Empfänger ein PDF statt einer signierten Word-Datei benötigen, benötigen Sie nicht DigitalSignatureUtil. Signieren und versehen Sie das PDF beim Speichern mit einem Zeitstempel, indem Sie PdfSaveOptions.digital_signature_details.timestamp_settings auf ein PdfDigitalSignatureTimestampSettings‑Objekt setzen. Dieser Weg ist bereits seit viel länger als 26.9 verfügbar. Die PdfDigitalSignatureTimestampSettings reference enthält ein vollständiges Beispiel.
Nächste Schritte
Um Signaturzeilen hinzuzufügen, mit einem Signaturzeilen‑Bild zu signieren oder vorhandene Signaturen zu entfernen, siehe Arbeiten mit digitalen Signaturen in der Aspose.Words for Python Dokumentation.
FAQs
Was fügt ein vertrauenswürdiger Zeitstempel einer digitalen Signatur hinzu?
Eine Zeitstempelbehörde (TSA) bescheinigt den Zeitpunkt, zu dem die Signatur erstellt wurde. Dieser Zeitpunkt stammt von einer unabhängigen Drittpartei und nicht von der Computeruhr des Unterzeichners, und er ermöglicht es einem Prüfer nachzuweisen, dass die Signatur existierte, bevor das Signaturzertifikat abgelaufen oder widerrufen wurde.Welche Aspose.Words-Version unterstützt das Zeitstempeln in DigitalSignatureUtil?
Version 26.9 von Aspose.Words for Python via .NET fügteSignOptions.timestamp_settings,XmlDsigLevel.X_AD_ES_Tund die KlasseDigitalSignatureTimestampSettingshinzu. Frühere Versionen können Signaturen nur im PDF‑Ausgabeformat mit einem Zeitstempel versehen.Muss ich sowohl xml_dsig_level als auch timestamp_settings setzen?
Ja. Wenn nur einer von beiden gesetzt ist, signiert Aspose.Words das Dokument weiterhin, fordert jedoch keinen Zeitstempel an und bettet keinen ein, und es wird kein Fehler ausgelöst.Welche Dateiformate können mit einem Zeitstempel versehen werden?
DOCX‑ und DOC‑Dateien, die mitX_AD_ES_Tsigniert werden, erhalten einen Zeitstempel. Das Signieren einer ODT‑Datei mit einem Zeitstempel führt zu einem Fehler, der besagt, dass das Format kein Zeitstempeln unterstützt.Bestätigt is_valid, dass der Zeitstempel gültig ist?
Nein.DigitalSignature.is_validprüft nur die Signatur selbst. Um den Zeitstempel zu bestätigen, muss geprüft werden, ob das Signatur‑XML ein Zeitstempel‑Token enthält, und das Token mit einem Werkzeug wie OpenSSL inspiziert werden.Was passiert, wenn die TSA nicht erreicht werden kann?
DigitalSignatureUtil.signwirft einenRuntimeError, der das Netzwerk‑, Authentifizierungs‑ oder Zeitüberschreitungsproblem beschreibt. Der Zielpfad kann als leere Datei zurückbleiben, daher sollte sie vor einem erneuten Versuch gelöscht werden.
