Совместимость между двумя алгоритмами AES - PullRequest
1 голос
/ 27 марта 2010

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

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

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

Вот что я использую в Objective-C, адаптированном в основном из этого и этого :

@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's 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, которая всегда дает одну и ту же зашифрованную строку. Я прочитал ответы этого поста , и это заставляет меня поверить, что я прав в отношении чего-то вроде инициализации вектора, но мне нужна ваша помощь, чтобы точно определить, что происходит.

Спасибо!

Ответы [ 2 ]

3 голосов
/ 27 марта 2010

Да, между двумя реализациями есть ряд отличий.

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

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

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

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

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

0 голосов
/ 27 марта 2010

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

...