Itext MakeSignature.signDetached不会引发此类算法异常(SUN provider和SHA-256)

Itext MakeSignature.signDetached不会引发此类算法异常(SUN provider和SHA-256),itext,sha256,Itext,Sha256,我正在尝试用iText对PDF文档进行数字签名。由于我最终将与JCE provider一起使用硬件加密器,因此我还尝试在单元测试中测试如何摆脱BountyCastle,并暂时使用默认的SUN实现,直到硬件加密器到达 但是,我在运行程序时遇到以下异常: 线程主java.security.NoSuchAlgorithmException:无此类算法:提供程序SUN的SHA256 位于sun.security.jca.GetInstance.getServiceGetInstance.java:87

我正在尝试用iText对PDF文档进行数字签名。由于我最终将与JCE provider一起使用硬件加密器,因此我还尝试在单元测试中测试如何摆脱BountyCastle,并暂时使用默认的SUN实现,直到硬件加密器到达

但是,我在运行程序时遇到以下异常:

线程主java.security.NoSuchAlgorithmException:无此类算法:提供程序SUN的SHA256 位于sun.security.jca.GetInstance.getServiceGetInstance.java:87 位于sun.security.jca.GetInstance.getInstanceGetInstance.java:206 位于java.security.security.getImplSecurity.java:698 位于java.security.MessageDigest.getInstanceMessageDigest.java:215 在com.itextpdf.text.pdf.security.DigestAlgorithms.GetMessageDigestAlgorithms.java:159 位于com.itextpdf.text.pdf.security.ProviderDigest.getMessageDigestProviderDigest.java:61 com.itextpdf.text.pdf.security.MakeSignature.signDetachedMakeSignature.java:130 在SignDoc.signPdfSignDoc.java:142 在SignDoc.mainSignDoc.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 ProviderDigestSUN”

查看iText 5.5.1-SNAPSHOT的源代码,我发现以下代码片段可疑:

MakeSignature.java第142-145行

hashAlgorithm=externalSignature.getHashAlgorithm被调用,然后在中使用

DigestAlgorithms.digestdata,externalDigest.getMessageDigesthashAlgorithm

PrivateKeySignature.java第76行

因为我使用的是PrivateKeySignature,所以我查看了PrivateKeySignature.java,发现它返回其私有类成员hashAlgorithm,这就是它在构造第76行期间获取值的方式:

this.hashAlgorithm= DigestAlgorithms.GetDigestAlgorithms.GetAllowedIgestShashalGorithm

DigestAlgorithms.java方法GetAllowedIgests和getDigest

反过来,如果在AllowedIgests哈希映射2.16.840.1.101.3.4.2.1中找到算法名称,则GetAllowedIgests返回算法的OID,否则返回null

getDigest使用digestNames哈希映射从OID获取摘要名称

但是,与OID对应的digestNames哈希映射中的名称是SHA256,而不是SHA-256

结果,得到的最终摘要名称是SHA256,而不是SHA-256,SHA256导致SUN provider中出现NoSuch算法异常

我尝试直接使用SUN提供程序获取消息摘要实例。它在SHA-256上成功了,但抛出了我在这里为SHA256报告的相同异常

当使用JCE提供程序而不是BC时,这是iText的问题吗


如果有人能解释一下我的问题,我将不胜感激。

作为临时解决办法,我在PrivateKeySignature.java中添加了以下内容:

//临时修复-删除hashAlgorithm名称中的连字符 //String signMode=hashAlgorithm+with+encryptionAlgorithm; 字符串signMode=hashAlgorithm.replaceAll-,+with+encryptionAlgorithm; //结束临时修复


至少现在对我有效。我认为,在设计出长期解决方案之前,必须研究不同上下文中不同算法的标准名称如何变化。

JCE确实没有将SHA256定义为SHA-256的别名。您能否修改iText的digestNames哈希映射并将2.16.840.1.101.3.4.2.1->SHA256条目替换为2.16.840.1.101.3.4.2.1->SHA-256?谢谢您的建议。我想这会解决我的问题,但我不确定这是否是正确的方法。无论如何,我会先试试。如果我按照建议修改映射,我可以成功地通过MessageDigest.getInstance。然而,当涉及到签名时,我立刻被“没有这样的算法例外”击中。getInstance这一次是SHA-256withRSA,而我相信它期待的是SHA256withRSA。假设相同的算法名称(如SHA-256 for digest)可以用作签名算法的前缀,似乎存在问题,因为算法名称在不同的提供商(如SHA256 vs SHA-256)之间不一致。