My problem is: what I encrypt in Java I can decrypt perfectly in Java, but PHP mcrypt can’t decrypt. What I encrypt with mcrypt I can decrypt with mcrypt, but can’t in Java.
I want to send and receive encrypted data from a Java application to a PHP page, so I need it to be compatible.
Here’s what I have…
JAVA…
public static String crypt(String input, String key){
byte[] crypted = null;
try{
SecretKeySpec skey = new SecretKeySpec(Base64.decodeBase64(key), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skey);
crypted = cipher.doFinal(input.getBytes());
}catch(Exception e){
}
return Base64.encodeBase64String(crypted);
}
public static String decrypt(String input, String key){
byte[] output = null;
try{
SecretKeySpec skey = new SecretKeySpec(Base64.decodeBase64(key), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skey);
output = cipher.doFinal(Base64.decodeBase64(input));
}catch(Exception e){
}
return new String(output);
}
Running:
public static void main(String[] args) {
String key = "Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8=";
String data = "example";
System.out.println(Cpt.decrypt(Cpt.crypt(data, key), key));
}
Output:
example
PHP…
function getEncrypt($sStr, $sKey) {
return base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
$sKey,
$sStr,
MCRYPT_MODE_ECB
)
);
}
function getDecrypt($sStr, $sKey) {
return mcrypt_decrypt(
MCRYPT_RIJNDAEL_256,
$sKey,
base64_decode($sStr),
MCRYPT_MODE_ECB
);
}
Running:
$crypt = getDecrypt(getEncrypt($str, $key), $key);
echo "<p>Crypt: $crypt</p>";
Output:
Crypt: example�������������������������
Using PHP to crypt “example” with key “Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8=” I get “YTYhgp4zC+w5IsViTR5PUkHMX4i7JzvA6NJT1FqhoGY=”.
Using Java to crypt the same thing with the same key I get “+tdAZqTE7WAVPXhB3Tp5+g==”.
I’m encoding and decoding to base64 in the right order and I tested base64 encode and decode compatibility between Java and PHP and it’s working.
BUG#1
MCRYPT_RIJNDAEL_256is not AES. The 256 in that constant refers to the blocksize, not the keysize. UseMCRYPT_RIJNDAEL_128to get the same algorithm as AES. The keysize is set just by the number of bytes in the key argument you supply. So supply 32 bytes and you get AES with a 256-bit key.BUG#2
These two lines are never correct in Java and indicate a fundamental misunderstanding of the nature of the arbitrary binary data produced by cryptographic transforms:
There is nothing wrong with transmitting and storing
byte[]directly, but if you must use only printable strings then you should base64 encode/decode to do so. As you are already using base64 extensively that would seem like the way to go. I would guess that the correct two lines would be:EDIT:
Just kidding about bug #2. Really, I was wrong, I didn’t notice it was the decrypt direction. Of course, if you know the decrypted
byte[]is a valid string then it is perfectly correct to do what your code does.