En digital signatur registrerar vem som har signerat ett dokument. En betrodd tidsstämpel registrerar när, och den tiden kommer från en oberoende tidsstämpelmyndighet (TSA) snarare än klockan på signerarens dator. Denna handledning visar hur du signerar ett Word‑dokument med en tidsstämplad XAdES‑T‑signatur i Python och sedan bekräftar att tidsstämpeln finns i filen.

Viktiga slutsatser

  • Ställ in båda SignOptions.xml_dsig_level = XmlDsigLevel.X_AD_ES_T och SignOptions.timestamp_settings. Endast en av dem ger en signatur utan tidsstämpel, och inget felmeddelande informerar dig om det.
  • Aspose.Words begär tidsstämpeln under DigitalSignatureUtil.sign, så det anropet kräver nätverksåtkomst till TSA.
  • DOCX och DOC filer kan tidsstämplas. ODT-filer kan inte.
  • DigitalSignature.is_valid kontrollerar signaturen, inte tidsstämpeln. Bekräfta tidsstämpeln separat.

Vad ett betrott tidsstämpel lägger till en signatur

Varje signatur som Aspose.Words skapar innehåller en signeringstid, som sätts av SignOptions.sign_time. Det värdet kommer från undertecknarens maskin, så vem som helst som bestrider dokumentet kan också bestrida tiden.

En XAdES‑T‑signatur lägger till oberoende bevis. Efter att dokumentet har signerats skickar Aspose.Words en hash av signaturvärdet till en TSA. TSA:n returnerar en RFC 3161‑token, signerad med sitt eget certifikat, som binder hashen till en specifik tid. Den token lagras i signaturen. En verifierare kan sedan visa att signaturen existerade vid den tidpunkten, vilket är särskilt viktigt när signaturcertifikatet senare löper ut eller återkallas.

Förutsättningar

Innan du kör exemplet, se till att du har:

pip install --upgrade "aspose-words>=26.9"
  • Ett signeringscertifikat i PKCS#12-format (.pfx eller .p12) och dess lösenord.
  • En tidsstämpelauktoritets-URL. Exemplet använder FreeTSA (https://freetsa.org/tsr), en gratis offentlig TSA som är praktisk för testning. För produktionsdokument, använd den TSA som din organisation eller certifikatleverantör rekommenderar, eftersom de som granskar dina dokument måste lita på den TSA:s certifikat.
  • TSA-referenser, endast om din TSA kräver autentisering.

Utan en licens kör Aspose.Words i evalueringsläge med begränsningar. En tillfällig licens tar bort dem medan du testar.

Signera ett Word‑dokument med en betrodd tidsstämpel

Följande skript signerar en DOCX‑fil med en XAdES‑T‑signatur och bäddar in en tidsstämpel från 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}")

Så fungerar koden

  • CertificateHolder.create läser den privata nyckeln och certifikatkedjan från .pfx-filen. Ett felaktigt lösenord misslyckas här, innan någon signering påbörjas.
  • XmlDsigLevel.X_AD_ES_T instruerar Aspose.Words att bygga en XAdES‑T‑signatur, vilket är XAdES‑EPES plus en signatur‑tidsstämpel.
  • DigitalSignatureTimestampSettings innehåller TSA‑URL:en, ett valfritt användarnamn och lösenord samt en valfri timeout. Tomma strängar är okej för en TSA som accepterar anonyma förfrågningar. Om TSA svarar med en HTTP‑autentiseringsutmaning skickar Aspose.Words de referenser du angav.
  • DigitalSignatureUtil.sign skriver en signerad kopia till OUTPUT_DOC och lämnar indatafilen oförändrad. Signera ett osignerat dokument: om indata redan har en signatur innehåller utdata både den befintliga signaturen och den nya.

Kontrollera att tidsstämpeln har bäddats in

DigitalSignature‑objekten som Aspose.Words returnerar visar inte tidsstämpeln, och is_valid kontrollerar den inte. Vid testning rapporterade ett dokument vars tidsstämpel‑token hade avsiktligt korruptats fortfarande is_valid som True. För att bekräfta tidsstämpeln, titta i signatur‑XML‑filen som lagras i DOCX‑paketet:

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 ett signerat DOCX bör du se en liknande utskrift:

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

För att läsa tiden som TSA certifierade, skicka den sparade token till OpenSSL:

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

Raden Time stamp visar den certifierade tiden i GMT, och raden TSA identifierar den myndighet som utfärdade den.

Denna kontroll läser DOCX‑paketformatet. En DOC‑fil lagrar sin signatur i en binär behållare, så det ZIP‑baserade skriptet gäller inte för den.

Felsökning av signering och tidsstämpelfel

SymptomTrolig orsakVad du ska göra
Signeringen lyckas, men ingen tidsstämpel har lagts tillEndast en av xml_dsig_level = X_AD_ES_T och timestamp_settings var inställdStäll in båda innan du anropar sign. Med XML_D_SIG eller X_AD_ES_EPES ignoreras tidsstämpelinställningarna.
RuntimeError som nämner (401) UnauthorizedTSA:n kräver autentiseringsuppgifter, eller så är uppgifterna felaktigaSkicka med användarnamn och lösenord som utfärdats av din TSA-leverantör.
RuntimeError som nämner en nekad anslutning eller ett proxyfelTSA‑URL:en är felaktig, eller en brandvägg eller proxy blockerar begäranKontrollera URL:en och bekräfta att maskinen som kör ditt skript kan nå TSA:n.
RuntimeError som nämner The operation has timed outTSA:n svarade inte inom tidsgränsenFörsök igen, eller skicka med en längre timeout till DigitalSignatureTimestampSettings.
En tom utdatafil återstår efter ett felsign skapar destinationsfilen innan TSA‑begäran misslyckasTa bort destinationsfilen innan du försöker igen, eller skriv till en temporär sökväg och byt namn på den efter ett lyckat anrop.
RuntimeError som säger att tidsstämpling inte stöds av detta filformatInmatningen är en ODT‑filTidsstämpla DOCX‑ eller DOC‑filer, eller konvertera till PDF och använd PDF‑signeringsvägen som beskrivs nedan.
No usable version of libssl was found, eller en krasch på grund av ett saknat ICU‑paket, på LinuxPython‑paketets medföljande .NET‑runtime kräver OpenSSL 1.1 och en stödjande ICU‑versionInstallera OpenSSL 1.1, eller installera en stödjande ICU. Om din applikation inte behöver kultur‑specifik formatering, sätt DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 för ICU‑felet.

Alternativ: Tidsstämpel för en signatur i PDF‑utdata

Om dina mottagare behöver en PDF snarare än en signerad Word‑fil, behöver du inte DigitalSignatureUtil. Signera och tidsstämpla PDF‑filen vid sparande genom att sätta PdfSaveOptions.digital_signature_details.timestamp_settings till ett PdfDigitalSignatureTimestampSettings‑objekt. Denna metod har funnits tillgänglig mycket längre än 26.9. PdfDigitalSignatureTimestampSettings‑referensen innehåller ett komplett exempel.

Nästa steg

För att lägga till signaturlinjer, signera med en signaturlinje‑bild eller ta bort befintliga signaturer, se Work with Digital Signatures i Aspose.Words for Python-dokumentationen.

Vanliga frågor

  1. Vad tillför en betrodd tidsstämpel till en digital signatur?
    En tidsstämpelmyndighet (TSA) intygar den tid då signaturen skapades. Den tiden kommer från en oberoende tredje part snarare än undertecknarens datorklocka, och den låter en verifierare visa att signaturen fanns innan signeringscertifikatet gick ut eller revokerades.

  2. Vilken version av Aspose.Words stödjer tidsstämpling i DigitalSignatureUtil?
    Version 26.9 av Aspose.Words for Python via .NET lade till SignOptions.timestamp_settings, XmlDsigLevel.X_AD_ES_T och klassen DigitalSignatureTimestampSettings. Tidigare versioner kan endast tidsstämpla signaturer i PDF-utdata.

  3. Behöver jag ange både xml_dsig_level och timestamp_settings?
    Ja. Om endast en av dem är angiven, signerar Aspose.Words fortfarande dokumentet men begär eller bäddar inte in en tidsstämpel, och det kastar inget fel.

  4. Vilka filformat kan tidsstämplas?
    DOCX- och DOC-filer som signeras med X_AD_ES_T får en tidsstämpel. Att signera en ODT-fil med en tidsstämpel ger ett fel som säger att formatet inte stödjer tidsstämpling.

  5. Bekräftar is_valid att tidsstämpeln är giltig?
    Nej. DigitalSignature.is_valid kontrollerar själva signaturen. För att bekräfta tidsstämpeln, kontrollera att signaturens XML innehåller en tidsstämpel‑token och inspektera token med ett verktyg som OpenSSL.

  6. Vad händer om TSA inte kan nås?
    DigitalSignatureUtil.sign kastar ett RuntimeError som beskriver nätverks-, autentiserings- eller tidsgräns‑problemet. Destinationssökvägen kan bli en tom fil, så ta bort den innan du försöker igen.

Skaffa en gratis licens och support