Different results in AES256 encryption in Swift (iOS) and PHP
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:
$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>";
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?
- Decode OpenSSL AES256 string in iOS
- Objective-C decrypt AES 128 cbc hex string
- I Want to Create AES 128 using CFB Encryption with No Padding in objective c
- How can I make my AES encryption identical between Java and Objective-C (iPhone)?
- AES with CommonCrypto uses too much memory - Objective-C
- PHP iOS AES Encryption
Solutions Collect From Internet About “Different results in AES256 encryption in Swift (iOS) and PHP”
This is due to padding mode differences.
PHP uses “zero padding” if the plain text is not N-times the block size. So PHP pads 0..15 bytes with value
00 for 128 bit block ciphers such as AES. For plaintext that ends on a block boundary it will not add any padding bytes.
Most other languages use PKCS#7 padding, which pads up to the next block boundary, where the padding byte reflects the number of bytes added. So that would be 1..16 bytes with a value of 1..16 (or
10 in hexadecimals). For plaintext that ends on a block boundary it will add 16 bytes of padding.
PKCS#7 padding is deterministic and does not depend on the plaintext value (which could consist of bytes with any value, not just text); in other words, it can always be applied and removed independent of the content.
Zero padding has the issue that plain text ending with
00 bytes may have those
00 bytes removed during unpadding. This is usually not an issue for ASCII compatible strings as
00 is a control character, usually meaning End Of File (EOF).
Please check the comments on
mcrypt_encrypt to see how you can apply PKCS#7 padding to PHP.
- Firebase, how do I return a handle so that I can call removeObserver?
- How to dismiss UIPopover from a button in the Popover
- How do I rename a project in Xcode 5?
- KVO not working: message was received but not handled
- Error when using
- Upload image from iOS app to php — Can't quite get it right — What am I missing?
- How to TDD UIGestureRecognizers?
- List of fonts that can be used with SpriteKit's labelNodeWithFontNamed method
- NSDate set timezone in swift
- anchor tag not working in safari (ios) for iPhone/iPod Touch/iPad
- Is there no default(T) in Swift?
- How can you apply distortions to a UIImage using OpenGL ES?
- Does a project have to be created as a sprite kit or can the framework simply be added?
- Swift 2 : Iterating and upper/lower case some characters
- Display data in two different TableView in the same View in Swift