Android Encrypting String using RSA Public key
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
}
Chandru
I am an elegant and enthusiastic developer who always believes the myth of working smart rather working hard.
Updated on June 17, 2022Comments
-
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
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.