[英]Decryption result using RSA differs in plain Java and Android
我对消息进行加密/解密,如下所示:加密字符串-> 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。
以我的经验,默认值是Java加密中难以发现的错误的巨大且永无止境的来源。 他们可以咬任何人,但它们会捕食初学者。 初学者最有可能选择默认值,因为就其本质而言,它们很困惑并且正在寻求简化。 而且很难发现它们,甚至几乎看不见,因为它们不存在。 当您查看String.getBytes()
它看起来完全是无辜的。 为什么初学者会怀疑new String(s.getBytes())
永远不等于s
? 最糟糕的是,测试似乎表明它是真实的。 仅当您将s.getBytes()
byte[]
从s.getBytes()
传输到具有不同平台默认字符集的另一个平台时,您才注意到该错误。
永远不要使用String.getBytes()
,总要使用String.getBytes(Charset)
。 从不使用的String(byte[])
构造,总是使用String(byte [], Charset)
构造。 您始终可以使用UTF-8字符集( Charset.forName("UTF-8")
)。 我专门使用它。
同样,请始终在Cipher.getInstance(String)
工厂方法中指定所有三个组件算法/模式/填充 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.