Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSA Encryption Decryption in Android

I am implementing a demo for RSA Encryption and Decryption in Android. I can Perform Encryption very well, but In Decryption I get an Exception: >>java.security.InvalidKeyException: unknown key type passed to RSA.

    KeyPairGenerator kpg;
    KeyPair kp;
    PublicKey publicKey;
    PrivateKey privateKey;
    byte [] encryptedBytes,decryptedBytes;
    Cipher cipher,cipher1;
    String encrypted,decrypted;

    public String RSAEncrypt (final String plain) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException 
    {
        kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        kp = kpg.genKeyPair();
        publicKey = kp.getPublic();
        privateKey = kp.getPrivate();

        cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        encryptedBytes = cipher.doFinal(plain.getBytes());
        encrypted = new String(encryptedBytes);
        System.out.println("EEncrypted?????"+encrypted);
        return encrypted;

    }

    public String RSADecrypt (final String result) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException 
    {

        cipher1=Cipher.getInstance("RSA");
        cipher1.init(Cipher.DECRYPT_MODE, privateKey);
        decryptedBytes = cipher1.doFinal(result.getBytes());
        decrypted = new String(decryptedBytes);
        System.out.println("DDecrypted?????"+decrypted);
        return decrypted;

    }

And I am calling the function from here:

encrypt.setOnClickListener(new OnClickListener()
        { 
            public void onClick(View arg0) 
            {
                    try
                    {
                        RSAEncrypt rsaencrypt=new RSAEncrypt();
                        rsaencrypt.RSAEncrypt(name);

                        result=rsaencrypt.RSAEncrypt(name);
                        Toast.makeText(getBaseContext(), result.toString(),Toast.LENGTH_SHORT).show();

                        System.out.println("Result:"+result);
                    }
                    catch(Exception e)
                    {
                        e.printStackTrace();
                        Toast.makeText(getBaseContext(), e.toString(),Toast.LENGTH_LONG).show();
                    }
            }
        });

        decrypt.setOnClickListener(new OnClickListener()
        { 
            public void onClick(View arg0) 
            {
                {
                    try
                    {
                        RSAEncrypt rsadecrypt=new RSAEncrypt();

                        rsadecrypt.RSADecrypt(result);

                        ans=rsadecrypt.RSADecrypt(result);
                        System.out.println("Result is"+ans);
                        Toast.makeText(getBaseContext(), ans.toString(),Toast.LENGTH_LONG).show();
                    }
                    catch(Exception e)
                    {
                        e.printStackTrace();
                        Toast.makeText(getBaseContext(), e.toString(),Toast.LENGTH_LONG).show();
                        System.out.println("Exception is>>"+e);
                    }
            }
        });
like image 950
Riddhi Barbhaya Avatar asked Sep 18 '12 07:09

Riddhi Barbhaya


People also ask

How do I decrypt RSA encryption?

To decrypt a ciphertext C using an RSA public key we simply compute the plaintext M as: M = Cd mod N. Note that both RSA encryption and RSA decryption involve a modular exponentiation and so we would be well advised to use the Repeated Squares Algorithm if we want to make these processes reasonably efficient.

What is encryption and decryption in Android?

Encryption is the process of encoding all user data on an Android device using symmetric encryption keys. Once a device is encrypted, all user-created data is automatically encrypted before committing it to disk and all reads automatically decrypt data before returning it to the calling process.

What is RSA key in Android?

RSA is a public-key or asymmetric crypto system. It uses a public key for encryption and a private key for decryption. Anyone can use the public key to encrypt a message, but it can be decrypted only by the private key owner.

Can you crack RSA encryption?

RSA is the standard cryptographic algorithm on the Internet. The method is publicly known but extremely hard to crack. It uses two keys for encryption. The public key is open and the client uses it to encrypt a random session key.


4 Answers

My class:

package com.infovale.cripto;  import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Arrays;  import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException;  public class RSA {  KeyPairGenerator kpg; KeyPair kp; PublicKey publicKey; PrivateKey privateKey; byte[] encryptedBytes, decryptedBytes; Cipher cipher, cipher1; String encrypted, decrypted;  public String Encrypt (String plain) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException  {     kpg = KeyPairGenerator.getInstance("RSA");     kpg.initialize(1024);     kp = kpg.genKeyPair();     publicKey = kp.getPublic();     privateKey = kp.getPrivate();      cipher = Cipher.getInstance("RSA");     cipher.init(Cipher.ENCRYPT_MODE, publicKey);     encryptedBytes = cipher.doFinal(plain.getBytes());      encrypted = bytesToString(encryptedBytes);     return encrypted;  }  public String Decrypt (String result) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException  {                 cipher1=Cipher.getInstance("RSA");     cipher1.init(Cipher.DECRYPT_MODE, privateKey);     decryptedBytes = cipher1.doFinal(stringToBytes(result));     decrypted = new String(decryptedBytes);     return decrypted;  }  public  String bytesToString(byte[] b) {     byte[] b2 = new byte[b.length + 1];     b2[0] = 1;     System.arraycopy(b, 0, b2, 1, b.length);     return new BigInteger(b2).toString(36); }  public  byte[] stringToBytes(String s) {     byte[] b2 = new BigInteger(s, 36).toByteArray();     return Arrays.copyOfRange(b2, 1, b2.length); } } 
like image 35
Elton da Costa Avatar answered Sep 23 '22 22:09

Elton da Costa


In RSA you should use the public key for encryption and the private key for decryption.

Your sample code uses for encryption and decryption the public key - this can not work.

Hence in the decryption part you should initialize the cipher this way:

cipher1.init(Cipher.DECRYPT_MODE, privateKey); 

Furthermor your code has a second significant bug:

You are converting a byte array with binary content to a String.

Never ever convert binary data to a String!

Strings are for string characters, not binary data. If you want to pack binary data into a String encode it to printable characters for example using Hex or Base64.

The following example uses the hexadecimal encoder fro org.apache.common.codec package - a third party library with has to be installed.

public byte[] RSAEncrypt(final String plain) throws NoSuchAlgorithmException, NoSuchPaddingException,         InvalidKeyException, IllegalBlockSizeException, BadPaddingException {     kpg = KeyPairGenerator.getInstance("RSA");     kpg.initialize(2048);     kp = kpg.genKeyPair();     publicKey = kp.getPublic();     privateKey = kp.getPrivate();      cipher = Cipher.getInstance("RSA");     cipher.init(Cipher.ENCRYPT_MODE, publicKey);     encryptedBytes = cipher.doFinal(plain.getBytes());     System.out.println("EEncrypted?????" + new String(org.apache.commons.codec.binary.Hex.encodeHex(encryptedBytes)));     return encryptedBytes; }  public String RSADecrypt(final byte[] encryptedBytes) throws NoSuchAlgorithmException, NoSuchPaddingException,         InvalidKeyException, IllegalBlockSizeException, BadPaddingException {      cipher1 = Cipher.getInstance("RSA");     cipher1.init(Cipher.DECRYPT_MODE, privateKey);     decryptedBytes = cipher1.doFinal(encryptedBytes);     decrypted = new String(decryptedBytes);     System.out.println("DDecrypted?????" + decrypted);     return decrypted; } 
like image 61
Robert Avatar answered Sep 21 '22 22:09

Robert


Here is an example for Android of:

  • generating a private/public RSA key pair
  • encrypting a string
  • decrypting the encrypted string

These methods deal with all the base 64 encoding/decoding.

    public void TestEncryptData(String dataToEncrypt) {
        // generate a new public/private key pair to test with (note. you should only do this once and keep them!)
        KeyPair kp = getKeyPair();

        PublicKey publicKey = kp.getPublic();
        byte[] publicKeyBytes = publicKey.getEncoded();
        String publicKeyBytesBase64 = new String(Base64.encode(publicKeyBytes, Base64.DEFAULT));

        PrivateKey privateKey = kp.getPrivate();
        byte[] privateKeyBytes = privateKey.getEncoded();
        String privateKeyBytesBase64 = new String(Base64.encode(privateKeyBytes, Base64.DEFAULT));

        // test encryption
        String encrypted = encryptRSAToString(dataToEncrypt, publicKeyBytesBase64);

        // test decryption
        String decrypted = decryptRSAToString(encrypted, privateKeyBytesBase64);
    }

    public static KeyPair getKeyPair() {
        KeyPair kp = null;
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(2048);
            kp = kpg.generateKeyPair();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return kp;
    }

    public static String encryptRSAToString(String clearText, String publicKey) {
        String encryptedBase64 = "";
        try {
            KeyFactory keyFac = KeyFactory.getInstance("RSA");
            KeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKey.trim().getBytes(), Base64.DEFAULT));
            Key key = keyFac.generatePublic(keySpec);

            // get an RSA cipher object and print the provider
            final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
            // encrypt the plain text using the public key
            cipher.init(Cipher.ENCRYPT_MODE, key);

            byte[] encryptedBytes = cipher.doFinal(clearText.getBytes("UTF-8"));
            encryptedBase64 = new String(Base64.encode(encryptedBytes, Base64.DEFAULT));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return encryptedBase64.replaceAll("(\\r|\\n)", "");
    }

    public static String decryptRSAToString(String encryptedBase64, String privateKey) {

        String decryptedString = "";
        try {
            KeyFactory keyFac = KeyFactory.getInstance("RSA");
            KeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey.trim().getBytes(), Base64.DEFAULT));
            Key key = keyFac.generatePrivate(keySpec);

            // get an RSA cipher object and print the provider
            final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
            // encrypt the plain text using the public key
            cipher.init(Cipher.DECRYPT_MODE, key);

            byte[] encryptedBytes = Base64.decode(encryptedBase64, Base64.DEFAULT);
            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
            decryptedString = new String(decryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return decryptedString;
    }
like image 32
seb Avatar answered Sep 23 '22 22:09

seb


I think the problem is that you should use the same key pair to encrypt and decrypt the cipher. Referring to the JavaDoc:

 genKeyPair() This will generate a new key pair every time it is called.
like image 21
jaredzhang Avatar answered Sep 24 '22 22:09

jaredzhang