为什么iPad上的AES加密和PHP中的解密失败? [英] Why does this AES encryption on an iPad and decryption in PHP fail?

查看:116
本文介绍了为什么iPad上的AES加密和PHP中的解密失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个iPad应用程序将加密信息传输到基于PHP的网站,但我在解密这些信息方面遇到了困难。我使用以下代码进行PHP端解密:

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);  
}  

以及我的iPad应用程序中的这个Objective-C代码:

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 /* 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端解密的数据时?

Why am I seeing data corruption when trying to decrypt data encoded on the iPad and decrypted on the PHP side?

推荐答案

检查您正在使用的密钥。在PHP中,MCRYPT_RIJNDAEL_128 _256等常量不代表关键强度,而是代表正在使用的块大小。

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.

要使用PHP获得128位加密,您需要使用密钥长度为16个字节。对于256,你需要32个字节,依此类推。

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.

PHP和C代码对我来说都是正确的。确保在两种情况下正确使用密钥。

Both you PHP and C code look correct to me. Make sure the key is being used correctly in both cases.

另一种想法。看起来你在C中使用PKCS#7填充。我不认为PHP默认设计用于填充。如果内存为我服务,我相信Mcrypt函数使用空填充。

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.

最后用PHP检查你的初始化向量。我注意到你在C代码中没有使用它,这意味着你不应该接受PHP中的$ iv变量。这应该作为NULL传递给mcrypt函数(但是强烈建议不要这样做)。

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).

你应该做的是在你的C代码中随机化一个IV(数据的位置)正在加密)然后将IV与加密数据一起发送。您可以检测正在使用的算法的IV大小,并将其从加密数据的前面拆分,然后用于填充PHP方面的内容。这进一步确保了您的加密。

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.

这篇关于为什么iPad上的AES加密和PHP中的解密失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆