타임스탬프 기관 (TSA)
TCPDF-Next Pro는 프로덕션급 RFC 3161 타임스탬프 기관 클라이언트(TsaClient)와 PAdES B-LTA 워크플로를 위한 /DocTimeStamp 서명을 임베딩하는 DocumentTimestamp 헬퍼를 제공합니다.
TsaClient
기본 사용법
use Yeeefang\TcpdfNext\Pro\Tsa\TsaClient;
$tsa = new TsaClient(url: 'https://freetsa.org/tsr');
$token = $tsa->timestamp($pdfHash);인증을 사용한 경우
일부 엔터프라이즈 TSA 서버는 자격 증명이 필요합니다:
$tsa = new TsaClient(
url: 'https://tsa.enterprise.example/rfc3161',
username: 'api-user',
password: 'api-secret',
);RFC 3161 TimeStampReq 구성
클라이언트는 모든 요청에 대해 표준을 준수하는 TimeStampReq ASN.1 구조를 빌드합니다:
- MessageImprint -- 타임스탬프할 데이터의 SHA-256 다이제스트.
- Nonce -- 리플레이 공격을 방지하기 위한 암호학적으로 안전한 64비트 랜덤 값.
- CertReq -- TSA가 응답에 서명 인증서를 포함하도록
true로 설정.
// 해시는 원시 바이너리여야 합니다 (SHA-256의 경우 32바이트)
$hash = hash('sha256', $documentBytes, binary: true);
$token = $tsa->timestamp($hash, algorithm: 'sha256');논스 검증
TimeStampResp를 수신한 후 클라이언트는 자동으로:
- 응답에서
TSTInfo를 파싱합니다. TSTInfo에서 논스를 추출합니다.- 요청에서 보낸 논스와 비교합니다.
- 불일치하면
TsaNonceMismatchException을 발생시킵니다.
try {
$token = $tsa->timestamp($hash);
} catch (\Yeeefang\TcpdfNext\Pro\Tsa\TsaNonceMismatchException $e) {
// 논스 불일치 -- MITM 또는 리플레이 공격 가능성
log_security_event($e->getMessage());
}PKIStatus 검증
클라이언트는 모든 응답에서 PKIStatus 필드를 검증합니다:
| 코드 | 의미 | 클라이언트 동작 |
|---|---|---|
0 | granted | 토큰 승인 |
1 | grantedWithMods | 경고를 로깅하고 토큰 승인 |
2 | rejection | TsaRejectedException 발생 |
3 | waiting | 지원되지 않음; 예외 발생 |
4 | revocationWarning | 경고를 로깅하고 토큰 승인 |
5 | revocationNotification | TsaCertRevokedException 발생 |
DNS 핀닝 (SSRF 보호)
서버 측 요청 위조(SSRF)를 방지하기 위해 TSA 호스트명을 특정 IP 주소에 핀닝할 수 있습니다. 클라이언트는 CURLOPT_RESOLVE를 사용하여 DNS 해석을 완전히 우회합니다:
$tsa = new TsaClient(
url: 'https://tsa.enterprise.example/rfc3161',
);
// 호스트명을 알려진 IP에 핀닝 -- DNS를 조회하지 않음
$tsa->pinDns('tsa.enterprise.example', '203.0.113.42', port: 443);이는 TSA URL이 사용자 입력이나 외부 설정에서 유래하여 내부 네트워크 주소로 해석되면 안 되는 환경에서 중요합니다.
mTLS (상호 TLS)
엔터프라이즈 TSA 서버는 클라이언트 인증서 인증을 자주 요구합니다. 클라이언트 인증서와 개인 키를 전달하세요:
$tsa = new TsaClient(
url: 'https://tsa.bank.example/timestamp',
);
$tsa->clientCertificate(
certPath: '/etc/pki/tsa-client.pem',
keyPath: '/etc/pki/tsa-client.key',
keyPassword: 'client-key-pass',
);기본 cURL 핸들은 CURLOPT_SSLCERT, CURLOPT_SSLKEY, CURLOPT_SSLCERTPASSWD로 구성됩니다.
DocumentTimestamp (B-LTA)
DocumentTimestamp는 PDF에 /DocTimeStamp 서명을 추가하며, 이는 PAdES B-LTA 워크플로의 마지막 단계입니다. 이 타임스탬프는 이전의 모든 서명과 DSS(문서 보안 저장소)를 포함한 전체 문서를 커버합니다.
use Yeeefang\TcpdfNext\Pro\Tsa\DocumentTimestamp;
use Yeeefang\TcpdfNext\Pro\Tsa\TsaClient;
$tsa = new TsaClient(url: 'https://freetsa.org/tsr');
$stamper = new DocumentTimestamp(
tsaClient: $tsa,
hashAlgorithm: 'sha256',
);
// 문서 타임스탬프 적용 (증분 저장)
$stamper->apply($document);B-LTA 워크플로 요약
1. 문서 서명 (PAdES B-B)
2. 서명 타임스탬프 추가 (PAdES B-T)
3. DSS 임베딩 (OCSP + CRL) (PAdES B-LT)
4. /DocTimeStamp 추가 (PAdES B-LTA) <-- DocumentTimestamp인기 TSA 서버
| 제공업체 | URL | 인증 | 비고 |
|---|---|---|---|
| FreeTSA | https://freetsa.org/tsr | 없음 | 무료; 테스트용으로 적합 |
| Sectigo | https://timestamp.sectigo.com | 없음 | 프로덕션급; 무료 티어 |
| DigiCert | https://timestamp.digicert.com | 없음 | 광범위하게 신뢰됨 |
| GlobalSign | https://timestamp.globalsign.com/tsa/r6advanced1 | 없음 | SHA-256 기본값 |
| 커스텀 / 엔터프라이즈 | 다양 | Basic, mTLS, Bearer | pinDns() + clientCertificate() 사용 |
TIP
프로덕션 PAdES B-LTA 문서의 경우, Adobe 승인 신뢰 목록(AATL)에 루트 인증서가 포함된 TSA 제공업체를 사용하세요. 이렇게 하면 수동 신뢰 구성 없이 Adobe Acrobat에서 타임스탬프가 인식됩니다.