【问题标题】:MakeSignature.signDetached throws No Such Algorithm exception (SUN provider & SHA-256)MakeSignature.signDetached 抛出无此类算法异常(SUN 提供者和 SHA-256)
【发布时间】:2014-03-24 11:11:31
【问题描述】:

我正在尝试使用 iText 对 PDF 文档进行数字签名。由于我最终将在 JCE 提供程序中使用硬件加密器,因此我也在尝试在我的单元测试中测试摆脱 BountyCastle 并暂时使用默认的 SUN 实现(直到硬件加密器到达)。

但是,当我运行我的程序时出现以下异常:

线程“主”java.security.NoSuchAlgorithmException 中的异常:没有这样的算法:提供者 SUN 的 SHA256 在 sun.security.jca.GetInstance.getService(GetInstance.java:87) 在 sun.security.jca.GetInstance.getInstance(GetInstance.java:206) 在 java.security.Security.getImpl(Security.java:698) 在 java.security.MessageDigest.getInstance(MessageDigest.java:215) 在 com.itextpdf.text.pdf.security.DigestAlgorithms.getMessageDigest(DigestAlgorithms.java:159) 在 com.itextpdf.text.pdf.security.ProviderDigest.getMessageDigest(ProviderDigest.java:61) 在 com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:130) 在 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)的源代码,我发现以下代码片段很可疑:

  1. MakeSignature.java 第 142 - 145 行

    hashAlgorithm = externalSignature.getHashAlgorithm() 被调用然后用在

    DigestAlgorithms.digest(数据, externalDigest.getMessageDigest(hashAlgorithm));

  2. PrivateKeySignature.java 第 76 行

    由于我使用的是 PrivateKeySignature,所以我查看了 PrivateKeySignature.java,发现它返回了它的私有类成员 hashAlgorithm,这就是它在构造过程中获取值的方式(第 76 行):

    this.hashAlgorithm = DigestAlgorithms.getDigest(DigestAlgorithms.getAllowedDigests(hashAlgorithm));

  3. DigestAlgorithms.java 方法 getAllowedDigests() 和 getDigest()

    反过来,如果在 allowedDigests 哈希映射(在我的例子中为 2.16.840.1.101.3.4.2.1)中找到算法名称,则 getAllowedDigests() 返回算法的 OID,否则返回 null。

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

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

因此,得到的最终摘要名称是“SHA256”而不是“SHA-256”,并且“SHA256”导致 SUN 提供程序中出现 NoSuchAlgorithm 异常。

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

在使用 BC 以外的 JCE 提供程序时,iText 是否存在问题?

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

【问题讨论】:

  • 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。但是,当谈到 Signature.getInstance() 时,我立即被“没有这样的算法”异常击中(这一次是 SHA-256withRSA,我相信它期待 SHA256withRSA)。似乎存在一个问题,即摘要的相同算法名称(例如 SHA-256 )可以用作签名算法的前缀,因为算法名称在提供者之间不一致(例如 SHA256 与 SHA-256) .

标签: itext sha256


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 2021-08-05
    • 2014-11-05
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多