在 Android 中使用 RSA 算法解密数据

Posted

技术标签:

【中文标题】在 Android 中使用 RSA 算法解密数据【英文标题】:Decrypt data using RSA algorithm in Android 【发布时间】:2016-03-30 13:04:39 【问题描述】:

我正在尝试在我的 android 应用程序中使用 RSA 加密算法加密数据。我能够加密数据,但是每当我要解密该加密数据时,我都会遇到异常。

我已经在 google 中尝试过,也尝试过应用所有解决方案,但得到以下相同的异常。

javax.crypto.IllegalBlockSizeException: input must be under 64 bytes
    at com.android.org.conscrypt.OpenSSLCipherRSA.engineDoFinal(OpenSSLCipherRSA.java:245)
    at javax.crypto.Cipher.doFinal(Cipher.java:1340)
    at eu.agilers.util.Utility.decryptData(Utility.java:193)
    at eu.agilers.supersail.SuperSail.onCreate(SuperSail.java:46)
    at android.app.Activity.performCreate(Activity.java:6283)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2758)
    at android.app.ActivityThread.access$900(ActivityThread.java:177)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5942)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)

加密方式:

public static String encryptData(String textToEncrypt) 

    String modulus = "sAyRG6mbVY1XoPGZ9Yh+ZJvI40wxiq4LzoSbLlIdrYLelvzeQZD6Y6eG9XIALpEvnL3ZECf1Emnv17yELrcQ5w==";
    String exponent = "AQAB";

    try 

        byte[] modulusBytes = Base64.decode(modulus.getBytes("UTF-8"), Base64.DEFAULT);
        byte[] exponentBytes = Base64.decode(exponent.getBytes("UTF-8"), Base64.DEFAULT);

        BigInteger modulusInt = new BigInteger(1, modulusBytes);
        BigInteger exponentInt = new BigInteger(1, exponentBytes);

       /* RSAPrivateKeySpec rsaPrivKey = new RSAPrivateKeySpec(modulusInt, exponentInt);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PrivateKey privKey = fact.generatePrivate(rsaPrivKey);*/

        RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulusInt, exponentInt);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PublicKey pubKey = fact.generatePublic(rsaPubKey);

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);

        byte[] encryptedByteData = cipher.doFinal(textToEncrypt.getBytes());

        return Base64.encodeToString(encryptedByteData, Base64.NO_WRAP);

     catch (Exception e) 
        e.printStackTrace();
        return null;
    

解密方法:

public static String decryptData(String data) 

    try 

        String modulus = "sAyRG6mbVY1XoPGZ9Yh+ZJvI40wxiq4LzoSbLlIdrYLelvzeQZD6Y6eG9XIALpEvnL3ZECf1Emnv17yELrcQ5w==";
        String exponent = "AQAB";

        byte[] modulusBytes = Base64.decode(modulus.getBytes("UTF-8"), Base64.DEFAULT);
        byte[] exponentBytes = Base64.decode(exponent.getBytes("UTF-8"), Base64.DEFAULT);

        BigInteger modulusInt = new BigInteger(1, modulusBytes);
        BigInteger exponentInt = new BigInteger(1, exponentBytes);

       /* RSAPrivateKeySpec rsaPrivKey = new RSAPrivateKeySpec(modulusInt, exponentInt);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PrivateKey privKey = fact.generatePrivate(rsaPrivKey);*/

        RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulusInt, exponentInt);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PublicKey pubKey = fact.generatePublic(rsaPubKey);

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        cipher.init(Cipher.DECRYPT_MODE, pubKey);

        byte[] base64String = Base64.decode(data, Base64.DEFAULT);

        byte[] plainBytes = new String(base64String).getBytes("UTF-8");

        plainBytes = cipher.update(plainBytes);

        byte[] values = cipher.doFinal(plainBytes);

        return new String(values, "UTF-8");

     catch (Exception e) 
        e.printStackTrace();
        return null;
    

请帮帮我。

【问题讨论】:

您的输入是否低于 64 字节? 我使用相同的方法 encryptData() 加密字符串,然后解密我从 encryptData() 方法获得的相同字符串。比如,String encr = encryptData("testData"); String decr = decryptData(encr); 你甚至懒得回答我的问题... 具体的错误是因为byte[] plainBytes = new String(base64String).getBytes("UTF-8");这行,反正也没有意义。即使您解决了这个问题,您仍在尝试使用公钥解密(请参阅下面的@Jim Flood 答案),这同样没有意义。 【参考方案1】:

首先,尝试使用私钥而不是公钥解密。绝对不可能使用 RSA 公钥来解密由 RSA 公钥加密的数据。

RSA 密钥成对出现:公共和私人。您需要私钥来解密。如果公钥真的可以解密公钥加密的密文,那么所有的公钥密码都会被破解。

【讨论】:

以上是关于在 Android 中使用 RSA 算法解密数据的主要内容,如果未能解决你的问题,请参考以下文章

使用polarssl进行RSA加密解密

Python使用rsa模块实现非对称加密与解密

js中常见的数据加密与解密的方法

RSA算法加密解密,数据传输,前台与后台数据交互

android rsa加解密私钥和公钥怎么用

利用openssl进行RSA加密解密