使用RSA公钥的Android加密字符串

时间:2017-04-21 02:29:43

标签: android encryption rsa bouncycastle spongycastle

我正在一个项目中工作,我必须使用RSA公钥加密密码。我从SO那里尝试了很多样品和解决方案,如下所示

  1. Android RSA encryption from public string

  2. RSA using SpongyCastle

  3. 但遗憾的是,没有一个解决方案适用于我的案例。如果我尝试任何解决方法,我会反复跟踪异常

    错误日志:

    04-21 07:50:57.876 18842-18842/com.takeoffandroid.passwordencryption W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
    04-21 07:50:57.986 18842-18842/com.takeoffandroid.passwordencryption W/System.err: java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0c0890ba:ASN.1 encoding routines:asn1_check_tlen:WRONG_TAG
    04-21 07:50:57.986 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at com.android.org.conscrypt.OpenSSLKey.getPublicKey(OpenSSLKey.java:250)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at com.android.org.conscrypt.OpenSSLRSAKeyFactory.engineGeneratePublic(OpenSSLRSAKeyFactory.java:47)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at java.security.KeyFactory.generatePublic(KeyFactory.java:172)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at com.takeoffandroid.passwordencryption.MainActivity.RSAEncrypt(MainActivity.java:181)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at com.takeoffandroid.passwordencryption.MainActivity.onCreate(MainActivity.java:80)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.app.Activity.performCreate(Activity.java:6532)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2383)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.app.ActivityThread.access$900(ActivityThread.java:157)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.os.Looper.loop(Looper.java:148)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5437)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err: Caused by: java.lang.RuntimeException: error:0c0890ba:ASN.1 encoding routines:asn1_check_tlen:WRONG_TAG
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at com.android.org.conscrypt.NativeCrypto.d2i_PUBKEY(Native Method)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:     at com.android.org.conscrypt.OpenSSLKey.getPublicKey(OpenSSLKey.java:248)
    04-21 07:50:57.987 18842-18842/com.takeoffandroid.passwordencryption W/System.err:  ... 16 more
    

    我的要求:

    我有一个公钥,我想用该公钥加密edittext中输入的文本。对于Eg:密码@ 123应使用公钥加密。

    公钥:

    public static String PUBLIC_KEY = "-----BEGIN RSA PUBLIC KEY-----\n" +
                "MMDDFDFK43545mmdf499Mdfdasl43ND/GGKLGKL4434safddEcBFfbTZUM517\n" +
                "VDSVFS45fwdGJGGLKGGL332XSA3=d/S/2ETegJPFQ4sjiY7/DsS2o9Gr\n" +
                "asBASF3465243FCDXSDCDxsSFC39NkDiNO2QKNXivAQVpuJeuoDeK\n" +
                "wNGmwDkIsvxBn8u55QpOwvdaRBeLqllJ6xoF6OuwnD0IB4tVDL2MbMVj1U9GtEGL\n" +
                "DJKHSJAH434jjhdds54KkhjbvGJGGGG/Vn4OYNooIWE9uuiyxm2M\n" +
                "AFSDAFXZB546FGHxcvv324FDGJIYTaa346/9xQIDAQAB\n" +
                "-----END RSA PUBLIC KEY-----";
    

    我尝试过的代码实现:

    示例I:

      public static String encryptDataRSA(final String data) throws IOException {
            final byte[] dataToEncrypt = data.getBytes();
            byte[] encryptedData = null;
    
            try {
    
                PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(RSAUtils.PUBLIC_KEY.getBytes()));
    
                final Cipher cipher = Cipher.getInstance("RSA");
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                encryptedData = cipher.doFinal(dataToEncrypt);
    
                try {
                    final String encryptedText = new String(Base64.encode(encryptedData, Base64.DEFAULT), "UTF-8");
                    return encryptedText.toString();
                }
                catch (final UnsupportedEncodingException e1) { return null; }
            } catch (Exception e) { e.printStackTrace(); }
    
            return "ERROR";
        }
    

    样本II:

        public byte[] RSAEncrypt(final String plain) throws NoSuchAlgorithmException, NoSuchPaddingException,
                InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(1024);
            KeyPair kp = kpg.genKeyPair();
            PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(RSAUtils.PUBLIC_KEY.getBytes()));
    
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] encryptedBytes = cipher.doFinal(plain.getBytes());
            System.out.println("EEncrypted?????" + org.apache.commons.codec.binary.Hex.encodeHexString(encryptedBytes));
            return encryptedBytes;
        }
    

    样本III:

     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 个答案:

答案 0 :(得分:8)

试试这个。

public static String PUBLIC_KEY = "YOUR PUBLIC KEY";

static String enccriptData(String txt)
{
  String encoded = "";
  byte[] encrypted = null;
    try {
        byte[] publicBytes = Base64.decode(PUBLIC_KEY, Base64.DEFAULT);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); //or try with "RSA"
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        encrypted = cipher.doFinal(txt.getBytes());
        encoded = Base64.encodeToString(encrypted, Base64.DEFAULT);
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    return encoded;
}

编辑:

您可以使用我的代码,但阅读James K Polk的评论,他是对的

答案 1 :(得分:0)

用于RSA加密的Kotlin代码:

首先,您需要删除"-----BEGIN PUBLIC KEY-----""-----END PUBLIC KEY-----"以及...以使文本干净。

只需使用此:

 publicKy = publicKy  .replace("\\r".toRegex(), "")
        .replace("\\n".toRegex(), "")
        .replace(System.lineSeparator().toRegex(), "")
        .replace("-----BEGIN PUBLIC KEY-----", "")
        .replace("-----END PUBLIC KEY-----", "")


    val encryptedString = enccriptData(input,publicKy)

'输入'是您要使用公钥加密的文本,
那么您需要使用此方法:

fun enccriptData(txt: String, pk: String): String? {
    var encoded = ""
    var encrypted: ByteArray? = null
    try {
        val publicBytes: ByteArray = Base64.decode(pk, Base64.DEFAULT)
        val keySpec = X509EncodedKeySpec(publicBytes)
        val keyFactory: KeyFactory = KeyFactory.getInstance("RSA")
        val pubKey: PublicKey = keyFactory.generatePublic(keySpec)
        val cipher: Cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING")
        cipher.init(Cipher.ENCRYPT_MODE, pubKey)
        encrypted = cipher.doFinal(txt.toByteArray())
        encoded = Base64.encodeToString(encrypted, Base64.DEFAULT)
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return encoded
}