Android和Java中的RSA加密

我想用RSA加密加密字符串。 我的公钥/私钥生成并存储在DB中。 在android中,我使用这段代码:

public static String encryptRSAToString(String text, String strPublicKey) { byte[] cipherText = null; String strEncryInfoData=""; try { KeyFactory keyFac = KeyFactory.getInstance("RSA"); KeySpec keySpec = new X509EncodedKeySpec(Base64.decode(strPublicKey.trim().getBytes(), Base64.DEFAULT)); Key publicKey = keyFac.generatePublic(keySpec); // get an RSA cipher object and print the provider final Cipher cipher = Cipher.getInstance("RSA"); // encrypt the plain text using the public key cipher.init(Cipher.ENCRYPT_MODE, publicKey); cipherText = cipher.doFinal(text.getBytes()); strEncryInfoData = new String(Base64.encode(cipherText,Base64.DEFAULT)); } catch (Exception e) { e.printStackTrace(); } return strEncryInfoData.replaceAll("(\\r|\\n)", ""); } 

出于调试目的,我尝试使用相同的参数调用此方法2次,并且字符串结果类似(如预期的那样)。

我想在java中生成相同的加密String。 但是,“android.util.Base64”类在Java中不可用,所以我尝试使用默认的Base64类:

 public static String encryptRSAToString(String text, String strPublicKey) { byte[] cipherText = null; String strEncryInfoData=""; try { KeyFactory keyFac = KeyFactory.getInstance("RSA"); KeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(strPublicKey.trim().getBytes())); Key publicKey = keyFac.generatePublic(keySpec); // get an RSA cipher object and print the provider final Cipher cipher = Cipher.getInstance("RSA"); // encrypt the plain text using the public key cipher.init(Cipher.ENCRYPT_MODE, publicKey); cipherText = cipher.doFinal(text.getBytes()); strEncryInfoData = new String(Base64.encodeBase64(cipherText)); } catch (Exception e) { e.printStackTrace(); } return strEncryInfoData.replaceAll("(\\r|\\n)", ""); } 

但是Android中生成的String和java中生成的String是不同的。

在Android端生成:

 Ky2T4j1JdI081ZESVJgxZXEf/xmtpehfv/EwpVvKQxUu1JI8lwXP2Rc66jHZRc0P846ZYuF3C9YEmWoKbXGXk2MBuT5KVxa2yoTbwZlMmhVOX3X3Efq0VyaO5zZ4qavIq036cA3MzvQbUAb678UdbALW/CjRCsOdeH+hSCzNQ+0= 

在JAVA方面生成:

 XhSLxfiJUUdZW5kWh0MEPSrqoROBBhNC/krfTx+sdnXML3WegYbMzSvNnPgB8+8Z9joEUBMmoeBI1OhTF6qPFL1EEixkFYAkGaryEFxvN/aFI75kEUj71OHNzAHAuvS+h+9Nssx9psSZ5gc2OoLQH0QtbGDyXB4p+qUGFCde4tY= 

有人知道如何解决我的问题吗?

谢谢

看起来你依赖默认设置已经被撤消了。 如果您希望实现互操作性,请不要这样做。

以下是我发现的错误依赖于代码中的默认值的两个示例。

final Cipher cipher = Cipher.getInstance("RSA");

转换字符串应该采用“algorithm / mode / padding”的forms,但是你已经停止了模式填充规范。 因此,您获得了默认值。 Android和Oracle Java的默认值明显不同。 您应该始终完全指定转换 ,例如:
final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");

另一个不好的例子是cipherText = cipher.doFinal(text.getBytes());

text.getBytes()您依赖于no-args getBytes()方法,该方法使用平台的默认字符集。 但是这个默认字符集在不同平台上有所不同,因此这不可移植。 在几乎所有情况下,我遇到过你应该指定UTF-8字符集。 因此,正确的线将是
cipherText = cipher.doFinal(text.getBytes("UTF-8"));

并且用于在decrypt方法中重新创建原始字符串的正确字符串构造函数是String(byte [] data, String charsetName)

我还没评论,所以我回答。

可能正在使用不同的默认配置。 看看这个问题: Apache的Base64.encodeBase64和Android的Base64.encode与Base64.Default标志有什么区别吗?

存在不同密码和散列实现的偏差。 我建议使用OpenSSL作为常见实现。