Совместимость между двумя алгоритмами AES

1

Я новичок в криптографии, и я создаю некоторые тестовые приложения, чтобы попытаться понять основы этого. Я не пытаюсь строить алгоритмы с нуля, но я пытаюсь сделать два разных варианта реализации AES-256 друг с другом.

У меня есть база данных, которая была заполнена эта реализация Javascript, хранящаяся в Base64. Теперь я пытаюсь получить метод Objective-C для расшифровки его содержимого, но я немного потерял, где различия в реализациях. Я могу зашифровать/дешифровать в Javascript, и я могу зашифровать/расшифровать в Cocoa, но не могу сделать строку, зашифрованную в Javascript, расшифрованной в Cocoa или наоборот.

Я предполагаю, что это связано с вектором инициализации, nonce, встречным режимом работы или всем этим, что, откровенно говоря, не говорит мне в данный момент.

Здесь то, что я использую в Objective-C, адаптировано в основном из this и this:

@implementation NSString (Crypto)

- (NSString *)encryptAES256:(NSString *)key {
    NSData *input = [self dataUsingEncoding: NSUTF8StringEncoding]; 
    NSData *output = [NSString cryptoAES256:input key:key doEncrypt:TRUE];  
    return [Base64 encode:output];
}

- (NSString *)decryptAES256:(NSString *)key {
    NSData *input = [Base64 decode:self];
    NSData *output = [NSString cryptoAES256:input key:key doEncrypt:FALSE];
    return [[[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding] autorelease];
}

+ (NSData *)cryptoAES256:(NSData *)input key:(NSString *)key doEncrypt:(BOOL)doEncrypt {
    // '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 = [input 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 why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void* buffer = malloc(bufferSize);  
    size_t numBytesCrypted = 0;
    CCCryptorStatus cryptStatus =
        CCCrypt(doEncrypt ? kCCEncrypt : kCCDecrypt,
            kCCAlgorithmAES128,
            kCCOptionECBMode | kCCOptionPKCS7Padding,
            keyPtr, kCCKeySizeAES256,
            nil, // initialization vector (optional)
            [input bytes], dataLength, // input
            buffer, bufferSize, // output
            &numBytesCrypted
        );  
    if (cryptStatus == kCCSuccess) {
        // the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
    }   
    free(buffer); // free the buffer;
    return nil;
}

@end

Конечно, вход Base64 декодирован заранее.

Я вижу, что каждое шифрование с одним и тем же содержимым в Javascript дает другую зашифрованную строку, что не соответствует реализации Objective-C, которая всегда дает ту же зашифрованную строку. Я прочитал ответы этого сообщения, и это заставляет меня думать, что я прав насчет чего-то в соответствии с инициализацией вектора, но мне нужна ваша помощь, чтобы определить, что точно.

Спасибо!

  • 0
    Вы нашли способ заставить двух говорить? Я сталкиваюсь с точно такой же проблемой, но я не могу найти способ сделать эту работу. Любая помощь приветствуется. Благодарю.
  • 0
    @Ipfavreau IPfavreau, я столкнулся с той же проблемой, что и ты. Вы решили это? Спасибо!
Показать ещё 1 комментарий
Теги:
encryption
aes
cocoa

2 ответа

3
Лучший ответ

Yup, существует ряд различий между двумя реализациями.

  • Реализация Javascript использует режим CTR, в то время как реализация Objective-C использует режим ECB (ECB слаб и не должен использоваться.)

  • В реализации Javascript используется расширение ключа. То есть он преобразует ключ перед передачей его в код AES. Не уверен в реализации Objective-C. В любом случае, вы можете почти быть уверены, что две реализации не используют один и тот же ключ для шифрования.

  • Реализация Javascript использует текущее время для генерации 8-байтового IV, который добавляется к зашифрованному тексту. Этот IV используется для инициализации счетчика для режима CTR. Из-за изменений IV, шифрование одного и того же открытого текста приведет к разным зашифрованным текстам. Также использование текущего времени для генерации режима IV для CTR в порядке, если вы не зашифровываете два зашифрованных текста в течение одного такта tick(). Реализация Objective-C не использует IV (поскольку использует режим ECB).

  • В коде Objective-C используется дополнение PKCS # 7, код Javascript не использует его. Это является следствием использования различных режимов шифрования.

  • Кроме того, вам также нужно проверить, как кодируется шифрованный текст. Код Javascript использует кодировку Base64. Код Objective-C слишком много распределен по нескольким сообщениям, что я не нашел соответствующий код.

  • 0
    Я также заметил, что в вашем коде Objective-C написано kCCAlgorithmAES128 , но в вашем тексте говорится, что вы пытаетесь реализовать AES-256. Вы случайно используете блок меньшего размера?
  • 0
    Спасибо за этот хороший ответ. Что касается размера блока, все реализации AES256, которые я видел в Objective-C (с использованием CCCrypt по умолчанию), используют kCCAlgorithmAES128 в качестве размера блока, нет доступного kCCAlgorithmAES256, о котором я знаю. Не разбираясь в криптографии, я не могу сказать, оказывает ли это влияние или это стандартная практика. Что касается кодировки, оба используют Base64 для результирующего зашифрованного текста.
Показать ещё 1 комментарий
0

Для тестирования вам следует использовать тестовые значения из сайта NIST для AES и FIPS 197.

  • 0
    И как мне интерпретировать результаты? Что я узнаю с этими значениями, если я уже знаю, что результирующие зашифрованные строки из обеих реализаций отличаются?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню