我正在开发Android应用,我需要使用java Signature
class进行数据身份验证。
在每台Android设备上,我都可以对数据进行签名并验证其签名。但是,给定一定数量的数据进行签名,一个明确的模数,一个明确的私有指数和一个明确的公共指数,我的签名输出会有所不同,具体取决于设备。我尝试使用大量设备,我获得了Android 3.2和3.2.1的相同签名,但是对于Android 2.2.x设备却是不同的。
我从先前在java项目中使用带有RSA的KeyFactory
生成的常量字段计算这些签名。密钥大小为2048位。
以下是我用于调用签名和验证的代码的引用。
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);
}
如果我没有误会,使用带有RSA的SHA256的签名是确定性的。那我怎么解释这样的行为呢?另一个有趣的问题是,我怎样才能使这项工作跨设备,即签名是相同的,不管我使用哪种设备?
提前谢谢你,弗兰克!
答案 0 :(得分:11)
是的,SHA256withRSA
完全是确定性的。
理论上,您可能会受到其中一个Android版本上发现的旧修改过的BouncyCastle库版本中的错误(see an example)的影响。如果您使用SHA512withRSA
代替,那么这样的错误可能会被消除,好吧,至少会引用一个。
但是,在开始深入挖掘哈希算法之前,请先查看回家。
也许您通过调用String.getBytes
获得了字节数组。此调用取决于Android 2.2和Android 2.3之间的默认平台编码different。这意味着虽然在两种情况下字符串都相同,但字节数组可能不是。
要控制编码并使代码平台独立,请将编码指定为参数:
plainText.getBytes("UTF-8")
如果做不到这一点,还有一些策略可以实现独立于平台的实施。