I am trying to decrypt the string "~9?8?m???=?T?G"
that I receive from a back-end server which uses OpenSSL to encrypt the String using AES-256-CBC. There is the code block:
public static String decryptText(String textToDecrypt) {
try {
byte[] base64TextToDecrypt = Base64.encodeBase64(textToDecrypt.getBytes("UTF-8"));
byte[] guid = "fjakdsjkld;asfj".getBytes("UTF-8");
byte[] iv = new byte[16];
System.arraycopy(guid, 0, iv, 0, guid.length);
IvParameterSpec ips = new IvParameterSpec(iv);
byte[] secret = DECRYPTION_SECRET_HASH.getBytes("UTF-8");
SecretKeySpec secretKey = new SecretKeySpec(secret, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// decryption pass
cipher.init(Cipher.DECRYPT_MODE, secretKey, ips);
byte[] converted = cipher.doFinal(base64TextToDecrypt);
System.out.println(new String(converted));
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Decipher error for " + textToDecrypt, e);
}
return "";
}
Unfortunately, when I get to the
byte[] converted = cipher.doFinal(base64TextToDecrypt);
statement the following exception is thrown:
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
Any ideas?
You should decode the string instead of encoding the platform specific representation of the string, right at the start of your method.
byte[] base64TextToDecrypt = Base64.decodeBase64(textToDecrypt);
or more precisely:
byte[] bytesToDecrypt = Base64(base64TextToDecrypt);
if you name your variables correctly.
In general, each time you (feel like you have to) use the String.getBytes(): byte[]
method or the String(byte[])
constructor you are likely doing something wrong. You should first think about what you are trying to do, and specify a character-encoding if you do need to use it.
In your case, the output in the converted
variable is probably character-encoded. So you you could use the following fragment:
String plainText = new String(converted, StandardCharsets.UTF_8);
System.out.println(plainText);
instead of what you have now.
So thanks to @owlstead, I was able to figure out the solution. It was that I made the mistake of Base64encoding an already Base64 encoded string. The following is by code chunk.
public static String decryptText(String textToDecrypt) {
try {
byte[] decodedValue = Base64.decodeBase64(textToDecrypt.getBytes());
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ips = new IvParameterSpec(iv);
byte[] input = textToDecrypt.getBytes();
Cipher cipher = Cipher.getInstance(ENCRYPTION_METHOD);
// decryption pass
cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY, ips);
byte[] plainText = cipher.doFinal(decodedValue);
return new String(plainText);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Decipher error for " + textToDecrypt, e);
}
return "";
}
The corresponding encrypting is like this
public static String encryptText(String textToEncrypt) {
try {
byte[] guid = "1234567890123456".getBytes("UTF-8");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ips = new IvParameterSpec(iv);
// The secret key from the server needs to be converted to byte array for encryption.
byte[] secret = ENCRYPTION_SECRET_HASH.getBytes("UTF-8");
// we generate a AES SecretKeySpec object which contains the secret key.
// SecretKeySpec secretKey = new SecretKeySpec(secret, "AES");
Cipher cipher = Cipher.getInstance(ENCRYPTION_METHOD);
cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY, ips);
byte[] cipherText = cipher.doFinal(textToEncrypt.getBytes());
byte[] base64encodedSecretData = Base64.encodeBase64(cipherText);
String secretString = new String(base64encodedSecretData);
return secretString;
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Encryption error for " + textToEncrypt, e);
}
return "";
}
Keep the following things in mind while encrypting and decrypting strings,
ENCRYPTION:
Convert string to byteArray using toByteArray(Charsets.UTF-8) and always specify the charset with UTF-8.
Encrypyt the above byteArray using cipher.doFinal(byteArray).
Now this is not enough, you need to do base64 encoding for that encrypted byteArray using Base64.encode(encryptedByteArray, Base64.DEFAULT)
Remember this again returns byteArray , if you want to convert to string, use toString(Charsets.UTF-8) and most importantly specify the charset again as UTF-8 and then process or store it in DB as you wish.
DECRYPTION:
1.Get the encrypted string and first step while decrypting is to decode the encrypted string using base64.decode(encryptedString.toByteArray(Charsets.UTF-8), Base64.DEFAULT)
Now decrypt the decoded byteArray by using cipher.dofinal(decodedByteArray).
Convert the Decrypted byteArray to String using toString(Charsets.UTF-8). NOTE:Always specify the charset. This returns the original string.
I know I have not shared any code but trust me the flow is the important part while encrypting and decrypting a string..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With