Una firma digitale registra chi ha firmato un documento. Un timestamp attendibile registra quando, e quel tempo proviene da un’autorità di timestamp indipendente (TSA) piuttosto che dall’orologio del computer del firmatario. Questo tutorial mostra come firmare un documento Word con una firma XAdES‑T con timestamp in Python, quindi confermare che il timestamp sia presente nel file.
Punti chiave
- Imposta entrambi
SignOptions.xml_dsig_level = XmlDsigLevel.X_AD_ES_TeSignOptions.timestamp_settings. Uno solo produce una firma senza timestamp e nessun errore lo segnala. - Aspose.Words richiede il timestamp durante
DigitalSignatureUtil.sign, quindi quella chiamata necessita di accesso di rete al TSA. - I file DOCX e DOC possono essere timbrati. I file ODT no.
DigitalSignature.is_validverifica la firma, non il timestamp. Verifica il timestamp separatamente.
Cosa aggiunge un timestamp attendibile a una firma
Ogni firma creata da Aspose.Words contiene un orario di firma, impostato da SignOptions.sign_time. Tale valore proviene dal computer del firmatario, quindi chiunque contesti il documento può contestare anche l’ora.
Una firma XAdES‑T aggiunge prove indipendenti. Dopo che il documento è stato firmato, Aspose.Words invia un hash del valore della firma a un TSA. Il TSA restituisce un token RFC 3161, firmato con il proprio certificato, che associa l’hash a un momento specifico. Quel token è memorizzato all’interno della firma. Un verificatore può quindi dimostrare che la firma esisteva in quel momento, il che è particolarmente importante quando il certificato di firma scade o viene revocato in seguito.
Prerequisiti
Prima di eseguire l’esempio, assicurati di avere:
- Aspose.Words for Python via .NET 26.9 o versioni successive. Installa o aggiorna da PyPI:
pip install --upgrade "aspose-words>=26.9"
- Un certificato di firma in formato PKCS#12 (
.pfxo.p12) e la sua password. - Un URL dell’autorità di timestamp. L’esempio utilizza FreeTSA (
https://freetsa.org/tsr), un TSA pubblico gratuito comodo per i test. Per i documenti di produzione, utilizzare il TSA raccomandato dalla tua organizzazione o dal fornitore del certificato, poiché le persone che verificano i tuoi documenti devono fidarsi del certificato di quel TSA. - Credenziali TSA, solo se il tuo TSA richiede l’autenticazione.
Senza una licenza, Aspose.Words funziona in modalità di valutazione con limitazioni. Una licenza temporanea le rimuove durante il test.
Firma un documento Word con un timestamp attendibile
Il seguente script firma un file DOCX con una firma XAdES‑T e incorpora un timestamp dal 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}")
Come funziona il codice
CertificateHolder.createlegge la chiave privata e la catena di certificati dal file.pfx. Una password errata fallisce qui, prima che inizi qualsiasi firma.XmlDsigLevel.X_AD_ES_Tindica ad Aspose.Words di creare una firma XAdES‑T, che è XAdES‑EPES più un timestamp della firma.DigitalSignatureTimestampSettingscontiene l’URL del TSA, un nome utente e password opzionali e un timeout opzionale. Stringhe vuote vanno bene per un TSA che accetta richieste anonime. Se il TSA risponde con una sfida di autenticazione HTTP, Aspose.Words invia le credenziali fornite.DigitalSignatureUtil.signscrive una copia firmata inOUTPUT_DOCe lascia invariato il file di input. Firma un documento non firmato: se l’input ha già una firma, l’output contiene sia la firma esistente sia quella nuova.
Verifica che il timestamp sia stato incorporato
Gli oggetti DigitalSignature restituiti da Aspose.Words non espongono il timestamp e is_valid non lo verifica. Durante i test, un documento il cui token di timestamp era stato deliberatamente corrotto segnalava comunque is_valid come True. Per confermare il timestamp, guarda all’interno del file XML della firma memorizzato nel pacchetto 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")
Per un DOCX firmato, dovresti vedere un output simile a questo:
Signer: CN=Your Name | valid: True
_xmlsignatures/sig1.xml: timestamp embedded (saved to timestamp-token.der)
Per leggere l’ora certificata dal TSA, passa il token salvato a OpenSSL:
openssl ts -reply -token_in -in timestamp-token.der -token_out -text
La riga Time stamp mostra l’ora certificata in GMT, e la riga TSA identifica l’autorità che l’ha emessa.
Questo controllo legge il formato del pacchetto DOCX. Un file DOC memorizza la sua firma in un contenitore binario, quindi lo script basato su ZIP non si applica.
Risoluzione dei problemi di firma e timestamp
| Sintomo | Causa probabile | Cosa fare |
|---|---|---|
| La firma ha successo, ma nessun timestamp è incorporato | È stata impostata solo una delle opzioni xml_dsig_level = X_AD_ES_T e timestamp_settings | Imposta entrambe prima di chiamare sign. Con XML_D_SIG o X_AD_ES_EPES, le impostazioni del timestamp vengono ignorate. |
RuntimeError che menziona (401) Unauthorized | Il TSA richiede credenziali, o le credenziali sono errate | Fornisci il nome utente e la password rilasciati dal tuo provider TSA. |
RuntimeError che menziona una connessione rifiutata o un errore di proxy | L’URL del TSA è errato, oppure un firewall o un proxy blocca la richiesta | Verifica l’URL e conferma che la macchina che esegue lo script possa raggiungere il TSA. |
RuntimeError che menziona The operation has timed out | Il TSA non ha risposto entro il timeout | Riprova, oppure passa un valore timeout più lungo a DigitalSignatureTimestampSettings. |
| Un file di output vuoto rimane dopo un errore | sign crea il file di destinazione prima che la richiesta al TSA fallisca | Elimina il file di destinazione prima di riprovare, oppure scrivi in un percorso temporaneo e rinominalo dopo una chiamata riuscita. |
RuntimeError che indica che il timestamp non è supportato da questo formato di file | L’input è un file ODT | Applica il timestamp a file DOCX o DOC, oppure converti in PDF e utilizza il percorso di firma PDF descritto di seguito. |
No usable version of libssl was found, o un crash relativo a un pacchetto ICU mancante, su Linux | Il runtime .NET incluso nel pacchetto Python richiede OpenSSL 1.1 e una versione ICU supportata | Installa OpenSSL 1.1, oppure installa una ICU supportata. Se la tua applicazione non necessita di formattazione specifica per la cultura, imposta DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 per l’errore ICU. |
Alternativa: Apporre un timestamp a una firma nell’output PDF
Se i tuoi destinatari hanno bisogno di un PDF anziché di un file Word firmato, non è necessario DigitalSignatureUtil. Firma e apponi un timestamp al PDF durante il salvataggio impostando PdfSaveOptions.digital_signature_details.timestamp_settings su un oggetto PdfDigitalSignatureTimestampSettings. Questa modalità è disponibile da molto più tempo rispetto alla 26.9. Il riferimento PdfDigitalSignatureTimestampSettings include un esempio completo.
Prossimi Passi
Per aggiungere linee di firma, firmare con un’immagine di linea di firma o rimuovere firme esistenti, vedere Lavorare con le firme digitali nella documentazione di Aspose.Words for Python.
FAQs
Cosa aggiunge un timestamp attendibile a una firma digitale?
Un’autorità di timestamp (TSA) certifica l’ora in cui è stata creata la firma. Tale ora proviene da una terza parte indipendente anziché dall’orologio del computer del firmatario, e consente a chi verifica di dimostrare che la firma esisteva prima che il certificato di firma scadesse o fosse revocato.Quale versione di Aspose.Words supporta il timestamping in DigitalSignatureUtil?
La versione 26.9 di Aspose.Words for Python via .NET ha aggiuntoSignOptions.timestamp_settings,XmlDsigLevel.X_AD_ES_Te la classeDigitalSignatureTimestampSettings. Le versioni precedenti possono aggiungere timestamp solo alle firme nell’output PDF.Devo impostare sia xml_dsig_level che timestamp_settings?
Sì. Se ne è impostato solo uno, Aspose.Words firma comunque il documento ma non richiede né incorpora un timestamp, e non genera un errore.Quali formati di file possono essere timestampati?
I file DOCX e DOC firmati conX_AD_ES_Tricevono un timestamp. Firmare un file ODT con un timestamp genera un errore che indica che il formato non supporta il timestamping.is_valid conferma che il timestamp è valido?
No.DigitalSignature.is_validverifica solo la firma stessa. Per confermare il timestamp, controlla che l’XML della firma contenga un token di timestamp e ispeziona il token con uno strumento come OpenSSL.Cosa succede se il TSA non è raggiungibile?
DigitalSignatureUtil.signgenera unRuntimeErrorche descrive il problema di rete, autenticazione o timeout. Il percorso di destinazione potrebbe rimanere come un file vuoto, quindi è consigliabile eliminarlo prima di riprovare.
