如何解决使用 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 举报,一经查实,本站将立刻删除。