0

我正在尝试使用 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()没有执行执行?

4

0 回答 0