Java 如何使用pdfbox启用长期验证(LTV)

Java 如何使用pdfbox启用长期验证(LTV),java,pdfbox,signature,Java,Pdfbox,Signature,我使用pdfbox进行签名,但当acrobat reader中的检查签名有结果时:无法启用长期验证(LTV) 这是我的源代码 @Override public byte[] sign(InputStream content) throws IOException { try { CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); X509Certificate cert = (X509Ce

我使用pdfbox进行签名,但当acrobat reader中的检查签名有结果时:无法启用长期验证(LTV)

这是我的源代码

@Override
public byte[] sign(InputStream content) throws IOException {
    try {
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        X509Certificate cert = (X509Certificate) this.certificateChain[0];
        ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA256WithRSA").build(this.privateKey);
        gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(sha1Signer, cert));
        gen.addCertificates(new JcaCertStore(Arrays.asList(this.certificateChain)));
        CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
        CMSSignedData signedData = gen.generate(msg, false);

        //add timestamp if TSA is available
        TimeStampManager timeStampManager = new TimeStampManager();
        signedData = timeStampManager.addSignedTimeStamp(signedData, timeStampToken);
        return signedData.getEncoded();
    } catch (Exception e) {
        // Write log error sign to table Log in DB
        // TODO: 10/19/20  
        
        //throw new IOException cause a SignatureInterface
        throw new IOException(e);
    }
}
TimestampManager.addSignedTimeStamp

/**
 * Extend cms signed data with TimeStamp first or to all signers
 *
 * @param signedData Generated CMS signed data
 * @param timeStampToken TimeStampToken
 * @return CMSSignedData Extended CMS signed data
 * @throws IOException, TSPException
 */
public CMSSignedData addSignedTimeStamp(CMSSignedData signedData, TimeStampToken timeStampToken) throws IOException, TSPException {
    SignerInformationStore signerStore = signedData.getSignerInfos();
    List<SignerInformation> signersWithTimeStamp = new ArrayList<>();
   
    for (SignerInformation signer : signerStore.getSigners()) {
        // This adds a timestamp to every signer (into his unsigned attributes) in the signature.
        signersWithTimeStamp.add(signTimeStamp(signer, timeStampToken));
    }

    // new SignerInformationStore have to be created cause new SignerInformation instance
    // also SignerInformationStore have to be replaced in a signedData
    return CMSSignedData.replaceSigners(signedData, new SignerInformationStore(signersWithTimeStamp));
}

/**
 * Extend CMS Signer Information with the TimeStampToken into the unsigned Attributes.
 *
 * @param signer information about signer
 * @return information about SignerInformation
 * @throws IOException
 */
private SignerInformation signTimeStamp(SignerInformation signer, TimeStampToken timeStampToken) throws IOException, TSPException {
    AttributeTable unsignedAttributes = signer.getUnsignedAttributes();

    ASN1EncodableVector vector = new ASN1EncodableVector();
    if (unsignedAttributes != null) {
        vector = unsignedAttributes.toASN1EncodableVector();
    }

    byte[] token = timeStampToken.getEncoded();
    ASN1ObjectIdentifier oid = PKCSObjectIdentifiers.id_aa_signatureTimeStampToken;
    ASN1Encodable signatureTimeStamp = new Attribute(oid, new DERSet(ASN1Primitive.fromByteArray(token)));
    vector.add(signatureTimeStamp);
    Attributes signedAttributes = new Attributes(vector);

    // replace unsignedAttributes with the signed once
    return SignerInformation.replaceUnsignedAttributes(signer, new AttributeTable(signedAttributes));
}
/**
*首先扩展带有时间戳的cms签名数据或扩展到所有签名者
*
*@param signedData生成的CMS签名数据
*@param timestaken timestaken
*@return CMSSignedData扩展CMS签名数据
*@IOException,tspeException
*/
公共CMSSignedData addSignedTimeStamp(CMSSignedData signedData,TimeStampToken TimeStampToken)引发IOException,TSPEException{
SignerInformationStore signerStore=signedData.getSignerInfos();
List signersWithTimeStamp=new ArrayList();
for(SignerInformation signer:signerStore.getSigners()){
//这将为签名中的每个签名者(到其未签名的属性中)添加一个时间戳。
signersWithTimeStamp.add(signTimeStamp(signer,timestank));
}
//必须创建新的SignerinInformation存储,因为需要创建新的SignerinInformation实例
//还必须在signedData中替换SignerInformationStore
返回CMSSignedData.replaceSigners(signedData,新SignerInformationStore(signersWithTimeStamp));
}
/**
*使用TimeStampToken将CMS签名者信息扩展到未签名属性中。
*
*@param签名者关于签名者的信息
*@返回有关签名信息的信息
*@抛出异常
*/
私有SignerInformation signTimeStamp(SignerInformation signer,TimeStampToken TimeStampToken)抛出IOException,tspeexception{
AttributeTable UnsignedAttribute=signer.GetUnsignedAttribute();
ASN1EncodableVector=新的ASN1EncodableVector();
if(unsignedAttribute!=null){
vector=unsignedAttribute.toASN1EncodableVector();
}
byte[]token=timeStampToken.getEncoded();
ASN1ObjectIdentifier oid=PKCSObjectIdentifiers.id_aa_signatureTimeStampToken;
ASN1Encodable signatureTimeStamp=新属性(oid,新DERSet(ASN1Primitive.fromByteArray(token));
vector.add(signatureTimeStamp);
属性signedAttributes=新属性(向量);
//将未签名的属性替换为已签名的属性
返回SignerInformation.ReplaceUnsignedAttribute(签名者,新属性表(SignedAttribute));
}
我想签名自动启用LTV相同的这个

请在我的源代码中使用pdfbox帮助自动启用签名中的LTV! 谢谢

更新: 使用pdf示例版本2.0.21时的问题
然后我将版本pdf示例更新为2.0.23,然后我的问题是解决

您是否尝试了源代码下载中的
AddValidationInformation.java
示例?我尝试了AddValidationInformation AddValidationInformation validation=new AddValidationInformation();File outFile=File.createTempFile(“outPdf”,“.pdf”);验证。验证签名(填充、输出文件);但有错误:找不到证书的颁发者证书:“CN=AMANO-TSU-320,OU=Thales TSS ESN:D420-2845-7C98,OU=e-timing TSA,O=AMANO Corporation,L=Yokohama,ST=Kanagawa,C=JP”,即证书'CN=SECOM时间戳CA3,O=“SECOM信托系统有限公司”,C=JP'在链中丢失,原因是证书和时间戳不匹配,因为我从secom购买的证书和我从天野之弥购买的时间戳?这意味着您的TSA服务器没有返回整个链,并且证书没有告诉从哪里获取它。告诉TSA返回整个链,或者自己下载丢失的证书并在需要时添加,即更改示例代码,以便在需要时使用此证书。签名和时间戳不必来自同一供应商。@ShahidGhafoor请帮助我解决此问题。@Tilmanhausher我发送信息链接文件签名pdf:TSA证书:amano时间戳谢谢您至少应该提到您使用了
AddValidationInformation
。示例中没有“自动启用LTV”。