java - 具有 RSA 签名的 SHA256 在各种 Android 设备上返回不同的输出

标签 java android rsa digital-signature

我正在开发一个 Android 应用程序,我需要使用 java Signature class用于数据认证。

在每台 Android 设备上,我都可以签署数据并验证其签名。但是,给定要签名的确定数据 block 、确定的模数、确定的私有(private)指数和确定的公共(public)指数,我的签名输出会有所不同,具体取决于设备。我确实尝试了一堆设备,并且我获得了适用于 Android 3.2 和 3.2.1 的相同签名,但获得了适用于 Android 2.2.x 设备的不同签名。

我根据之前在 java 项目中使用带有 RSA 的 KeyFactory 生成的常量字段计算这些签名。 key 大小为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);
}

如果我没记错的话,使用 SHA256 和 RSA 的签名是确定性的。那我该如何解释这种行为呢?另一个有趣的问题,我怎样才能使它跨设备工作,即签名是相同的,不管我使用哪种设备?

提前谢谢你,弗兰克!

最佳答案

是的,SHA256withRSA 是完全确定的。

理论上,您可能会受到在其中一个 Android 版本上发现的旧修改 BouncyCaSTLe 库版本中的错误 ( see an example ) 的影响。如果您改为使用 SHA512withRSA,这样的错误可能会被消除,好吧,至少引用的那个是。

但是,在您开始深入研究哈希算法之前,请先了解一下。

也许您已经通过调用 String.getBytes 获得了您的字节数组。此调用取决于默认平台编码,即 different Android 2.2 和 Android 2.3 之间。这意味着虽然您的字符串在两种情况下都相同,但字节数组可能不同。

要控制编码并使您的代码平台独立,请将编码指定为参数:

plainText.getBytes("UTF-8")

如果做不到这一点,还有一些策略可以实现独立于平台的实现。

  • 等到 2.2 可能有问题的库消失
  • 随您的软件分发已知良好的库 (jar)。如果那是 BouncyCaSTLe,您将无法确保加载您的类而不是 Android 的类。该解决方案称为 SpongyCaSTLe。
  • 玩对齐/填充。尝试通过添加您自己的固定填充使以字节为单位的消息长度与 0,55、56 或 63 模 64 一致,并希望这些选项之一将开始提供可移植签名。选择这些值是为了与填充到 512 位 block 的可疑算法的最外层交互。

关于java - 具有 RSA 签名的 SHA256 在各种 Android 设备上返回不同的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11251088/

相关文章:

java - 使用模数和指数在 C# 中进行 RSA/ECB/PKCS1Padding 解密

java - Android 以编程方式添加的 ListPreference 缺少标题

Java:不兼容的类型(int/boolean)

android - 更改语言的按钮 Flutter

PHP 许可证生成器保护与 paypal IPN 冲突?

cryptography - 在 .Net Core 上使用非对称 key

java - 如何在一行中打印一个数组的所有内容?

java - 外键未存储在子实体中(一对多)

android - 如何在 Android 中将自定义对象写入文件

android - 如何计算主页小部件的宽度