Android和Java中的RSA加密 [英] RSA encryption in Android and Java

查看:138
本文介绍了Android和Java中的RSA加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用RSA加密来加密一个字符串。我的公钥/私钥生成并存储在数据库中。在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);

//获取RSA密码对象并打印提供程序
final Cipher cipher = Cipher.getInstance(RSA);
//使用公钥加密纯文本
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
cipherText = cipher.doFinal(text.getBytes());
strEncryInfoData = new String(Base64.encode(cipherText,Base64.DEFAULT));

} catch(Exception e){
e.printStackTrace();
}
返回strEncryInfoData.replaceAll((\\\\\\\),);
}

为了调试目的,我尝试使用相同参数调用2次此方法和String结果是相似的(如预期的)。



我想在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);

//获取RSA密码对象并打印提供程序
final Cipher cipher = Cipher.getInstance(RSA);
//使用公钥加密纯文本
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
cipherText = cipher.doFinal(text.getBytes());
strEncryInfoData = new String(Base64.encodeBase64(cipherText));

} catch(Exception e){
e.printStackTrace();
}
返回strEncryInfoData.replaceAll((\\\\\\\),);
}

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

生成的Android侧:

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

在JAVA方面生成:

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

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



谢谢

解决方案

看起来你依靠默认值被撤销了。



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



final Cipher cipher = Cipher.getInstance(RSA);



转换字符串应该是算法/模式/填充的形式,但是您已经停止了模式填充规范。因此,您获得了默认值。 Android和Oracle Java的默认值显然不同。您应始终完全指定转换例如:

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));



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


I would like to encrypt a String with RSA encryption. My public/private keys were generated and stored in DB. In android, I use this code:

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)", "");
}

For debug purpose, I try to call 2 times this method with the same parameters and String result were similar (as expected).

I want to generate the same encrypted String in java. However, "android.util.Base64" class is not available in Java, so I've tried with the default Base64 class:

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)", "");
    }

But the String generated in Android and the one in java are different.

Generated in Android side :

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

Generated in JAVA side :

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

Does someone know how to solve my issue ?

thank you

解决方案

It looks like you've been undone by relying on defaults. Never do that if you hope for interoperability.

Here are the two examples of mistakenly relying on defaults in your code that I've found.

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

The tranformation string is supposed to be of the form "algorithm/mode/padding" but you've left off the mode and padding specifications. As a result you got default values for those. The defaults are evidently different on Android and Oracle Java. You should always fully specify the transformation, for example:
final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");

Another bad example is cipherText = cipher.doFinal(text.getBytes());

In text.getBytes() you are relying on the no-args getBytes() method which uses the default charset for the platform. But this default charset differs on different platforms, and thus this is not portable. In almost all cases I've run across you should specify the UTF-8 charset. So the correct line would thus be
cipherText = cipher.doFinal(text.getBytes("UTF-8"));

and the correct string constructor to use to recreate the original string in the decrypt method is the String(byte [] data, String charsetName).

这篇关于Android和Java中的RSA加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆