我有一个iPad应用程序将加密信息传输到基于PHP的网站,但我在解密这些信息方面遇到了困难。我使用以下代码进行PHP端解密:
//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);
}
和我的iPad应用程序中的这个Objective-C代码:
#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 /* initialization 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
为什么我在尝试解密iPad上编码的数据并在PHP端解密时会看到数据损坏?
答案 0 :(得分:3)
检查您正在使用的密钥。在PHP中,MCRYPT_RIJNDAEL_128 _256等常量不代表关键强度,而是代表正在使用的块大小。
要使用PHP获得128位加密,您需要使用长度为16个字节的密钥。对于256,您需要32个字节,依此类推。
PHP和C代码对我来说都是正确的。确保在两种情况下正确使用密钥。
另一个想法。看起来你在C中使用PKCS#7填充。我不认为PHP默认设计用于填充。如果内存为我服务,我相信Mcrypt函数使用空填充。
最后在PHP中检查初始化向量。我注意到你没有在你的C代码中使用它,这意味着你不应该接受PHP中的$ iv变量。这应该作为NULL传递给mcrypt函数(但是非常不鼓励这样做。)
您应该做的是将C代码中的IV随机化(数据被加密),然后将IV与加密数据一起发送。您可以检测正在使用的算法的IV大小,并将其从加密数据的前面拆分,然后用于填充PHP方面的内容。这进一步确保了您的加密。
答案 1 :(得分:0)
请参阅此讨论以更好地使用AES加密/解密 AES with CommonCrypto uses too much memory - Objective-C