代码之家  ›  专栏  ›  技术社区  ›  dpilwal

itext不工作时的数字签名验证

  •  1
  • dpilwal  · 技术社区  · 8 年前

    https://developers.itextpdf.com/examples/security/digital-signatures-white-paper/digital-signatures-chapter-5 地点我在验证数字签名文档时出现以下错误。有谁能帮助解决这个问题吗。

    Exception in thread "main" ExceptionConverter: java.security.NoSuchAlgorithmException: SHA256with1.2.840.10045.4.3.2 Signature not available
    at java.security.Signature.getInstance(Signature.java:229)
    at com.itextpdf.text.pdf.security.PdfPKCS7.initSignature(PdfPKCS7.java:697)
    at com.itextpdf.text.pdf.security.PdfPKCS7.<init>(PdfPKCS7.java:459)
    at com.itextpdf.text.pdf.AcroFields.verifySignature(AcroFields.java:2420)
    at com.itextpdf.text.pdf.AcroFields.verifySignature(AcroFields.java:2373)
    at nic.test.C5_01_SignatureIntegrity.verifySignature(C5_01_SignatureIntegrity.java:24)
    at test.ExtractSignInfor.inspectSignature(ExtractSignInfor.java:95)
    at test.ExtractSignInfor.inspectSignatures(ExtractSignInfor.java:135)
    at test.ExtractSignInfor.main(ExtractSignInfor.java:63)
    
    2 回复  |  直到 8 年前
        1
  •  5
  •   Michaël Demey    8 年前

    如果您搜索iText阻塞的OID,您将看到这是“ecdsa-with-sha256”:

    http://www.oid-info.com/get/1.2.840.10045.4.3.2

    iText 5不支持这一点。但我们确实在iText 7中添加了对此的支持。尝试使用最新的iText 7版本运行此代码示例:

    BouncyCastleProvider provider = new BouncyCastleProvider();
    Security.addProvider(provider);
    
    PdfReader reader = new PdfReader(INPUT);
    PdfDocument pdfDocument = new PdfDocument(reader);
    
    PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDocument, false);
    
    for ( String name : acroForm.getFormFields().keySet() ) {
        PdfFormField formField = acroForm.getField(name);
        if (formField != null && formField instanceof PdfSignatureFormField)    {
            SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
            PdfPKCS7 pkcs7 = signatureUtil.verifySignature(name);
            pkcs7.verify();
            [...]
    
        2
  •  4
  •   mkl    8 年前

    正如迈克尔·德米在他的回答中已经解释的那样,这是第5条。x目前不支持有问题的算法OID。

    不过幸运的是,我的文字是5。在签名验证期间,x主要依靠底层的BouncyCastle库来支持安全算法,而其本身做的很少,所缺少的只是iText正确地找到OID的“加密算法”ECDSA的名称(在引号中,因为它不是真正的加密,因为没有并行解密)。

    您可以在iText 5中添加该OID的验证支持。x(在5.5.13的当前快照中测试)如下:

    java.lang.reflect.Field algorithmNamesField = com.itextpdf.text.pdf.security.EncryptionAlgorithms.class.getDeclaredField("algorithmNames");
    algorithmNamesField.setAccessible(true);
    @SuppressWarnings("unchecked")
    HashMap<String, String> algorithmNames = (HashMap<String, String>) algorithmNamesField.get(null);
    algorithmNames.put("1.2.840.10045.4.3.2", "ECDSA");
    

    执行此添加后,iText验证

    PdfReader reader = new PdfReader(resource);
    AcroFields acroFields = reader.getAcroFields();
    
    List<String> names = acroFields.getSignatureNames();
    for (String name : names) {
       System.out.println("Signature name: " + name);
       System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name));
       System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions());
       PdfPKCS7 pk = acroFields.verifySignature(name);
       System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate()));
       System.out.println("Document verifies: " + pk.verify());
    }
    

    Signature name: Signature1
    Signature covers whole document: true
    Document revision: 1 of 1
    Subject: {ST=[Rajasthan], C=[India], CN=[Devi Singh Pilwal], O=[Personal]}
    Document verifies: true
    

    (测试代码 VerifySignature.java 方法 testVerifyTestDsp

    • 上面的代码使用反射作为 Map 有问题的不是公开的。根据您的环境,可能不允许使用这种解决方案。在这种情况下,您必须相应地修补iText。此外,由于 如果不公开,解决方案可能在未来版本中失败。(这不太可能,因为iText 5处于维护模式,但谁也不知道。)

    • 这个很老了

    • 验证 用例。ECDSA签名可能需要完全不同的更改。

    推荐文章