【问题标题】:Decryption result using RSA differs in plain Java and Android使用 RSA 的解密结果在普通 Java 和 Android 中有所不同
【发布时间】:2012-12-22 05:28:35
【问题描述】:

我加密/解密如下消息: 加密字符串 -> base64 编码字节 -> 序列化字符串 -> 反序列化字符串 -> 解码 b64 -> 解密字节。

加密如下:

PublicKey pubKey = readPublicKey();
Cipher cipher;
cipher = Cipher.getInstance(CRYPTO_ALG);
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData;
cipherData = cipher.doFinal(message.getBytes());
return cipherData;

解密是这样完成的:

PrivateKey pk = readPrivateKey();
Cipher cipher = Cipher.getInstance(CRYPTO_ALG);
cipher.init(Cipher.DECRYPT_MODE, pk);

return new String(cipher.doFinal(data));

键是这样读取的:

ObjectInputStream oin =
   new ObjectInputStream(new BufferedInputStream(is));
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();

RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privKey = fact.generatePrivate(keySpec);

return privKey;

我在这里省略了 b64 的东西,但我已经验证问题不会影响该代码。

现在发生的事情是我实际上得到了正确的答案,但它前面带有二进制乱码。如果我加密“TESTDATA”,我将得到 TESTDATA。该代码在纯 Java 中运行良好,但在 Android 中失败。有谁知道如何解决这一问题?

编辑:使用 RSA/NONE/NoPadding 加密/解密似乎没有帮助。我还在普通 JRE 中使用 org.bouncycastle。

【问题讨论】:

  • @Milos:这似乎很合理,但是当我使用“RSA/NONE/NoPadding”加密/解密时它不起作用。输出都是乱码。我错过了什么吗?生成密钥时是否需要更改某些内容?
  • @navlelo,尝试打印出生成的密钥,看看是否一切都符合这个要求。
  • @navlelo:这个网站上肯定有 200 个问题,其他问题是程序员使用默认值而不知道它们的含义。不要使用默认值。 message.getBytes() 是做什么的?它使用 platform 默认字符集。 new String(byte[]) 构造函数有什么作用?它还使用默认平台字符集。那你在做什么?您正在尝试在不同的平台上运行您的代码!始终指定字符集。您始终可以使用“UTF-8”。 Cipher.getInstance("RSA") 也是如此。为什么要关闭模式和填充?你只是自找麻烦。

标签: java android rsa pki


【解决方案1】:

根据我的经验,默认值是 Java 加密中难以发现的错误的巨大且永无止境的来源。他们可以咬任何人,但他们捕食初学者。初学者最有可能选择默认值,因为就其本质而言,他们会感到困惑并寻求简化。而且它们很难被发现,实际上几乎是看不见的,因为它们在那里。当您查看String.getBytes() 时,它看起来完全是无辜的。为什么初学者会怀疑new String(s.getBytes()) 永远等于s?最糟糕的是,测试似乎表明这是真的。只有当您将byte[]s.getBytes() 传输到具有不同平台默认字符集的另一个平台时,您才会注意到该错误。

永远不要使用String.getBytes(),始终使用String.getBytes(Charset)。永远不要使用 String(byte[]) 构造函数,始终使用 String(byte [], Charset) 构造函数。您始终可以使用 UTF-8 字符集 (Charset.forName("UTF-8"))。我专门用它。

同样,始终在Cipher.getInstance(String) 工厂方法中指定所有三个组件algorithm/mode/padding

【讨论】:

    猜你喜欢
    • 2013-09-27
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 2015-02-27
    • 2017-06-14
    • 1970-01-01
    相关资源
    最近更新 更多