微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 iText、PKCS11 和 SHA-256 算法签署 PDF 时出现问题 文档摘要不匹配损坏的原始 RSA 签名

如何解决使用 iText、PKCS11 和 SHA-256 算法签署 PDF 时出现问题 文档摘要不匹配损坏的原始 RSA 签名

我正在尝试使用 PCKS11(USB 令牌)和 iText 签署 pdf,当我使用 SHA-1 算法时它工作正常,签名有效并且一切正常但是当我将其更改为 SHA256 时,签名不是有效,有谁知道为什么?我会把我的代码放在下面:

PKCS11 pkcs11 = PKCS11.getInstance("C:\\Windows\\System32\\example.dll","C_GetFunctionList",null,false);
long[] slotList = pkcs11.C_GetSlotList(true);
String providerString = "name=*\nlibrary=C:\\Windows\\System32\\example.dll\n" + "slot=" + slotList [0];
SunPKCS11 sunPKCS11 = new SunPKCS11(new ByteArrayInputStream(providerString .getBytes()));
Provider provider = sunPKCS11;

KeyStore keyStore = KeyStore.getInstance("PKCS11",provider);
keyStore.load(null,password);
keyStore.aliases();


Security.addProvider(keyStore.getProvider());

List<String> aliases = Collections.list(keyStore.aliases());
String alias = aliases.get(0);

PrivateKey pk = (PrivateKey)keyStore.getKey(alias,password);

Certificate[] certChain = new Certificate[1];
certChain[0] = signerCert;

PdfReader reader = new PdfReader(inputData);

ByteArrayOutputStream outStream = new ByteArrayOutputStream();        
    
pdfstamper stamper = pdfstamper.createSignature(reader,outStream,'\0',true);
    
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();

String fieldName = keyStore.getCertificatealias(signerCert).replaceAll(".","");

appearance.setVisibleSignature(new Rectangle(420,10,70,85),pageNumber,fieldName);

ExternalSignature es = new PrivateKeySignature(pk,DigestAlgorithms.SHA256,keyStore.getProvider().getName());

    ExternalDigest digest = new BouncyCastleDigest();
    
    MakeSignature.signDetached(appearance,digest,es,certChain,CryptoStandard.CADES);
      
    return outStream.toByteArray();

为什么它适用于 SHA-1 而不是 SHA-2?您认为问题出在哪里?

解决方法

您的签名存在不匹配和错误。

download.pdf

这是您在问题评论中分享的示例文件

文档摘要不匹配

PDF 签名字节的 SHA-256 哈希值为

9356BCD36F172806A3DCE7F062A66441E7C1DDC9203ABDAA0154A3F19208C8E3

但嵌入式签名容器声称它是

5F892978FF2459157D631809A05F5DBCFCB55800236D2D5C3E4E4D94577012B4

根据您的代码,不应该发生。您确定问题中的代码已创建 PDF 吗?或者您是否按照您的 I changed my hash like this 评论指出的方式对其进行了更改,然后创建了示例文档?那么这种差异很可能是由您的更改引起的。

损坏的原始 RSA 签名

解密原始签名字节并去除填充后得到

3031300D0609608648016503040201050004201DC71B824BAA3C7EC6744A0941CFADDAA893E8C1

这是不完整的。它对应于

SEQUENCE (2 elem)
  SEQUENCE (2 elem)
    OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST Algorithm)
    NULL
  OCTET STRING (32 byte) 1DC71B824BAA3C7EC6744A0941CFADDAA893E8C1XXXXXXXXXXXXXXXXXXXXXXXX

缺少该 XXXXXXXXXXXXXXXXXXXXXXXX 部分的 12 个字节。

因此,签名设备似乎并不真正支持 SHA256withRSA,至少不与 example.dll PKCS#11 驱动程序和 SunPKCS11 安全提供程序结合使用。

顺便说一句,那里的 OCTET STRING 应该是

EC7FCC5D003DFEC58B0ECB49CEEAD28495FFA8D798A1A88DA6051C1857B971EC

因此,这里看起来像是另一个不匹配,实际上那里的 1DC71B824BAA3C7EC6744A0941CFADDAA893E8C1 似乎与此值无关。

SHA256.pdf

你能看看这个吗?这个是用itext的库制作的,没有改动代码。

在这个文件中确实没有哈希不匹配了,只是签名值被截断了,这里

3031300D0609608648016503040201050004204C8440B547E6A0EFD1489B8F5B5DFDA2DFA45DC1

对应

SEQUENCE (2 elem)
  SEQUENCE (2 elem)
    OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST Algorithm)
    NULL
  OCTET STRING (32 byte) 4C8440B547E6A0EFD1489B8F5B5DFDA2DFA45DC1XXXXXXXXXXXXXXXXXXXXXXXX

完整的 OCTET STRING 应该是

4C8440B547E6A0EFD1489B8F5B5DFDA2DFA45DC19048B5E53D468FE6A8E4E973

显然,您的签名设备链、example.dll PKCS#11 驱动程序和来自 JRE 的 SunPKCS11 安全提供程序确实不支持 SHA256withRSA。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?