我正在尝试使用iText对PDF文档进行数字签名。由于我将最终使用JCE提供程序的硬件加密器,我也试图在我的单元测试中测试摆脱BountyCastle,而是暂时使用默认的SUN实现(直到硬件加密器到达)。
但是,当我运行程序时出现以下异常:
线程“main”中的异常java.security.NoSuchAlgorithmException:没有这样的算法:SHA256 for provider SUN at sun.security.jca.GetInstance.getService(GetInstance.java:87) 在sun.security.jca.GetInstance.getInstance(GetInstance.java:206) at java.security.Security.getImpl(Security.java:698) 在java.security.MessageDigest.getInstance(MessageDigest.java:215) at com.itextpdf.text.pdf.security.DigestAlgorithms.getMessageDigest(DigestAlgorithms.java:159) at com.itextpdf.text.pdf.security.ProviderDigest.getMessageDigest(ProviderDigest.java:61) at com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:130) at SignDoc.signPdf(SignDoc.java:142) 在SignDoc.main(SignDoc.java:182)
最后几行代码如下:
//ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
//ExternalDigest digest = new BouncyCastleDigest();
//ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "SUN");
ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "SunRsaSign");
ExternalDigest digest = new ProviderDigest("SUN");
MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
如您所见,我只是复制样本并将提供者名称和调用'new BouncyCastleDigest()'更改为'new ProviderDigest(“SUN”)'
偷看iText(5.5.1-SNAPSHOT)的源代码,我发现以下代码片段可疑:
MakeSignature.java第142 - 145行
调用hashAlgorithm = externalSignature.getHashAlgorithm(),然后在
中使用DigestAlgorithms.digest(data,externalDigest.getMessageDigest( hashAlgorithm ));
PrivateKeySignature.java第76行
由于我正在使用PrivateKeySignature,因此我查看了PrivateKeySignature.java并发现它返回其私有类成员hashAlgorithm,这是它在构造期间获取值的方式(第76行):
this。 hashAlgorithm = DigestAlgorithms.getDigest(DigestAlgorithms.getAllowedDigests(的HashAlgorithm ));
DigestAlgorithms.java方法getAllowedDigests()和getDigest()
反过来,如果在allowedDigests哈希映射(在我的例子中为2.16.840.1.101.3.4.2.1)中找到算法名称,则getAllowedDigests()返回算法的OID,否则返回null。
getDigest使用digestNames哈希映射从OID获取摘要名称。
但是,与OID对应的digestNames哈希映射中的名称是SHA256,而不是SHA-256。
因此,最终的摘要名称为“SHA256”而不是“SHA-256”,而“SHA256”导致SUN提供程序中出现NoSuchAlgorithm异常。
(我尝试直接使用SUN提供程序获取消息摘要实例。它成功用于SHA-256,但抛出了我在这里报告的SHA256相同的异常。
使用除BC以外的JCE提供程序时,这是iText的问题吗?
欣赏是否有人可以解释我的问题。
答案 0 :(得分:0)
作为临时解决方法,我将以下内容添加到PrivateKeySignature.java:
//临时修复 - 删除hashAlgorithm名称中的连字符 // String signMode = hashAlgorithm +“with”+ encryptionAlgorithm; String signMode = hashAlgorithm.replaceAll(“ - ”,“”)+“with”+ encryptionAlgorithm; //结束临时修复
至少目前它对我有用。我相信,在研究长期解决方案之前,必须研究不同背景下不同算法的标准名称。