我们正在使用名为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
这将为我们提供许可证文件。
或者验证期间是否发生了错误?我是否必须修改任何Bouncycastle配置才能正确解决前导零问题?他们的FAQ提供了一些提示,但License3j
source显然从未使用任何Cipher
实例,所以我完全迷失了如何将其集成到给定的API中
我知道这是一个非常特殊的问题,一个库显然不是很清楚。因此,我感谢任何一点反馈或意见。
答案 0 :(得分:6)
看起来它是bouncycastle中的一个错误,只有在1.6之后的Java版本中遇到过,bouncycastle总是创建数据错误,但Java在它接受的数据中会变得更加严格1.7的验证即可。
Bouncycastle在将签名序列化到文件时未能将签名填充到正确的长度,如果整数具有足够的前导零,则其字节表示将更小。
Java版本1.7及更高版本期望RSA签名字节与密钥长度相同。
Bouncycastle将RSA签名字节数组(从Java的RSA JCE提供程序返回)转换为整数,并丢弃有关其长度的信息。
Line 263 of the PGPSignatureGenerator
显示从JCE返回RSA签名字节并转换为整数的位置。
这个整数最终使用MPInteger#encode
写入输出流,它只使用底层大整数的位长来确定要写入多少数据。
This answer更详细地介绍了为什么每200个案例中会看到这个aproximatley,以及Java的版本如何发挥作用。