디지털 서명은 누가 문서에 서명했는지를 기록합니다. 신뢰할 수 있는 타임스탬프는 언제를 기록하며, 그 시간은 서명자의 컴퓨터 시계가 아니라 독립적인 타임스탬프 권한 기관(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 토큰을 반환하며, 이 토큰은 해시를 특정 시간에 연결합니다. 해당 토큰은 서명 내부에 저장됩니다. 검증자는 이후 서명이 그 순간에 존재했음을 보여줄 수 있으며, 이는 서명 인증서가 나중에 만료되거나 폐기될 때 가장 중요합니다.
사전 요구 사항
예제를 실행하기 전에, 다음이 준비되어 있는지 확인하세요:
- Aspose.Words for Python via .NET 26.9 이상. 설치하거나 업그레이드하려면 PyPI에서.
pip install --upgrade "aspose-words>=26.9"
- 서명 인증서 in PKCS#12 format (
.pfxor.p12) and its password. - 타임스탬프 권한 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에 기록하고 입력 파일은 변경하지 않습니다. 서명되지 않은 문서를 서명하면: 입력에 이미 서명이 있는 경우 출력에 기존 서명과 새로운 서명이 모두 포함됩니다.
타임스탬프가 포함되었는지 확인
DigitalSignature 객체는 Aspose.Words가 반환하지만 타임스탬프를 노출하지 않으며, 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
- 신뢰할 수 있는 타임스탬프가 디지털 서명에 무엇을 추가합니까?
타임스탬프 인증 기관(TSA)은 서명이 생성된 시간을 인증합니다. 이 시간은 서명자의 컴퓨터 시계가 아니라 독립적인 제3자에 의해 제공되며, 검증자가 서명 인증서가 만료되거나 폐기되기 전에 서명이 존재했음을 확인할 수 있게 합니다. - DigitalSignatureUtil에서 타임스탬프를 지원하는 Aspose.Words 버전은 어느 것인가요?
Aspose.Words for Python via .NET의 버전 26.9에서는SignOptions.timestamp_settings,XmlDsigLevel.X_AD_ES_T및DigitalSignatureTimestampSettings클래스를 추가했습니다. 이전 버전에서는 PDF 출력에서만 서명에 타임스탬프를 적용할 수 있습니다. - xml_dsig_level과 timestamp_settings를 모두 설정해야 하나요?
예. 둘 중 하나만 설정하면 Aspose.Words는 여전히 문서를 서명하지만 타임스탬프를 요청하거나 삽입하지 않으며 오류도 발생시키지 않습니다. - 어떤 파일 형식에 타임스탬프를 적용할 수 있나요?
X_AD_ES_T로 서명된 DOCX 및 DOC 파일은 타임스탬프를 받습니다. ODT 파일에 타임스탬프를 적용하려고 하면 해당 형식이 타임스탬프를 지원하지 않는다라는 오류가 발생합니다. - is_valid가 타임스탬프가 유효함을 확인합니까?
아니요.DigitalSignature.is_valid는 서명 자체만 확인합니다. 타임스탬프를 확인하려면 서명 XML에 타임스탬프 토큰이 포함되어 있는지 확인하고, OpenSSL과 같은 도구로 해당 토큰을 검사해야 합니다. - TSA에 연결할 수 없으면 어떻게 되나요?
DigitalSignatureUtil.sign은 네트워크, 인증 또는 시간 초과 문제를 설명하는RuntimeError를 발생시킵니다. 대상 경로에 빈 파일이 남을 수 있으므로 재시도하기 전에 해당 파일을 삭제하십시오.
