I am working in AES256 to be able to encrypt/decrypt between iOS and PHP using insecure channels.
I have seen many similar questions that move around the key size, the mode (CBC or ECB), the use of a random iv, etc. But in this case, I found a weird behaviour as follows.
Configuration in both environments: - Key: 32 bytes(256 bits) - Block size: 128 bits (standard) - iv: 16 bytes (static for testing purposes) - Mode: CBC
If I encrypt a 16 or 32 bytes text (to match the AES block size), the result in Swift, and PHP are similar but not quite the same:
key = "12345678901234567890123456789012" plainText = "12345678901234567890123456789012" iv = "1234567890123456"
Swift cipher = e5RnnlJkv4QGnGhkMwfvgMHr80NWUVhbvvfCdPQ5V2KyKJTx4KfWmn4HXi4dG0b8 PHP cipher = e5RnnlJkv4QGnGhkMwfvgMHr80NWUVhbvvfCdPQ5V2I=
As you can see, there is a difference in the cipher length and in the last 2 characters of the PHP Base64 String.
But if I use a text that is not a AES128 Block Size multiplier, let´s say "Hello World", bot environments report different (but same size) ciphers as follows
Swift cipher = bdwO/5C8a+pliIoIXtuzfA==
PHP cipher = oPotHCkxpOwQhIaCz6hNMw==
In both cases (Swift and PHP), the cipher is decrypted correctly regardless of the size of the plaintext. Also, the Swift results are consistent with the Objective-C version of the code
Attached the simplified code used:
PHP
$key = "12345678901234567890123456789012";
$iv = "1234567890123456";
$plaintext = "Hello World";
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
$ciphertext_base64 = base64_encode($ciphertext);
echo "ciphertext: ".$ciphertext_base64."</br>";
Swift
let keyData: NSData! = (key as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let keyBytes = UnsafePointer<UInt8>(keyData.bytes)
let keyLength = size_t(kCCKeySizeAES256)
let plainData = (plainText as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let dataLength = UInt(plainData.length)
let dataBytes = UnsafePointer<UInt8>(plainData.bytes)
var bufferData = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
var bufferPointer = UnsafeMutablePointer<UInt8>(bufferData.mutableBytes)
let bufferLength = size_t(bufferData.length)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options = UInt32(kCCOptionPKCS7Padding)
let ivData: NSData! = (iv as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let ivPointer = UnsafePointer<UInt8>(ivData.bytes)
var numBytesEncrypted: UInt = 0
var cryptStatus = CCCrypt(operation, algoritm, options, keyBytes, keyLength, ivPointer, dataBytes, dataLength, bufferPointer, bufferLength, &numBytesEncrypted)
bufferData.length = Int(numBytesEncrypted)
let base64cryptString = bufferData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
println(base64cryptString)
Why are these different?