调用PGPOnePassSignature.verify时,签名长度不正确

qqi*_*ihq 5 java cryptography bouncycastle gnupg

我们正在使用一个名为license3j许可证管理的Java库.该库使用非对称加密,并依赖于Bouncycastle.我们使用简单的gpg命令创建许可证文件,并使用我们的公钥验证软件中的许可证.到目前为止一切正常.但是:在1,000个生成的许可证中,有一小部分无法正确验证,尽管它们实际上是有效的(大约5/1000).

在这种情况下会发生什么:当要验证许可证时com.verhas.licensor.License.setLicenseEncoded(InputStream),会org.bouncycastle.openpgp.PGPOnePassSignature.verify(PGPSignature)抛出以下异常:

org.bouncycastle.openpgp.PGPRuntimeOperationException: unable to verify signature: Signature length not correct: got 511 but was expecting 512

听起来相当模糊,只有基本的密码学知识.花几个小时谷歌搜索,给了我线索,有一些关于"领先的零".因此,在给定的示例中,显然一个前导零被剥离到某处(哪里?),并且要比较的签名数据的长度不匹配.说得通.

现在,我不知道问题可能在哪里.是在创建许可证文件期间吗?基本上,我们只是做以下事情:

gpg --armor --local-user=name.of.software --sign
Run Code Online (Sandbox Code Playgroud)

哪个会给我们许可文件.

或者验证期间是否发生错误?我是否必须修改任何Bouncycastle配置才能正确解决前导零问题?他们的FAQ提供了一些提示,但是License3j 源代码显然从未使用过任何Cipher实例,所以我完全迷失了如何将它集成到给定的API中.

我知道这是一个非常特殊的问题,一个库显然不是很有名.因此,我感谢任何一点反馈或输入.

Mag*_*nus 6

看起来它是bouncycastle中的一个bug,只在1.6之后的Java版本中遇到过,bouncycastle总是创建错误的数据,但Java在验证过程中接受的数据自1.7以来变得更加严格.

Bouncycastle在将签名序列化到文件时未能将签名填充到正确的长度,如果整数具有足够的前导零,则它的字节表示将更小.
Java版本1.7及更高版本期望RSA签名字节与密钥长度相同.

Bouncycastle将RSA签名字节数组(从Java的RSA JCE提供程序返回)转换为整数,并丢弃有关其长度的信息.显示的
第263行,PGPSignatureGenerator其中RSA签名字节从JCE返回并转换为整数.

这个整数最终被写入输出流,使用它只使用MPInteger#encode底层biginteger的bitlength来确定要写入多少数据.

这个答案更详细地描述了为什么你会在每200个案例中看到这个aproximatley,以及Java的版本如何发挥作用.

  • 不幸的是,在bouncycastle修复它看起来并不重要,你可以尝试在他们的问题跟踪器中提出一个错误,但我不确定你会有多少成功.一个hacky工作可能是尝试验证每个许可证,并在失败时重新生成它. (2认同)
  • 我不相信有任何其他免费的Java库可以执行PGP.Java标准库正在处理实际的RSA签名验证,这就是1.7中行为发生变化的原因.如果你想修改license3j,你可以通过包装验证程序提供程序来破解一些填充,但我不确定它是否会起作用.https://gist.github.com/magJ/27b2909ce749da6dd0ea19a3eb334a53 (2认同)