java - Android 和 Java 中的 RSA 加密

标签 java android security encryption rsa

我想用 RSA 加密来加密一个字符串。我的公钥/私钥已生成并存储在数据库中。在安卓中,我使用这段代码:

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 中生成相同的加密字符串。但是,“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中生成的是不一样的。

在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”的形式,但您没有使用modepadding 规范。结果,您获得了这些的默认值。默认值在 Android 和 Oracle Java 上明显不同。你应该总是fully specify the transformation ,例如:
final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");

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

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

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

关于java - Android 和 Java 中的 RSA 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30886589/

相关文章:

Android 开发 - 用户壁纸作为应用程序背景

java - 如何根据用户登录隐藏某些功能?

email - 邮箱验证码是否需要过期?

javascript - 从 PHP SVG-image 返回并通过 <img> 标签执行内部 javascript

java - 覆盖列表和Java实践

android - 评级栏不在单行中显示全明星

java - 简单密码程序的麻烦——Java

android - 如何在导航 View 中定位菜单项?

java - 按值对Map <Key,Value>进行排序

java - 是否可以在 selenium 测试中访问 java bean?