当前位置: 首页 > 知识库问答 >
问题:

iText通过检查CRL验证签名

蓝泰平
2023-03-14

我正在设置一个验证器,可以检查签名的有效性。

我所做的签名基于DSS级别LT,因此文档中内置了撤销检查。

我现在遇到的问题是在我在iText中开发的验证器级别上。它允许验证签名的有效性,但允许验证撤销的信息。根据我的研究,ITexts允许基于pkcs7.getCrl()验证签名本身中的信息。

然而,DSS签名将撤销信息纳入字典。

下面是我用来验证签名的代码:

import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.security.PdfPKCS7;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class TestCheck {

    public static String pdf_file = "CURRENT_SIGNATURE.pdf";

    public static final boolean verifySignature(PdfReader pdfReader)
            throws GeneralSecurityException, IOException {
        
        boolean valid = false;
        AcroFields acroFields = pdfReader.getAcroFields();
        
        
        PdfDictionary sigDict = acroFields.getSignatureDictionary("Signature1"); 
        System.out.println(sigDict);
        PdfString contents = sigDict.getAsString(PdfName.CONTENTS);

        
        List<String> signatureNames = acroFields.getSignatureNames();
        if (!signatureNames.isEmpty()) {
            for (String name : signatureNames) {
//                if (acroFields.signatureCoversWholeDocument(name)) {
                    PdfPKCS7 pkcs7 = acroFields.verifySignature(name);
                    valid = pkcs7.verify();
                    String reason = pkcs7.getReason();
                    Calendar signedAt = pkcs7.getSignDate();
                    X509Certificate signingCertificate = pkcs7.getSigningCertificate();
                    Principal issuerDN = signingCertificate.getIssuerDN();
                    Principal subjectDN = signingCertificate.getSubjectDN();
                    System.out.println("valid = "+valid);
                    //System.out.println("date = "+signedAt.getTime());
                    ////System.out.println("reason = "+reason);
                    //System.out.println("issuer = "+issuerDN);
                    //System.out.println("subject = "+subjectDN);
                    System.out.println("CRL : " + pkcs7.getCRLs());
                    break;
                }
           // }
        }
        return valid;
    }

    public static void main(String[] args) throws Exception {

        BouncyCastleProvider provider = new BouncyCastleProvider();
        Security.addProvider(provider);
        
        InputStream is = new FileInputStream(new File(pdf_file));
        PdfReader reader = new PdfReader(is);
        
        
        boolean ok = verifySignature(reader);
        System.out.println("Ver : "+ ok);
    }
}

共有1个答案

葛玉堂
2023-03-14

起初,我只想简单地指向iText 5和iText 7提供的LtvVerifier类。然而,该类测试结果不适用于当前的PAdES基线配置文件,而是针对较旧的PAdES LTV配置文件设计的(见ETSI TS 102 778-4第4节“PAdES LTV配置文件”)。

不过,如果我对你的问题理解正确,你已经知道如何评估CRL和OCSP的反应。因此,如果你学会了如何从DSS字典中提取撤销信息就足够了。

您的示例代码显然使用了iText 5。x、 所以我使用了当前的iText 5.5.14-SNAPSHOT。稍旧一点的版本也可以用于相同的代码。

PdfReader pdfReader = new PdfReader(...);

PdfDictionary dss = pdfReader.getCatalog().getAsDict(PdfName.DSS);
if (dss == null)
    System.out.println("No DSS in PDF");
else {
    PdfArray crlarray = dss.getAsArray(PdfName.CRLS);
    if (crlarray == null || crlarray.size() == 0)
        System.out.println("No CRLs in DSS");
    else {
        System.out.println("CRLs:");
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        for (int i = 0; i < crlarray.size(); i++) {
            PRStream stream = (PRStream) crlarray.getAsStream(i);
            X509CRL crl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(PdfReader.getStreamBytes(stream)));

            System.out.printf("  '%s' update %s\n", crl.getIssuerX500Principal(), crl.getThisUpdate());
        }
    }

    PdfArray ocsparray = dss.getAsArray(PdfName.OCSPS);
    if (ocsparray == null || ocsparray.size() == 0)
        System.out.println("\nNo OCSP responses in DSS");
    else {
        System.out.println("\nOCSP Responses:");
        for (int i = 0; i < ocsparray.size(); i++) {
            PRStream stream = (PRStream) ocsparray.getAsStream(i);
            OCSPResp ocspResponse = new OCSPResp(PdfReader.getStreamBytes(stream));
            if (ocspResponse.getStatus() == 0) {
                try {
                    BasicOCSPResp basicOCSPResp = (BasicOCSPResp) ocspResponse.getResponseObject();
                    System.out.printf("  '%s' update %s\n", basicOCSPResp.getResponderId(), basicOCSPResp.getProducedAt());
                } catch (OCSPException e) {
                    throw new GeneralSecurityException(e);
                }
            }
        }
    }
}

说明:测试testExtractRevocationInformationCURRENT_SIGNATURE

而不是将信息打印到系统。out您当然可以收集CRL和OCSP响应,并像以前一样处理它们。

此外,您当然可以检查从PdfPKCS7对象检索的吊销数据和从DSS检索的数据。Adobe Acrobat在验证过程中也会使用这两种方法。

 类似资料:
  • 在验证签名的上下文中,我希望在文档签名时验证签名证书的有效性。我意识到,如果我指定了过去的日期,则不使用CRL撤销检查方法,而如果我使用了当前时间或null,则撤销检查工作正常。我正在使用下一个代码 我已经启用了系统属性EnabledCRLDP。此外,OCSP不是一个通用的解决方案,因为它在某些证书中不起作用。 有什么理由不在过去的验证中使用CRL撤销方法? 在这种情况下,有什么方法可以强制使用C

  • 我在令牌使用者上得到以下错误。任何帮助解决这将是非常感谢的。多谢了。 “IDX10503:签名验证失败。 公共无效配置(IApplicationBuilder应用程序)

  • 我正在尝试用Itext 5和BouncyCastle 1.48验证PDF签名。我的代码适用于许多已签名的pdf,但也适用于特定客户的某些pdf。这是我的Java代码 有时我会遇到这样的例外: JAVAlang.IllegalArgumentException:getInstance:org中的未知对象。蹦蹦跳跳。asn1。Asn1在组织中列举。蹦蹦跳跳。asn1。ASN1序列。组织上的getIns

  • 我尝试了很多解决方案,但都是徒劳的。这就是我按照https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf的指导方针所做的: > 台阶 对auth请求进行放气,然后对其进行base64编码,最后对其进行Url编码。我们称之为AR Url编码RelayState。我们称之为RS Url编码签名算法字符串。我们称之为S

  • 我想知道是否有一个替代包括完整的CRL同时仍然支持LTV?包含完整的CRL似乎有点矫枉过正,而似乎唯一需要的“东西”是包含一个可验证的证明,证明链中的证书在签名时没有被撤销。我认为使用OCSP可能会提供这样的功能,但是简单地删除CRL并包含一个OcspClientBouncyCastle实例并不能起到作用。授予SignDetached的OCSP是否用于检查证书是否在签名时被吊销? 一个相关的问题涉