我正在尝试使用 Apache PDFBox 2.0.8 将 TSA 时间戳添加到 pdf 文档中。
这是设置和处理时间戳的方法:
@Override
public void timestampPDFDocument() throws IOException, SignatureException, COSVisitorException {
final PDSignature signature = new PDSignature();
signature.setType(COSName.DOC_TIME_STAMP);
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(COSName.getPDFName("ETSI.RFC3161"));
signature.setSignDate(Calendar.getInstance());
signature.setReason("test");
final PDDocument pdf = PDDocument.load(dataSrv.currentCtxFile());
final TimestampPDFImplementation sig = new TimestampPDFImplementation(cHTTPProxyPassword, cHTTPProxyUsername, ctstHttpUrl, signingCrt);
SignatureOptions options = new SignatureOptions();
pdf.addSignature(signature, sig, options);
pdf.save(dataSrv.createNewAndHandBufferedOutputStream());
pdf.close();
}
我将每个请求的文件存储在内存中,以便更轻松地操作“共享资源”,这就是加载时 pdf 的来源:
PDDocument.load(dataSrv.currentCtxFile());
我的实现SignatureInterface
:
public class TimestampPDFImplementation implements SignatureInterface {
String cHTTPProxyPassword;
String cHTTPProxyUsername;
String ctstHttpUrl;
String signingCrt;
public TimestampPDFImplementation(String cHTTPProxyPassword, String cHTTPProxyUsername, String ctstHttpUrl, String signingCrt) {
this.cHTTPProxyPassword = cHTTPProxyPassword;
this.cHTTPProxyUsername = cHTTPProxyUsername;
this.ctstHttpUrl = ctstHttpUrl;
this.signingCrt = signingCrt;
}
@Override
public byte[] sign(InputStream inputStream) throws SignatureException, IOException {
TElHTTPTSPClient tspClient = new TElHTTPTSPClient();
TElHTTPSClient httpClient = new TElHTTPSClient();
TElMemoryCertStorage certStorage = new TElMemoryCertStorage();
if (!Strings.isNullOrEmpty(cHTTPProxyPassword) &&
!Strings.isNullOrEmpty(cHTTPProxyUsername)) {
// set the http client
TElHTTPRequestParams requestParams = new TElHTTPRequestParams();
requestParams.setUsername(cHTTPProxyUsername);
requestParams.setPassword(cHTTPProxyPassword);
httpClient.setRequestParameters(requestParams);
}
tspClient.setHTTPClient(httpClient);
tspClient.setHashAlgorithm(SBConstants.SB_ALGORITHM_DGST_SHA512);
tspClient.setURL(ctstHttpUrl);
certStorage.add(loadCrt(signingCrt, ""), false);
httpClient.setCertStorage(certStorage);
tspClient.setIncludeCertificates(true);
tspClient.setOnHTTPError(setErrEvntHandler());
httpClient.setOnCertificateValidate(crtValidateEvent());
TElTSPReply tspReply = new TElTSPReply();
tspClient.timestamp(ByteStreams.toByteArray(inputStream), tspReply);
tspClient.Destroy();
if (tspReply.FailureInfo != 0 || tspReply.ServerResult != 0)
throw new SignatureException(
String.format("timestamping service error; FailureInfo: %s, ServerResult: %s", tspReply.FailureInfo, tspReply.ServerResult)
);
return tspReply.ReplyCMS;
}
private TSBHTTPTSPErrorEvent setErrEvntHandler() {
TSBHTTPTSPErrorEvent.Callback callback = (tObject, i) -> {
System.out.println();
};
return new TSBHTTPTSPErrorEvent(callback);
}
private TSBCertificateValidateEvent crtValidateEvent() {
TSBCertificateValidateEvent.Callback callback = (tObject, tElX509Certificate, tElX509CertificateValidateResult) -> {
// tElX509Certificate.loadFromFileAuto(signingCrt, "");
tElX509CertificateValidateResult.Validity = TSBCertificateValidity.cvOk;
tElX509CertificateValidateResult.Reason = 0;
};
return new TSBCertificateValidateEvent(callback);
}
private TElX509Certificate loadCrt(String filename, String crtPass) {
TElX509Certificate certificate = new TElX509CachedCertificate();
certificate.loadFromFileAuto(filename, crtPass);
return certificate;
}
}
签名逻辑应该没问题,我之前验证过。
我对这一切的问题是该byte[] sign(InputStream inputStream)
方法从未被执行过。没有抛出异常。保存的 PDF 的大小增加了,但是当绕过时间戳逻辑时没有效果。
timestampPDFDocument()
从注入@Service
到应用程序事件侦听器中调用并从那里调用。
那么,在这里正确执行 TSA 时间戳我缺少什么以及为什么sign()
没有执行执行?