AES 256 and Base64 Encrypted string works on iOS 8 but truncated on iOS 7

844 views Asked by At

One of my app needs to download a database with the content encrypted in AES 256. So I've used on server side phpAES to encode the strings in AES CBC with an IV.

On the iOS side I'm using FBEncryptor to decrypt the string.

This is the code on the server side:

$aes = new AES($key, "CBC", $IV);
$crypt = $aes->encrypt($string);
$b64_crypt = base64_encode($crypt);

On the iOS side I'm doing this:

NSString* decrypt = [FBEncryptorAES decryptBase64String:b64_crypt keyString:key iv:iv];

Actually everythings works fine on iOS 8. The problem is on iOS 7 where the decoded string is truncated at random length.

Thoughts?

2

There are 2 answers

8
Scott Arciszewski On BEST ANSWER

Don't use phpAES. You're shooting yourself in the foot with an enormous cannon.

From their page:

The free version only supports ECB mode, and is useful for encrypting/decrypting credit card numbers.

This is incredibly wrong and misleading. ECB mode is not suitable for any purpose except as a building block for other modes of operation. You want an AEAD mode; or, failing that, CBC or CTR with HMAC-SHA2 and a CSPRNG-derived IV/nonce. Using unauthenticated encryption is a very bad idea.

For interoperability with iOS, you should use libsodium.

If you cannot use libsodium, your best bet is OpenSSL and explicitly not mcrypt, and a compatible interface on the iOS side.

All currently supported versions (5.4+) of PHP expose openssl_encrypt() and openssl_decrypt() which allow fast and secure AES-CBC and AES-CTR encryption. However, you should consider using a library that implements these functions for you instead of writing them yourself.

3
zaph On

The truncation could be the result of incompatible padding.

phpAES uses non-standard null padding similar to mcrypt, this is unfortunate since the standard for padding is PKCS#7. It is unfortunate that one has to read the code to find that out. It is important to supply a 256-bit (32-byte) key since that sets the key size for the algorithm.

FBEncryptor only supports PKCS#7 padding.

So, these two methods are incompatible.

One solution is to add PKCS#7 padding to the string in php prior to calling phpAES which will not then add the null padding. Then FBEncryptor will be compatible with the encrypted data.

PKCS#7 padding always adds padding. The padding is a series by bytes with the value of the number of padding bytes added. The length of the padding is the block_size - (length(data) % block_size.

For AES where the block is is 16-bytes (and hoping the php is valid, it had been a while):

$pad_count = 16 - (strlen($data) % 16);
$data .= str_repeat(chr($pad_count), $pad_count);

Please add to the question working example keys, iv clear data and encrypted data as hex dumps.