For a few days i have been trying to get the encrypted data from a PHP service to my android application. I want to use Rijndael 256 bit encryption.
Encrypting and decrypting a string in PHP works fine. What i do is i send the data from php to android in the following structure = (initialization vector + hash(md5) + encrypted data).
In Java i split the received string in 3 compartments.
But what i get in java is a error message telling: IV must be 16 bytes long. I checked all over the internet trying to find a solution to this problem. Some suggested not using mcrypt in php while others said to use a 128 algorithm variant. Using 128 bit in PHP breaks the encryption.
Below i have 2 examples to perhaps clarify the problem further.
I appreciate your help.
PHP CODE encryption / decryption:
function encrypt_data($data,$privk)
{
// Random number for feeding into AES encyption algorithm
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
// Check if decrypted properly
$hash = md5($data);
// Encrypt the data using the privk and the iv
$encrypted = trim(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $privk, trim($data), MCRYPT_MODE_CBC, $iv));
$encode = base64_encode($encrypted);
$base64_iv = base64_encode($iv);
return $base64_iv.$hash.'='.$encode;
}
function decrypt_data($data,$privk)
{
// Split data into 3 variables: iv,hash,encdata
$arr = explode('=',$data,3);
$iv = base64_decode($arr[0]);
$hash = $arr[1];
$encdata = base64_decode($arr[2]);
// Decrypt using the 3 variables
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $privk, trim($encdata), MCRYPT_MODE_CBC, $iv));
// Check integrity of decrypted data
$hdec = md5($decrypted);
if ($hdec == $hash)
{
return $decrypted;
}
else
{
return false;
}
}
JAVA decryption:
public String decryptJson(String data)
{
String[] split= data.trim().split("=");
byte[] iv = Base64.decode(split[0],3);
String hash = split[1];
byte[] encd = Base64.decode(split[2],0);
String skey = "secretkeyfromdatabase";
byte[] skeyb = skey.getBytes();
try
{
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeySpec skeyspec = new SecretKeySpec(skeyb,"AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE,skeyspec,ivspec);
byte[] original = cipher.doFinal(encd);
return original.toString();
}
catch(Exception ex)
{
ex.printStackTrace();
return "ERROR! | "+ex+"IV:"+iv;
}
}
"I see it is 32 bytes in length. Is there a way so that it can accept a 32 byte IV?"
No. The underlying problem is that "Rijndael_256" in mcrypt is a Rijndael variant that uses 256 bit blocksize instead of 128 bit blocksize that is used in all AES versions. You will have difficulties to find any implementation of "Rijndeal_256" other than the mcrypt library. (See How can I do this same encrypt/decrypt PHP function on iOS with Objective-C?)
Edit: Bouncy Castle actually supports Rijndeal_256 via RijndaelEngine
: Encryption in Android equivalent to php's MCRYPT_RIJNDAEL_256
"Some suggested not using mcrypt in php while others said to use a 128 algorithm variant."
Both suggestions are correct. mcrypt is a horrible library, but if you have to you can get something running with "Rijndael_128", which is identical to AES128.
Some remarks on your code: You hash the verbatim data md5($data)
but encrypt a trimmed plaintext trim($data)
. You use the default zero padding of mcrypt but specify PKCS5Padding in Java, this wont't work. As you use CBC but no authentication after encryption and before decryption you are likely prone to padding oracle attacks.
"Yeah well im new in using cryptography." - Alternatives:
Given your current level of cryptography expertise you should avoid implementing any cryptography at all. Instead use high level libraries and protocols. Which one to use greatly depends on your use case. For example if the PHP code runs on a trusted server and the Java code on the client side you can connect to the server via SSL/TLS (most likely using https). The TLS connection will authenticate the server to the client and you can use basic http authentcation to authenticate the client to the server.