Aescrypt Decryption Between iOS and PHP

AESCrypt decryption between iOS and PHP

Disclaimer: I have zero iPhone development experience.

Short answer - what tc. said. Something is horribly wrong with the AES256EncryptWithKey:

Being AES256 you would expect it to require a 32 byte key, not a 16 byte key. But OK, say it pads shorter keys with null bytes to make them 32 bytes. This might explain why your 16 byte key is being padded with 16 null characters.

But, when it comes to the actual act of encryption, it's using AES 128, but with the 32 byte key. Say wha?

Converting tc.'s Python to PHP:

$base64encoded_ciphertext = '7opqbb7sEVNoXplyQv/X8g==';
$key = 'a16byteslongkey!';

$padded_key = $key . str_repeat(chr(0x00), 16); // Argh!

$result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $padded_key, base64_decode($base64encoded_ciphertext), 'ecb');

// Yetch - $result ends up being padded with 0x0b's (vertical tab).
var_dump(rtrim($result, chr(0x0b)));

Result:

string(5) "Hello"

~~

Edit: This post from Henno has some relevant details.

~~

Did some additional research. The null padding on your key is likely because AES256 requires a 32 byte key. The 0x0B padding on the plaintext is thanks to PKCS7. PKCS7 is a padding scheme where the byte used for padding is equal in value to the number of bytes added. In this example, 11 bytes were added to the end of 'Hello' turning your 5 byte input into a 16 byte block for AES. 11 = 0x0B.

Thus, the code above will not work when the plaintext is not length = 5. Try the following instead:

$pad_char = ord(substr($result, -1));
$result_without_padding = substr($result, 0, strlen($result) - $pad_char);

PHP iOS AES Encryption

As said in the comments, it would probably easiest for you to use HTTPS.

I once set up an iPhone app that had to communicate with a PHP backend over HTTPS, and spent many hours trying to find out why the iPhone wouldn't accept the encrypted connection.

As it turned out, it didn't work because I was using a self-signed certificate on the server side. Buying an SSL certificate from a Certificate Authority solved all issues.

SSL certificates that validate a single domain name without company or extended validation are really cheap, so I suggest you give that a try!

How to do AES256 decryption in PHP?

I'm not terribly familiar with this stuff, but it seems like trying MCRYPT_RIJNDAEL_256 in place of MCRYPT_RIJNDAEL_128 would be an obvious next step...

Edit: You're right -- this isn't what you need. MCRYPT_RIJNDAEL_128 is in fact the right choice. According to the link you provided, your key and IV are twice as long as they should be:

// How do you do 256-bit AES encryption in PHP vs. 128-bit AES encryption???
// The answer is: Give it a key that's 32 bytes long as opposed to 16 bytes long.
// For example:
$key256 = '12345678901234561234567890123456';
$key128 = '1234567890123456';

// Here's our 128-bit IV which is used for both 256-bit and 128-bit keys.
$iv = '1234567890123456';

AES Encryption in android and decryption in php and vice versa

I do something like this which actually works ;)

public class AESCrypter {
private final Cipher cipher;
private final SecretKeySpec key;
private AlgorithmParameterSpec spec;

public AESCrypter(String password) throws Exception
{
// hash password with SHA-256 and crop the output to 128-bit for key
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(password.getBytes("UTF-8"));
byte[] keyBytes = new byte[32];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);

cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
key = new SecretKeySpec(keyBytes, "AES");
spec = getIV();
}

public AlgorithmParameterSpec getIV()
{
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
IvParameterSpec ivParameterSpec;
ivParameterSpec = new IvParameterSpec(iv);

return ivParameterSpec;
}

public String encrypt(String plainText) throws Exception
{
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
String encryptedText = new String(Base64.encode(encrypted, Base64.DEFAULT), "UTF-8");

return encryptedText;
}

public String decrypt(String cryptedText) throws Exception
{
cipher.init(Cipher.DECRYPT_MODE, key, spec);
byte[] bytes = Base64.decode(cryptedText, Base64.DEFAULT);
byte[] decrypted = cipher.doFinal(bytes);
String decryptedText = new String(decrypted, "UTF-8");

return decryptedText;
}
}

Call this class like this :

 try {
AESCrypter _crypt = new AESCrypter("password");
String output = "";
String plainText = "top secret message";
output = _crypt.encrypt(plainText); //encrypt
System.out.println("encrypted text=" + output);
output = _crypt.decrypt(output); //decrypt
System.out.println("decrypted text=" + output);
} catch (Exception e) {
e.printStackTrace();
}

And for iPhone (Code is here) : https://github.com/Gurpartap/AESCrypt-ObjC

Hope this code works for you too :)



Related Topics



Leave a reply



Submit