デジタル署名は、誰が文書に署名したかを記録します。
信頼できるタイムスタンプは いつ を記録し、その時間は署名者のコンピュータの時計ではなく、独立したタイムスタンプ認証局 (TSA) から取得されます。
このチュートリアルでは、Python でタイムスタンプ付き XAdES‑T 署名を使用して Word 文書に署名する方法と、ファイル内にタイムスタンプが含まれていることを確認する方法を示します。

主なポイント

  • 両方 SignOptions.xml_dsig_level = XmlDsigLevel.X_AD_ES_T と SignOptions.timestamp_settings を設定してください。どちらか一方だけを設定すると、タイムスタンプなしの署名が生成され、エラーは通知されません。
  • Aspose.Words は DigitalSignatureUtil.sign の実行中にタイムスタンプを要求するため、その呼び出しには TSA へのネットワークアクセスが必要です。
  • DOCX と DOC ファイルはタイムスタンプを付与できます。ODT ファイルはできません。
  • DigitalSignature.is_valid は署名をチェックし、タイムスタンプはチェックしません。タイムスタンプは別途確認してください。

信頼できるタイムスタンプが署名にもたらすもの

Aspose.Words が作成するすべての署名には、SignOptions.sign_time で設定される署名時刻が含まれます。その値は署名者のマシンから取得されるため、文書の時間に異議を唱える者はその時刻にも異議を唱えることができます。

XAdES‑T 署名は独立した証拠を追加します。ドキュメントが署名された後、Aspose.Words は署名値のハッシュを TSA に送信します。TSA は RFC 3161 トークンを返し、独自の証明書で署名され、ハッシュを特定の時刻に結び付けます。そのトークンは署名内に保存されます。検証者はその署名がその時点で存在したことを示すことができ、署名証明書が後で期限切れになるか取り消される場合に最も重要です。

前提条件

例を実行する前に、以下が揃っていることを確認してください:

pip install --upgrade "aspose-words>=26.9"
  • 署名証明書 を PKCS#12 形式(.pfx または .p12)で、パスワードと共に。
  • タイムスタンプ認証局 URL。例では FreeTSA (https://freetsa.org/tsr) を使用しています。これはテストに便利な無料の公開 TSA です。本番用ドキュメントでは、組織または証明書プロバイダーが推奨する TSA を使用してください。ドキュメントを検証する人々がその TSA の証明書を信頼できる必要があります。
  • TSA 資格情報、TSA が認証を必要とする場合のみ。

ライセンスがない場合、Aspose.Words は制限付きの評価モードで実行されます。テスト中にこれらの制限を解除するには、一時ライセンス を使用します。

信頼できるタイムスタンプでWordドキュメントに署名する

以下のスクリプトは、DOCXファイルにXAdES‑T署名を付与し、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}")

コードの仕組み

  • CertificateHolder.create は .pfx ファイルから秘密鍵と証明書チェーンを読み取ります。パスワードが間違っている場合、署名が開始される前にここで失敗します。
  • XmlDsigLevel.X_AD_ES_T は Aspose.Words に XAdES-T 署名を作成するよう指示します。これは XAdES-EPES に署名タイムスタンプを加えたものです。
  • DigitalSignatureTimestampSettings は TSA の URL、オプションのユーザー名とパスワード、オプションのタイムアウトを保持します。匿名リクエストを受け付ける TSA では空文字列でも問題ありません。TSA が HTTP 認証チャレンジで応答した場合、Aspose.Words は提供された資格情報を送信します。
  • DigitalSignatureUtil.sign は署名済みのコピーを OUTPUT_DOC に書き込み、入力ファイルは変更しません。未署名のドキュメントに署名する場合、入力に既に署名があると、出力には既存の署名と新しい署名の両方が含まれます。

タイムスタンプが埋め込まれていることを確認する

Aspose.Words が返す DigitalSignature オブジェクトはタイムスタンプを公開せず、is_valid もそれをチェックしません。テストでは、タイムスタンプ トークンを意図的に破損させたドキュメントでも is_valid が True と報告されました。タイムスタンプを確認するには、DOCX パッケージに保存されている署名 XML を確認してください。

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")

署名された DOCX の場合、次のような出力が表示されます:

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

TSAが認証した時間を読み取るには、保存されたトークンをOpenSSLに渡します:

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

Time stamp 行は GMT の認証された時間を示し、TSA 行はそれを発行した権限を特定します。

このチェックは DOCX パッケージ形式を読み取ります。DOC ファイルは署名をバイナリ コンテナに保存するため、ZIP ベースのスクリプトは適用できません。

署名およびタイムスタンプエラーのトラブルシューティング

症状考えられる原因対策
署名は成功するが、タイムスタンプが埋め込まれないxml_dsig_level = X_AD_ES_T と timestamp_settings のうち片方だけが設定されていたsign を呼び出す前に両方を設定する。XML_D_SIG または X_AD_ES_EPES を使用すると、タイムスタンプ設定は無視される。
RuntimeError に (401) Unauthorized が含まれるTSA が認証情報を必要としている、または認証情報が間違っているTSA プロバイダーから発行されたユーザー名とパスワードを渡す。
RuntimeError に接続拒否またはプロキシエラーが含まれるTSA の URL が間違っている、またはファイアウォールやプロキシがリクエストをブロックしているURL を確認し、スクリプトを実行しているマシンが TSA に到達できることを確認する。
RuntimeError に The operation has timed out が含まれるTSA がタイムアウト内に応答しなかった再試行するか、DigitalSignatureTimestampSettings により長い timeout を渡す。
エラー後に空の出力ファイルが残るsign が TSA リクエストが失敗する前に宛先ファイルを作成する再試行前に宛先ファイルを削除するか、テンポラリパスに書き込み、成功した呼び出し後にリネームする。
RuntimeError がこのファイル形式ではタイムスタンプがサポートされていないと言う入力が ODT ファイルであるDOCX または DOC ファイルにタイムスタンプを付けるか、PDF に変換して以下で説明する PDF 署名ルートを使用する。
No usable version of libssl was found、または Linux で ICU パッケージが見つからないというクラッシュPython パッケージに同梱された .NET ランタイムは OpenSSL 1.1 とサポートされている ICU バージョンが必要OpenSSL 1.1 をインストールするか、サポートされている ICU をインストールする。アプリケーションがロケール固有のフォーマットを必要としない場合は、ICU エラー対策として DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 を設定する。

代替案: PDF 出力で署名にタイムスタンプを付ける

受信者が署名済み Word ファイルではなく PDF を必要とする場合、DigitalSignatureUtil は必要ありません。PdfSaveOptions.digital_signature_details.timestamp_settings に PdfDigitalSignatureTimestampSettings オブジェクトを設定して、保存時に PDF に署名とタイムスタンプを付けます。この方法は 26.9 よりはるかに前から利用可能です。PdfDigitalSignatureTimestampSettings リファレンス には完全なサンプルが含まれています。

次のステップ

署名行を追加したり、署名行画像で署名したり、既存の署名を削除したりするには、Aspose.Words for Python のドキュメントにある デジタル署名の操作 を参照してください。

FAQs

  1. 信頼できるタイムスタンプはデジタル署名に何を追加しますか?
    タイムスタンプ機関 (TSA) は署名が作成された時刻を認証します。その時刻は署名者のコンピュータの時計ではなく、独立した第三者から取得され、検証者は署名が署名証明書の有効期限切れや失効前に存在していたことを示すことができます。

  2. どの Aspose.Words バージョンが DigitalSignatureUtil のタイムスタンプをサポートしていますか?
    Aspose.Words for Python via .NET のバージョン 26.9 で SignOptions.timestamp_settings、XmlDsigLevel.X_AD_ES_T、および DigitalSignatureTimestampSettings クラスが追加されました。以前のバージョンでは PDF 出力の署名にのみタイムスタンプを付与できます。

  3. xml_dsig_level と timestamp_settings の両方を設定する必要がありますか?
    はい。どちらか一方だけを設定した場合、Aspose.Words はドキュメントに署名はしますが、タイムスタンプの要求や埋め込みは行わず、エラーも発生しません。

  4. どのファイル形式にタイムスタンプを付与できますか?
    X_AD_ES_T で署名された DOCX および DOC ファイルにはタイムスタンプが付与されます。ODT ファイルにタイムスタンプを付与しようとすると、該当フォーマットがタイムスタンプに対応していない旨のエラーが発生します。

  5. is_valid はタイムスタンプが有効であることを確認しますか?
    いいえ。DigitalSignature.is_valid は署名自体をチェックします。タイムスタンプを確認するには、署名 XML にタイムスタンプトークンが含まれているかを確認し、OpenSSL などのツールでそのトークンを検査してください。

  6. TSA に到達できない場合はどうなりますか?
    DigitalSignatureUtil.sign はネットワーク、認証、またはタイムアウトの問題を示す RuntimeError をスローします。宛先パスには空のファイルが残る可能性があるため、再試行する前に削除してください。

無料ライセンスとサポートを取得