Android Encrypting String using RSA Public key

15,256

Solution 1

try this.

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

EDIT:

You can use my code but read the comment of James K Polk, he's right

Solution 2

The Kotlin Code for RSA encryption:

first of all you need to remove "-----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY-----" and ... to have a clean text.

Just use this:

 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)

' input ' is the text which you want to encrypt with your public key,
then you need to use this method:

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
}
Share:
15,256
Chandru
Author by

Chandru

I am an elegant and enthusiastic developer who always believes the myth of working smart rather working hard.

Updated on June 17, 2022

Comments

  • Chandru
    Chandru almost 2 years

    I am working in a project where I have to encrypt password using RSA public key. I tried many samples and solutions from SO like as follows

    1. Android RSA encryption from public string

    2. RSA using SpongyCastle

    But none of the solutions worked in my case unfortunately. I was getting following exceptions repeatedly if i try with any work around

    Error Log:

    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
    

    My Requirement:

    I have a public key with me and I wanted to encrypt the text entered in the edittext with that public key. For Eg: Password@123 should be encrypted using public key.

    Public Key:

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

    Code Implementations I tried:

    Sample 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";
        }
    

    Sample 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;
        }
    

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

    Any help or suggestions would be really helpful to me. Thanks in advance.