0

It is pretty straightforward to generate public/private key pair from raw resource file(s) and use them to encrypt/decrypt in android app. However, the following code DO NOT correctly recover plaintext when it is run with Android-x86-v4.4.4 emulator in VirtualBox. Could anyone please point-out what is wrong with this code (it does not give any error or generate any exceptions): (Changing to Cipher.getInstance("RSA/NONE/NoPadding") is also of no help)

    PublicKey mPublicKey = null;
    PrivateKey mPrivateKey = null;

    String mPlainText = "The quick brown fox jumped over the lazy dog" ;
    byte[] mEncryptText = null;
    byte[] mDecryptText = null;


    try {
        InputStream mIS = getResources().openRawResource(R.raw.test1_public_key);
        DataInputStream dis = new DataInputStream(mIS);
        byte [] keyBytes = new byte [(int) mIS.available()];
        dis.readFully(keyBytes);
        dis.close();
        mIS.close();
        X509EncodedKeySpec mX509KeySpec = new X509EncodedKeySpec(keyBytes);
        mPublicKey = (KeyFactory.getInstance("RSA")).generatePublic(mX509KeySpec);
        Toast.makeText(this, "Publickey generated", Toast.LENGTH_LONG).show();
    }
    catch(Exception e){
        Log.e("onButtondecrypt", "exception", e);
        Log.e("onButtondecrypt", "exception: " + Log.getStackTraceString(e));
    }

    try {
        InputStream mIS = getResources().openRawResource(R.raw.test1_private_key);
        DataInputStream dis = new DataInputStream(mIS);
        byte [] keyBytes = new byte [(int) mIS.available()];
        dis.readFully(keyBytes);
        dis.close();
        mIS.close();
        PKCS8EncodedKeySpec mPKCS8keySpec = new PKCS8EncodedKeySpec(keyBytes);
        mPrivateKey = (KeyFactory.getInstance("RSA")).generatePrivate(mPKCS8keySpec);
        Toast.makeText(this, "PRIVATE key generated", Toast.LENGTH_LONG).show();
    }
    catch(Exception e){
        Log.e("onButtondecrypt", "exception", e);
        Log.e("onButtondecrypt", "exception: " + Log.getStackTraceString(e));
    }

    Toast.makeText(this, mPlainText, Toast.LENGTH_LONG).show();

    Toast.makeText(this, "Encrypting with Publickey ...", Toast.LENGTH_LONG).show();
    try {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, mPublicKey);
        mEncryptText = cipher.doFinal(mPlainText.getBytes());
        Toast.makeText(this, mEncryptText.toString(), Toast.LENGTH_LONG).show();
    }
    catch(Exception e){
        Log.e("onButtondecrypt", "exception", e);
        Log.e("onButtondecrypt", "exception: " + Log.getStackTraceString(e));
    }

    Toast.makeText(this, "Decrypting with PRIVATE key ...", Toast.LENGTH_LONG).show();
    try {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, mPrivateKey);
        mDecryptText = cipher.doFinal(mEncryptText);
        Toast.makeText(this, mDecryptText.toString(), Toast.LENGTH_LONG).show();
    }
    catch(Exception e){
        Log.e("onButtondecrypt", "exception", e);
        Log.e("onButtondecrypt", "exception: " + Log.getStackTraceString(e));
    }

Thanks to all.

gsp
  • 13
  • 1
  • 5
  • `mDecryptText.toString()` doesn't do what you think it does. See [this](https://stackoverflow.com/q/29140402/238704) question. – President James K. Polk Oct 18 '18 at 12:18
  • the way string is converted to byte[] and vice-versa is wrong. correct method is byte[] st = txt.getBytes("UTF-8"); and String s = new String(bytes); – gsp Oct 18 '18 at 13:30
  • It is strongly advised to include the full *"algorithm/mode/padding"* specification in for the argument to `Cipher.getInstance()`. It also recommended to transition to OAEP padding for RSA encryption. So, for example, you can specify `Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");` – President James K. Polk Oct 18 '18 at 18:54

2 Answers2

0

the way string is converted to byte[] and vice-versa is wrong. correct method is

byte[] st = txt.getBytes("UTF-8"); and

String s = new String(bytes);

Because of this, the encryption/decryption was correct, only the toast display was not correct.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
gsp
  • 13
  • 1
  • 5
-1
public static String encrypt(String value, String key) {

    String encrypted = null;
    try {
        byte[] value_bytes = value.getBytes("UTF-8");
        byte[] key_bytes = getKeyBytes(key);
        encrypted = Base64.encodeToString(encrypt(value_bytes, key_bytes, key_bytes), 0);
    } catch (Exception ex) {
        ExceptionRecord.catchException(ex);

    }
    return encrypted;
}

public static byte[] encrypt(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2, byte[] paramArrayOfByte3)
{
    byte[] byteencrypt = new byte[0];
    try {
        // setup AES cipher in CBC mode with PKCS #5 padding
        Cipher localCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        // encrypt
        localCipher.init(1, new SecretKeySpec(paramArrayOfByte2, "AES"), new IvParameterSpec(paramArrayOfByte3));
        byteencrypt = localCipher.doFinal(paramArrayOfByte1);
    }catch (Exception ex)
    {
        ExceptionRecord.catchException(ex);
    }
    return byteencrypt;
}

/**
 *
 * @param value data to decrypt
 * @param key a secret key used for encryption
 * @return String result after decryption
 * @throws KeyException
 * @throws GeneralSecurityException
 * @throws GeneralSecurityException
 * @throws InvalidAlgorithmParameterException
 * @throws IllegalBlockSizeException
 * @throws BadPaddingException
 * @throws IOException
 */
public static String decrypt(String value, String key) {
    String decrypted = null;
    try {
        byte[] value_bytes = Base64.decode(value, 0);
        byte[] key_bytes = getKeyBytes(key);
        decrypted = new String(decrypt(value_bytes, key_bytes, key_bytes), "UTF-8");
    } catch (Exception ex) {
        ExceptionRecord.catchException(ex);

    }
    return decrypted;
}

public static byte[] decrypt(byte[] ArrayOfByte1, byte[] ArrayOfByte2, byte[] ArrayOfByte3)
{
    byte[] bytedecrypt = new byte[0];
    try {
        // setup AES cipher in CBC mode with PKCS #5 padding
        Cipher localCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        // decrypt
        localCipher.init(2, new SecretKeySpec(ArrayOfByte2, "AES"), new IvParameterSpec(ArrayOfByte3));
        bytedecrypt = localCipher.doFinal(ArrayOfByte1);
    }catch (Exception ex)
    {
        ExceptionRecord.catchException(ex);
    }
    return bytedecrypt;
}

private static byte[] getKeyBytes(String paramString)
{
    byte[] keybytes = new byte[0];
    try {
        byte[] arrayOfByte1 = new byte[16];
        byte[] arrayOfByte2 = paramString.getBytes("UTF-8");
        System.arraycopy(arrayOfByte2, 0, arrayOfByte1, 0, Math.min(arrayOfByte2.length, arrayOfByte1.length));
        keybytes = arrayOfByte1;
    }
    catch (Exception ex)
    {
        ExceptionRecord.catchException(ex);
    }
    return  keybytes;
}
Bholendra Singh
  • 980
  • 7
  • 14