Une signature numérique indique qui a signé un document. Un horodatage de confiance indique quand, et ce moment provient d’une autorité d’horodatage indépendante (TSA) plutôt que de l’horloge de l’ordinateur du signataire. Ce tutoriel vous montre comment signer un document Word avec une signature XAdES‑T horodatée en Python, puis confirmer que l’horodatage se trouve dans le fichier.

Points clés

  • Définissez les deux SignOptions.xml_dsig_level = XmlDsigLevel.X_AD_ES_T et SignOptions.timestamp_settings. L’un ou l’autre seul produit une signature sans horodatage, et aucune erreur ne l’indique.
  • Aspose.Words demande l’horodatage pendant DigitalSignatureUtil.sign, donc cet appel nécessite un accès réseau au TSA.
  • Les fichiers DOCX et DOC peuvent être horodatés. Les fichiers ODT ne le peuvent pas.
  • DigitalSignature.is_valid vérifie la signature, pas l’horodatage. Confirmez l’horodatage séparément.

Ce que ajoute un horodatage de confiance à une signature

Chaque signature créée par Aspose.Words comporte un horodatage, défini par SignOptions.sign_time. Cette valeur provient de la machine du signataire, de sorte que toute personne contestant le document peut également contester l’heure.

Une signature XAdES‑T ajoute une preuve indépendante. Après que le document a été signé, Aspose.Words envoie un hachage de la valeur de la signature à un TSA. Le TSA renvoie un jeton RFC 3161, signé avec son propre certificat, qui lie le hachage à un moment précis. Ce jeton est stocké à l’intérieur de la signature. Un vérificateur peut alors démontrer que la signature existait à ce moment‑là, ce qui est particulièrement important lorsque le certificat de signature expire ou est révoqué ultérieurement.

Prérequis

Avant d’exécuter l’exemple, assurez‑vous d’avoir :

pip install --upgrade "aspose-words>=26.9"
  • Un certificat de signature au format PKCS#12 (.pfx ou .p12) et son mot de passe.
  • Une URL d’autorité d’horodatage. L’exemple utilise FreeTSA (https://freetsa.org/tsr), un TSA public gratuit pratique pour les tests. Pour les documents de production, utilisez le TSA recommandé par votre organisation ou votre fournisseur de certificats, car les personnes qui vérifient vos documents doivent faire confiance au certificat de ce TSA.
  • Identifiants TSA, uniquement si votre TSA nécessite une authentification.

Sans licence, Aspose.Words s’exécute en mode d’évaluation avec des limitations. Une licence temporaire les supprime pendant vos tests.

Signer un document Word avec un horodatage de confiance

Le script suivant signe un fichier DOCX avec une signature XAdES‑T et intègre un horodatage provenant du 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}")

Comment le code fonctionne

  • CertificateHolder.create lit la clé privée et la chaîne de certificats depuis le fichier .pfx. Un mot de passe incorrect échoue ici, avant que toute signature ne commence.
  • XmlDsigLevel.X_AD_ES_T indique à Aspose.Words de créer une signature XAdES‑T, qui est XAdES‑EPES plus un horodatage de signature.
  • DigitalSignatureTimestampSettings contient l’URL du TSA, un nom d’utilisateur et un mot de passe optionnels, ainsi qu’un délai d’attente optionnel. Les chaînes vides sont acceptables pour un TSA qui accepte les requêtes anonymes. Si le TSA répond avec un défi d’authentification HTTP, Aspose.Words envoie les informations d’identification que vous avez fournies.
  • DigitalSignatureUtil.sign écrit une copie signée dans OUTPUT_DOC et laisse le fichier d’entrée inchangé. Signez un document non signé : si l’entrée possède déjà une signature, la sortie contiendra à la fois la signature existante et la nouvelle.

Vérifiez que le horodatage a été intégré

Les objets DigitalSignature renvoyés par Aspose.Words n’exposent pas le horodatage, et is_valid ne le vérifie pas. Lors des tests, un document dont le jeton de horodatage avait été délibérément corrompu affichait toujours is_valid comme True. Pour confirmer le horodatage, examinez le XML de signature stocké dans le package 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")

Pour un DOCX signé, vous devriez voir une sortie similaire à celle-ci :

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

Pour lire l’heure certifiée par le TSA, transmettez le jeton enregistré à OpenSSL :

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

La ligne Time stamp indique l’heure certifiée en GMT, et la ligne TSA identifie l’autorité qui l’a émise.

Cette vérification lit le format de paquet DOCX. Un fichier DOC stocke sa signature dans un conteneur binaire, de sorte que le script basé sur ZIP ne s’applique pas à celui-ci.

Dépannage des erreurs de signature et d’horodatage

SymptômeCause probableQue faire
La signature réussit, mais aucun horodatage n’est intégréUn seul de xml_dsig_level = X_AD_ES_T et timestamp_settings était définiDéfinissez les deux avant d’appeler sign. Avec XML_D_SIG ou X_AD_ES_EPES, les paramètres d’horodatage sont ignorés.
RuntimeError mentionnant (401) UnauthorizedLe TSA nécessite des informations d’identification, ou celles‑ci sont incorrectesTransmettez le nom d’utilisateur et le mot de passe fournis par votre fournisseur TSA.
RuntimeError mentionnant une connexion refusée ou une erreur de proxyL’URL du TSA est incorrecte, ou un pare‑feu ou un proxy bloque la requêteVérifiez l’URL et confirmez que la machine exécutant votre script peut atteindre le TSA.
RuntimeError mentionnant The operation has timed outLe TSA n’a pas répondu dans le délai impartiRéessayez, ou transmettez un timeout plus long à DigitalSignatureTimestampSettings.
Un fichier de sortie vide reste après une erreursign crée le fichier de destination avant l’échec de la requête TSASupprimez le fichier de destination avant de réessayer, ou écrivez dans un chemin temporaire et renommez‑le après un appel réussi.
RuntimeError indiquant que l’horodatage n’est pas pris en charge par ce format de fichierL’entrée est un fichier ODTHorodatez les fichiers DOCX ou DOC, ou convertissez en PDF et utilisez la méthode de signature PDF décrite ci‑dessous.
No usable version of libssl was found, ou un plantage lié à un paquet ICU manquant, sous LinuxLe runtime .NET fourni avec le package Python nécessite OpenSSL 1.1 et une version ICU prise en chargeInstallez OpenSSL 1.1, ou installez une ICU prise en charge. Si votre application n’a pas besoin de formatage spécifique à la culture, définissez DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 pour l’erreur ICU.

Alternative : horodater une signature dans la sortie PDF

Si vos destinataires ont besoin d’un PDF plutôt que d’un fichier Word signé, vous n’avez pas besoin de DigitalSignatureUtil. Signez et horodate le PDF lors de l’enregistrement en définissant PdfSaveOptions.digital_signature_details.timestamp_settings sur un objet PdfDigitalSignatureTimestampSettings. Cette méthode est disponible depuis bien plus longtemps que la version 26.9. La référence PdfDigitalSignatureTimestampSettings comprend un exemple complet.

Prochaines étapes

Pour ajouter des lignes de signature, signer avec une image de ligne de signature ou supprimer des signatures existantes, consultez Travailler avec les signatures numériques dans la documentation Aspose.Words for Python.

FAQ

  1. Qu’est-ce qu’un horodatage de confiance ajoute à une signature numérique ?
    Une autorité d’horodatage (TSA) certifie l’heure à laquelle la signature a été créée. Cette heure provient d’un tiers indépendant plutôt que de l’horloge de l’ordinateur du signataire, et elle permet à un vérificateur de démontrer que la signature existait avant l’expiration ou la révocation du certificat de signature.

  2. Quelle version d’Aspose.Words prend en charge l’horodatage dans DigitalSignatureUtil ?
    La version 26.9 d’Aspose.Words for Python via .NET a ajouté SignOptions.timestamp_settings, XmlDsigLevel.X_AD_ES_T et la classe DigitalSignatureTimestampSettings. Les versions antérieures ne peuvent horodater les signatures que dans la sortie PDF.

  3. Dois‑je définir à la fois xml_dsig_level et timestamp_settings ?
    Oui. Si un seul de ces paramètres est défini, Aspose.Words signe toujours le document mais ne demande ni n’incorpore d’horodatage, et aucune erreur n’est levée.

  4. Quels formats de fichier peuvent être horodatés ?
    Les fichiers DOCX et DOC signés avec X_AD_ES_T reçoivent un horodatage. La signature d’un fichier ODT avec un horodatage génère une erreur indiquant que le format ne prend pas en charge l’horodatage.

  5. is_valid confirme‑t‑il que l’horodatage est valide ?
    Non. DigitalSignature.is_valid vérifie uniquement la signature elle‑même. Pour confirmer l’horodatage, il faut vérifier que le XML de la signature contient un jeton d’horodatage et inspecter ce jeton avec un outil tel qu’OpenSSL.

  6. Que se passe‑t‑il si la TSA est injoignable ?
    DigitalSignatureUtil.sign lève une RuntimeError décrivant le problème de réseau, d’authentification ou de délai d’attente. Le chemin de destination peut rester sous forme d’un fichier vide, il faut donc le supprimer avant de réessayer.

Obtenez une licence gratuite et le support