Почему происходит сбой шифрования AES на iPad и дешифрования в PHP? - PullRequest
3 голосов
/ 15 августа 2011

У меня есть приложение для 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);  
}  

и этот код Objective-C в моем приложении для iPad:

#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?

Ответы [ 2 ]

3 голосов
/ 15 августа 2011

Проверьте ключ, который вы используете.В PHP константы MCRYPT_RIJNDAEL_128 _256 и т. Д. Представляют не силу ключа, а размер используемого блока.

Чтобы получить 128-битное шифрование с PHP, вы хотите использовать ключ длиной 16 байт.Для 256 вам нужно 32 байта и т. Д. И т. Д.

И ваш код на PHP и C выглядят корректно для меня.Убедитесь, что ключ используется правильно в обоих случаях.

Как еще одна мысль.Похоже, вы используете заполнение PKCS # 7 в C. Я не верю, что PHP разработан для работы с этим заполнением по умолчанию.Если мне не изменяет память, я думаю, что функции Mcrypt используют заполнение нулями.

Наконец, проверьте ваш вектор инициализации в PHP.Я заметил, что вы не используете его в своем C-коде, что означает, что вы не должны принимать переменную $ iv в PHP.Это должно быть передано как NULL в функции mcrypt (но это крайне нежелательно).

Вместо этого вы должны рандомизировать IV в своем коде C (где данные шифруются) и затем отправить IVнаряду с зашифрованными данными.Вы можете определить размер IV для используемого алгоритма и отделить его от передней части зашифрованных данных, чтобы затем использовать для заполнения своей стороны PHP.Это дополнительно защищает ваше шифрование.

0 голосов
/ 10 марта 2012

Пожалуйста, обратитесь к этому обсуждению для лучшего использования AES шифрование / дешифрование AES с CommonCrypto использует слишком много памяти - Objective-C

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...