Why does this AES encryption on an iPad and decryption in PHP fail?
I have an iPad application that transmits encrypted information to a PHP-based website, but I'm having difficulties in properly decrypting this information. I use the following code for the PHP-side decryption:
//Decryption function
function mc_decrypt($decrypt, $key, $iv)
{
$decoded = base64_decode($decrypt);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
mcrypt_generic_init($td, $key, $iv);
$decrypted = mdecrypt_generic($td, $decoded);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return trim($decrypted);
}
and this Objective-C code in my iPad application:
#import <CommonCrypto/CommonCryptor.h>
@implementation NSData (AES256)
- (NSData *)AES256EncryptWithKey:(NSString *)key {
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
- (NSData *)AES256DecryptWithKey:(NSString *)key {
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initial开发者_StackOverflow中文版ization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer); //free the buffer;
return nil;
}
@end
Why am I seeing data corruption when trying to decrypt data encoded on the iPad and decrypted on the PHP side?
Check the key that you're using. In PHP the MCRYPT_RIJNDAEL_128 _256 etc constants do not represent the key strength, but rather the block size being used.
To get 128-bit encryption with PHP you want to use a key that is 16 bytes long. For 256 you need 32 bytes and so on and so forth.
Both you PHP and C code look correct to me. Make sure the key is being used correctly in both cases.
As another thought. It looks like you're using PKCS#7 padding in C. I don't believe PHP is designed to work with that padding by default. If memory serves me, I believe the Mcrypt functions use null padding.
Lastly check your initialization vector in PHP. I noticed you're not using one in your C code which means you should not be accepting an $iv variable in PHP. That should be passed as NULL into the mcrypt functions (but this is highly discouraged).
What you should do instead is randomize an IV in your C code (where the data is being encrypted) and then send the IV along with the encrypted data. You can detect the size of the IV for the algorithm being used and split it off the front of the encrypted data to then use to populate your PHP side of things. This further secures your encryption for you.
please refere to this discussion for better usage AES encrypt/decrypt AES with CommonCrypto uses too much memory - Objective-C
精彩评论