带有SHA1签名验证的弹性城堡DSA



我的项目正在使用来自某些第三方软件的一些数据集的签名验证。签名算法为SHA1withDSA。当我使用标准的SUN加密提供程序时,它附带SDK,一切都很好。最近我切换到Bouncy Castle 1.50,之后的一些数据集,以前(也就是说,与SUN提供者)站立验证,它开始失败,而其余的仍然被验证为OK。

我研究了这两个提供程序的源代码,结果发现SDK的默认提供程序对不正确形成的签名有某种保护(同时能够恢复),而Bouncy Castle提供程序没有。看看OpenJDK用于Java 7(第336-344行)或OpenJDK对于Java 8(第265-273行):在某些情况下,他们做了一些签名修复。然而org.bouncycastle.jcajce.provider.asymmetric.dsa.DSASigner#engineVerify没有这样做,而且,在org.bouncycastle.crypto.signers.DSASigner#verifySignature中明确地声明数字必须是正的,否则验证直接失败。

是BC中的一个bug,还是我错过了什么?为了克服对此,我将org.bouncycastle.crypto.signers.DSASigner和在那里添加了前面提到的签名修复,然后插入了这个作为另一个签名算法(通过子类化org.bouncycastle.jcajce.provider.asymmetric.dsa.DSASigner)。但也许还有另一种我忽略了的方式,而这个"问题"是众所周知的?请建议。

如果ASN.1整数的错误BER/DER编码(存储为带符号的大端,右对齐的八位字节)确实是罪魁祸首,那么Bouncy确实不是有bug。如果设置了编码的第一个位,则应为正值留下00值的字节,否则它将表示负值。

Sun提供商允许验证这些签名是错误的,而另一方当然会生成无效的签名。请注意,在Sun代码中不需要"修复"就可以验证签名:只需在将编码提供给验证函数之前调整编码即可。

唯一不可能的情况是,DSA验证作为通用签名验证方法从另一个库调用,而不是从可以在调用之前调整数据的应用程序调用。

另一方面,我认为你已经创造了一个优雅的修复。唯一的问题是,如果从符合JCA的框架验证提供者的签名,它可能无法运行。另一个可能的修复是在将输入Signature类进行验证之前重新编码

请注意,我不认为这可能是一个安全问题;签名由R和S的值组成,它们如何编码并不重要,只要您最终收到正确的值即可。

最新更新