java 带有 RSA 签名的 SHA256 在各种 Android 设备上返回不同的输出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11251088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SHA256 with RSA signature returns different outputs on various Android devices
提问by franckysnow
I am developping an Android app, and I need to use java Signature
classfor data authentication.
我正在开发一个 Android 应用程序,我需要使用javaSignature
类进行数据验证。
On each Android device, I can sign data and verify its signature. However, given a definite chunk of data to sign, a definite modulus, a definite private exponent and a definite public exponent, the outputs of my signatures are different, depending on devices. I did try with bunch of devices, and I obtain the same signatures for Android 3.2 and 3.2.1, but a differents for an Android 2.2.x device.
在每台 Android 设备上,我都可以对数据进行签名并验证其签名。但是,给定要签名的明确数据块、明确的模数、明确的私有指数和明确的公共指数,我的签名的输出是不同的,具体取决于设备。我确实尝试了很多设备,并且为 Android 3.2 和 3.2.1 获得了相同的签名,但为 Android 2.2.x 设备获得了不同的签名。
I compute these signature from constant fields that I generated previously using a KeyFactory
with RSA in a java project. The keysize is 2048bit.
我从之前KeyFactory
在 java 项目中使用 RSA生成的常量字段计算这些签名。密钥大小为 2048 位。
Here is a quote of the code that I use to invoque Signature and Verification.
这是我用来调用签名和验证的代码的引用。
public byte[] signData(byte[] data, PrivateKey privateKey) throws ... {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public boolean verifyData(byte[] data, byte[] sigBytes, PublicKey publicKey) throws ... {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(sigBytes);
}
If I am not mistaking, the signature using SHA256 with RSA is deterministic. Then how can I explain such a behaviour? Another interesting question, how could I make that work cross-devices, i.e. the signatures would be same, no mather which device I use?
如果我没记错的话,使用 SHA256 和 RSA 的签名是确定性的。那么我该如何解释这种行为呢?另一个有趣的问题,我怎样才能使跨设备工作,即签名是相同的,不知道我使用的是哪种设备?
Thank you in advance, Franck!
提前谢谢你,弗兰克!
回答by Jirka Hanika
Yes, SHA256withRSA
is completely deterministic.
是的,SHA256withRSA
是完全确定的。
In theory you could be affected by a bug (see an example) in an old modified BouncyCastle library version found on one of the Android versions. Such a bug might be eliminated if you used SHA512withRSA
instead, well, at least the referenced one would be.
从理论上讲,您可能会受到在其中一个 Android 版本上发现的旧修改 BouncyCastle 库版本中的错误(参见示例)的影响。如果您SHA512withRSA
改为使用,则可能会消除这样的错误,好吧,至少引用的错误会是。
However, before you start digging into the hash algorithm, check close to home.
但是,在开始深入研究哈希算法之前,请在家附近检查一下。
Maybe you have obtained your byte array through a call to String.getBytes
. This call depends on the default platform encoding which is differentbetween Android 2.2 and Android 2.3. This implies that while your strings are the same in both cases, the byte arrays might not be.
也许您已经通过调用String.getBytes
. 此调用取决于Android 2.2 和 Android 2.3 之间不同的默认平台编码。这意味着虽然您的字符串在两种情况下都相同,但字节数组可能不同。
To get encoding under control, and make your code platform independent, specify encoding as a parameter:
要控制编码并使您的代码平台独立,请将编码指定为参数:
plainText.getBytes("UTF-8")
Failing this, there are a few more tactics to get a platform independent implementation.
如果做不到这一点,还有一些策略可以实现独立于平台的实现。
- wait until 2.2 with the presumably buggy library dies out
- distribute a known good library (jar) with your software. If that would be BouncyCastle, you will have problems making sure that your and not Android's classes are loaded. The solution is called SpongyCastle.
- play with alignment/padding. Try to make the message length in bytes to be congruent with 0,55, 56 or 63 modulo 64 by adding your own fixed padding and hope that one of these options will start giving portable signatures. These values are chosen to interact with the outermost part of the suspect algorithm which is padding to 512 bit blocks.
- 等到 2.2 可能有问题的库消失
- 随您的软件分发一个已知良好的库 (jar)。如果那是 BouncyCastle,您将在确保加载您的类而不是 Android 的类时遇到问题。该解决方案称为 SpongyCastle。
- 玩对齐/填充。通过添加您自己的固定填充,尝试使以字节为单位的消息长度与 0,55、56 或 63 模 64 一致,并希望这些选项之一将开始提供可移植的签名。选择这些值以与填充到 512 位块的可疑算法的最外层部分交互。