数字签名错误 - 签名长度不正确:得到 344 但预期为 256

Digital Signature error - Signature length not correct: got 344 but was expecting 256

我正在使用带有 256 位证书的 SHA1withRSA 算法开发数字签名 java class。但我收到此错误:

Signature length not correct: got 344 but was expecting 256.

我正在使用 SunJSSE 提供程序(未实现 SHA256withRSA 算法),因为他使用 PKCS12 密钥库类型。我需要这个,因为这是一个批处理应用程序。

SAH1withRSA算法是否与256位证书不兼容?

首先,您不可能拥有 256 位 RSA 证书或密钥。 1977 年 RSA 发布时,256 位 RSA 并不安全,更不用说现在了。该异常表示它正在寻找 256 byte 签名,即 2048 位,这意味着密钥和证书也是 2048 位,这是目前(自 2015 年以来)标准和广泛使用的大小对于RSA。

其次,是的 SHA1withRSA 在技术上使用 2048 位 RSA 密钥(和证书),尽管它不太安全。 SHA1 最初被评为只有 80 位的抗碰撞强度,并且大约一年前被破坏(成本显着降低,大约 63 位)——参见 https://shattered.io——在许多情况下签名不安全,从而导致越来越多的系统、程序和用户拒绝 SHA1 签名。例如,从 8u144 开始(大约去年夏天)的所有 Oracle Java 包都默认配置 java.security jdk.certpath.disabledAlgorithms 以禁止在 TLS[= 中使用 SHA1 签名证书 33=](包括SSL,但默认情况下SSL也被破坏和禁止)。 Java 目前不禁止 SHA1 签名的其他用途,但可能会更改为。还有许多您可能想要与之通信或互操作的东西,例如浏览器、网络服务器、电子邮件系统、存储库等,要么已经禁止了 SHA1,要么可能会禁止。

但这不是必需的。您可以在一个程序中使用多个提供程序,特别是您可以使用 SunJSSE 的 KeyStore PKCS12,同时还使用 Signature SHA256withRSA(或SunRsaSign 的其他 SHA2+RSA 变体)。事实上,最简单的方法是根本不指定提供者,只让 KeyStore.getInstance()Signature.getInstance()(以及其他 JCA 接口 类)自动找到正确的提供者。

最后,您的签名可能是 base64 编码的: ceil(256/3)*4=344。查看数据,看看它是否由 base64 字符组成,如果是,是哪一组。如果它是 base64,将其解码为二进制(即 Java 中的 byte[])并使用它。在 Java8+ 中,只需使用 java.util.Base64,它支持现在常见的两种变体:'MIME' 变体和 'URL-safe'(主要是 JSON)变体。在较旧的 Java 中,您可以将 javax.xml.bind.DatatypeConverter 用于 MIME,或任意数量的具有不同功能的第三方库。