栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

iText7 LtvVerification.addVerification未启用LTV

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

iText7 LtvVerification.addVerification未启用LTV

您的代码不总是启用LTV的PDF的主要原因是,它没有添加与OCSP响应签名相关的验证信息。

它也不会添加CRL签名的验证信息。
但是,由于CRL通常由签署者证书的发行者证书签名,并且由于已经在主签名的上下文中添加了该发行者证书的验证信息,因此启用LTV通常不会因缺少CRL签名验证信息而失败。
。因此,如果您只能使用CRL,那么您的代码确实确实已经在启用LTV的PDF中了。

在此答案的上下文中(特别是其“使用自己的实用程序类的方法”一节),我

AdobeLtvEnabling
为iText
5 创建了一个实用程序类,以允许启用LTV的PDF,主要使用iText
5本身中的点点滴滴。与您的代码相反,它确实为OCSP响应签名(以及CRL签名)添加了验证信息。

在这里,您可以找到该类到iText 7的端口。

实用类
AdobeLtvEnabling

该实用程序类捆绑了LTV所需的代码,以在签名的PDF文档中启用签名。这些代码段大部分来自现有的iText代码。之所以没有设计此类的主要原因是该类

LtvVerification
所需的变量和方法是
private
。由于该类最初是为iText
5编写的,因此可能会在其中找到一些iText-5-ism。

public class AdobeLtvEnabling {        public AdobeLtvEnabling(Pdfdocument pdfdocument) {        this.pdfdocument = pdfdocument;    }        public void enable(IOcspClient ocspClient, ICrlClient crlClient) throws OperatorException, GeneralSecurityException, IOException, StreamParsingException, OCSPException {        SignatureUtil signatureUtil = new SignatureUtil(pdfdocument);        List<String> names = signatureUtil.getSignatureNames();        for (String name : names) { PdfPKCS7 pdfPKCS7 = signatureUtil.verifySignature(name, BouncyCastleProvider.PROVIDER_NAME); PdfSignature sig = signatureUtil.getSignature(name); List<X509Certificate> certificatesToCheck = new ArrayList<>(); certificatesToCheck.add(pdfPKCS7.getSigningCertificate()); while (!certificatesToCheck.isEmpty()) {     X509Certificate certificate = certificatesToCheck.remove(0);     addLtvForChain(certificate, ocspClient, crlClient, getSignatureHashKey(sig)); }        }        outputDss();    }    //    // the actual LTV enabling methods    //    void addLtvForChain(X509Certificate certificate, IOcspClient ocspClient, ICrlClient crlClient, PdfName key) throws GeneralSecurityException, IOException, StreamParsingException, OperatorCreationException, OCSPException {        ValidationData validationData = new ValidationData();        while (certificate != null) { System.out.println(certificate.getSubjectX500Principal().getName()); X509Certificate issuer = getIssuerCertificate(certificate); validationData.certs.add(certificate.getEnpred()); byte[] ocspResponse = ocspClient.getEnpred(certificate, issuer, null); if (ocspResponse != null) {     System.out.println("  with OCSP response");     validationData.ocsps.add(ocspResponse);     X509Certificate ocspSigner = getOcspSignerCertificate(ocspResponse);     if (ocspSigner != null) {         System.out.printf("  signed by %sn", ocspSigner.getSubjectX500Principal().getName());     }     addLtvForChain(ocspSigner, ocspClient, crlClient, getOcspHashKey(ocspResponse)); } else {    Collection<byte[]> crl = crlClient.getEnpred(certificate, null);    if (crl != null && !crl.isEmpty()) {        System.out.printf("  with %s CRLsn", crl.size());        validationData.crls.addAll(crl);        for (byte[] crlBytes : crl) { addLtvForChain(null, ocspClient, crlClient, getCrlHashKey(crlBytes));        }    } } certificate = issuer;        }        validated.put(key, validationData);    }    void outputDss() throws IOException {        PdfDictionary dss = new PdfDictionary();        PdfDictionary vrim = new PdfDictionary();        PdfArray ocsps = new PdfArray();        PdfArray crls = new PdfArray();        PdfArray certs = new PdfArray();        PdfCatalog catalog = pdfdocument.getCatalog();        if (pdfdocument.getPdfVersion().compareTo(PdfVersion.PDF_2_0) < 0) { catalog.addDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL5); catalog.addDeveloperExtension(new PdfDeveloperExtension(PdfName.ADBE, new PdfName("1.7"), 8));        }        for (PdfName vkey : validated.keySet()) { PdfArray ocsp = new PdfArray(); PdfArray crl = new PdfArray(); PdfArray cert = new PdfArray(); PdfDictionary vri = new PdfDictionary(); for (byte[] b : validated.get(vkey).crls) {     PdfStream ps = new PdfStream(b);     ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);     ps.makeIndirect(pdfdocument);     crl.add(ps);     crls.add(ps);     crls.setModified(); } for (byte[] b : validated.get(vkey).ocsps) {     b = buildOCSPResponse(b);     PdfStream ps = new PdfStream(b);     ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);     ps.makeIndirect(pdfdocument);     ocsp.add(ps);     ocsps.add(ps);     ocsps.setModified(); } for (byte[] b : validated.get(vkey).certs) {     PdfStream ps = new PdfStream(b);     ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);     ps.makeIndirect(pdfdocument);     cert.add(ps);     certs.add(ps);     certs.setModified(); } if (ocsp.size() > 0) {     ocsp.makeIndirect(pdfdocument);     vri.put(PdfName.OCSP, ocsp); } if (crl.size() > 0) {     crl.makeIndirect(pdfdocument);     vri.put(PdfName.CRL, crl); } if (cert.size() > 0) {     cert.makeIndirect(pdfdocument);     vri.put(PdfName.Cert, cert); } vri.put(PdfName.TU, new PdfDate().getPdfObject()); vri.makeIndirect(pdfdocument); vrim.put(vkey, vri);        }        vrim.makeIndirect(pdfdocument);        vrim.setModified();        dss.put(PdfName.VRI, vrim);        if (ocsps.size() > 0) { ocsps.makeIndirect(pdfdocument); dss.put(PdfName.OCSPs, ocsps);        }        if (crls.size() > 0) { crls.makeIndirect(pdfdocument); dss.put(PdfName.CRLs, crls);        }        if (certs.size() > 0) { certs.makeIndirect(pdfdocument); dss.put(PdfName.Certs, certs);        }        dss.makeIndirect(pdfdocument);        dss.setModified();        catalog.put(PdfName.DSS, dss);    }    //    // VRI signature hash key calculation    //    static PdfName getCrlHashKey(byte[] crlBytes) throws NoSuchAlgorithmException, IOException, CRLException, CertificateException {        CertificateFactory cf = CertificateFactory.getInstance("X.509");        X509CRL crl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(crlBytes));        byte[] signatureBytes = crl.getSignature();        DEROctetString octetString = new DEROctetString(signatureBytes);        byte[] octetBytes = octetString.getEnpred();        byte[] octetHash = hashBytesSha1(octetBytes);        PdfName octetName = new PdfName(convertToHex(octetHash));        return octetName;    }    static PdfName getOcspHashKey(byte[] basicResponseBytes) throws NoSuchAlgorithmException, IOException {        BasicOCSPResponse basicResponse = BasicOCSPResponse.getInstance(basicResponseBytes);        byte[] signatureBytes = basicResponse.getSignature().getBytes();        DEROctetString octetString = new DEROctetString(signatureBytes);        byte[] octetBytes = octetString.getEnpred();        byte[] octetHash = hashBytesSha1(octetBytes);        PdfName octetName = new PdfName(convertToHex(octetHash));        return octetName;    }    static PdfName getSignatureHashKey(PdfSignature sig) throws NoSuchAlgorithmException, IOException {        PdfString contents = sig.getContents();        byte[] bc = PdfEncodings.convertToBytes(contents.getValue(), null);        if (PdfName.ETSI_RFC3161.equals(sig.getSubFilter())) { try (   ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(bc)) ) {     ASN1Primitive pkcs = din.readObject();     bc = pkcs.getEnpred(); }        }        byte[] bt = hashBytesSha1(bc);        return new PdfName(convertToHex(bt));    }    static byte[] hashBytesSha1(byte[] b) throws NoSuchAlgorithmException {        MessageDigest sh = MessageDigest.getInstance("SHA1");        return sh.digest(b);    }    static String convertToHex(byte[] bytes) {        ByteBuffer buf = new ByteBuffer();        for (byte b : bytes) { buf.appendHex(b);        }        return PdfEncodings.convertToString(buf.toByteArray(), null).toUpperCase();    }    //    // OCSP response helpers    //    static X509Certificate getOcspSignerCertificate(byte[] basicResponseBytes) throws CertificateException, OCSPException, OperatorCreationException {        JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);        BasicOCSPResponse borRaw = BasicOCSPResponse.getInstance(basicResponseBytes);        BasicOCSPResp bor = new BasicOCSPResp(borRaw);        for (final X509CertificateHolder x509CertificateHolder : bor.getCerts()) { X509Certificate x509Certificate = converter.getCertificate(x509CertificateHolder); JcaContentVerifierProviderBuilder jcaContentVerifierProviderBuilder = new JcaContentVerifierProviderBuilder(); jcaContentVerifierProviderBuilder.setProvider(BouncyCastleProvider.PROVIDER_NAME); final PublicKey publicKey = x509Certificate.getPublicKey(); ContentVerifierProvider contentVerifierProvider = jcaContentVerifierProviderBuilder.build(publicKey); if (bor.isSignaturevalid(contentVerifierProvider))     return x509Certificate;        }        return null;    }    static byte[] buildOCSPResponse(byte[] BasicOCSPResponse) throws IOException {        DEROctetString doctet = new DEROctetString(BasicOCSPResponse);        ASN1EncodableVector v2 = new ASN1EncodableVector();        v2.add(OCSPObjectIdentifiers.id_pkix_ocsp_basic);        v2.add(doctet);        ASN1Enumerated den = new ASN1Enumerated(0);        ASN1EncodableVector v3 = new ASN1EncodableVector();        v3.add(den);        v3.add(new DERTaggedObject(true, 0, new DERSequence(v2)));         DERSequence seq = new DERSequence(v3);        return seq.getEnpred();    }    //    // X509 certificate related helpers    //    static X509Certificate getIssuerCertificate(X509Certificate certificate) throws IOException, StreamParsingException {        String url = getCACURL(certificate);        if (url != null && url.length() > 0) { HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection(); if (con.getResponseCode() / 100 != 2) {     throw new PdfException(PdfException.InvalidHttpResponse1).setMessageParams(con.getResponseCode()); } InputStream inp = (InputStream) con.getContent(); X509CertParser parser = new X509CertParser(); parser.engineInit(new ByteArrayInputStream(StreamUtil.inputStreamToArray(inp))); return (X509Certificate) parser.engineRead();        }        return null;    }    static String getCACURL(X509Certificate certificate) {        ASN1Primitive obj;        try { obj = getExtensionValue(certificate, Extension.authorityInfoAccess.getId()); if (obj == null) {     return null; } ASN1Sequence AccessDescriptions = (ASN1Sequence) obj; for (int i = 0; i < AccessDescriptions.size(); i++) {     ASN1Sequence AccessDescription = (ASN1Sequence) AccessDescriptions.getObjectAt(i);     if ( AccessDescription.size() != 2 ) {         continue;     }     else if (AccessDescription.getObjectAt(0) instanceof ASN1ObjectIdentifier) {         ASN1ObjectIdentifier id = (ASN1ObjectIdentifier)AccessDescription.getObjectAt(0);         if ("1.3.6.1.5.5.7.48.2".equals(id.getId())) {  ASN1Primitive description = (ASN1Primitive)AccessDescription.getObjectAt(1);  String AccessLocation =  getStringFromGeneralName(description);  if (AccessLocation == null) {      return "" ;  }  else {      return AccessLocation ;  }         }     } }        } catch (IOException e) { return null;        }        return null;    }    static ASN1Primitive getExtensionValue(X509Certificate certificate, String oid) throws IOException {        byte[] bytes = certificate.getExtensionValue(oid);        if (bytes == null) { return null;        }        ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bytes));        ASN1OctetString octs = (ASN1OctetString) aIn.readObject();        aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets()));        return aIn.readObject();    }    static String getStringFromGeneralName(ASN1Primitive names) throws IOException {        ASN1TaggedObject taggedObject = (ASN1TaggedObject) names ;        return new String(ASN1OctetString.getInstance(taggedObject, false).getOctets(), "ISO-8859-1");    }    //    // inner class    //    static class ValidationData {        final List<byte[]> crls = new ArrayList<byte[]>();        final List<byte[]> ocsps = new ArrayList<byte[]>();        final List<byte[]> certs = new ArrayList<byte[]>();    }    //    // member variables    //    final Pdfdocument pdfdocument;    final Map<PdfName,ValidationData> validated = new HashMap<PdfName,ValidationData>();}

( AdobeLtvEnabling.java)

使用范例

您可以使用以下

AdobeLtvEnabling
类:

try (   PdfReader pdfReader = new PdfReader(SOURCE);        PdfWriter pdfWriter = new PdfWriter(TARGET);        Pdfdocument pdfdocument = new Pdfdocument(pdfReader, pdfWriter,     new StampingProperties().preserveEncryption().useAppendMode())) {    AdobeLtvEnabling adobeLtvEnabling = new AdobeLtvEnabling(pdfdocument);    IOcspClient ocsp = new OcspClientBouncyCastle(null);    ICrlClient crl = new CrlClientonline();    adobeLtvEnabling.enable(ocsp, crl);}

( MakeLtvEnabled测试

testLtvEnableSignWithoutLtv

局限性

由于此代码实质上是从引用的答案的iText 5代码移植而来的,因此它还继承了该答案中列出的限制:

该代码在一些简化的限制下有效,尤其是:

  • 签名时间戳被忽略,
  • 假定检索到的CRL是直接而完整的,
  • 假定可以使用AIA条目构建完整的证书链。

如果您不能接受这些限制,则可以相应地改进代码。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/440437.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号