2013-08-17 2 views
4

Я знаю, что когда я использую режим CBC с Openssl, я могу указать в качестве ввода, который кратен размеру блока. Но как насчет других режимов? ECB, CFB, OFB? Я видел doc, но мне не все понятно. Должен ли я звонить им в цикле?Режимы шифрования ECB, CFB, OFB в Openssl

Скажем, ECB. Он шифрует 64 бита за раз. Итак, псевдокод будет выглядеть так (должен выглядеть так)?

int len = 512, c = 0; 
unsigned char in[len], out[len]; 
while(c < len) 
{ 
    Aes_ecb_encrypt(in+c, out+c, &enckey, AES_ENCRYPT); 
    c += 8; 
} 

Но с приведенным выше кодом он не является эффективным. Когда я меняю c += 8; на c += 16;, тогда это нормально. Каков хороший способ сделать это? Я имею в виду, что все мы знаем, что 8x8 = 64 бит, поэтому это должно быть правильно, но это не так, шифрование/дешифрование работает только тогда, когда у меня есть c += 16;.

Как насчет других режимов шифрования?

Пример для режима ECB (заметьте, что речь идет также о других режимах тоже;)):

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <openssl/aes.h> 
#include <openssl/rand.h> 

// a simple hex-print routine. could be modified to print 16 bytes-per-line 
static void hex_print(const void* pv, size_t len) 
{ 
    const unsigned char * p = (const unsigned char*)pv; 
    if (NULL == pv) 
     printf("NULL"); 
    else 
    { 
     size_t i = 0; 
     for (; i<len;++i) 
      printf("%02X ", *p++); 
    } 
    printf("\n"); 
} 

// main entrypoint 
int main(int argc, char **argv) 
{ 
    int keylength = 256; 
    unsigned char aes_key[keylength/8]; 
    memset(aes_key, 0, keylength/8); 
    if (!RAND_bytes(aes_key, keylength/8)) 
     exit(-1); 

    size_t inputslength = 0; 
    printf("Give an input's length:\n"); 
    scanf("%lu", &inputslength); 

    /* generate input with a given length */ 
    unsigned char aes_input[inputslength]; 
    memset(aes_input, 'X', inputslength); 

    // buffers for encryption and decryption 
    const size_t encslength = ((inputslength + AES_BLOCK_SIZE)/AES_BLOCK_SIZE) * AES_BLOCK_SIZE; 

    unsigned char paddedinput[encslength]; 
    memset(paddedinput, 0, encslength); 
    memcpy(paddedinput, aes_input, inputslength); 

    unsigned char enc_out[encslength]; 
    unsigned char dec_out[inputslength]; 
    memset(enc_out, 0, sizeof(enc_out)); 
    memset(dec_out, 0, sizeof(dec_out)); 

    AES_KEY enc_key, dec_key; 
    AES_set_encrypt_key(aes_key, keylength, &enc_key); 

    long c = 0; 
    while(c < encslength) 
    { 
     AES_ecb_encrypt(paddedinput+c, enc_out+c, &enc_key, AES_ENCRYPT); 
     c += 8; 
    } 

    c = 0; 
    AES_set_decrypt_key(aes_key, keylength, &dec_key); 
    while(c < encslength) 
    { 
     AES_ecb_encrypt(enc_out+c, dec_out+c, &dec_key, AES_DECRYPT); 
     c += 8; 
    } 

    printf("original:\t"); 
    hex_print(aes_input, sizeof(aes_input)); 

    printf("encrypt:\t"); 
    hex_print(enc_out, sizeof(enc_out)); 

    printf("decrypt:\t"); 
    hex_print(dec_out, sizeof(dec_out)); 

    return 0; 
} 
+1

Все режимы AES будут шифроваться в кратных размерах блока. Как эти блоки используются во время процесса шифрования, основное различие между режимами. Заполнение также входит в игру (и ваш ввод должен быть точным кратным размером блока, если заполнение не используется, если оно * используется *, в зависимости от размера ввода может быть сгенерирован до одного полного дополнительного размера блока выходных данных) , Вы сказали: «Но с приведенным выше кодом это не помогает». Ну, «выше» код ничего не делает * ничего, потому что это не настоящий код. Принесите [SSCCE] (http://www.sscce.org), и мы сможем работать с ним. – WhozCraig

+0

@WhozCraig: Спасибо. Я привел здесь AES только в качестве примера, я спрашиваю о всех других блочных шифрах. Наложенное «SSCCE» I работает только тогда, когда я меняю 'c + = 8;' на 'c + = 16;'. Должен ли я использовать * такой же * цикл для других режимов шифрования? (Думаю, мне придется изменить только часть с 'c + = ...;' и вызвать соответствующий режим функции, верно?) – ivy

+1

Хех. Я * написал * этот пример, который вы цитируете в [этом вопросе] (http://stackoverflow.com/questions/18152913/aes-aes-cbc-128-aes-cbc-192-aes-cbc-256-encryption-decryption- с-OpenSSL-с). Однако это было несколько специфично для этого вопроса ОП. Пока блок данных, который вы шифруете, является смежным, вам не нужно полностью петлю * *. Просто зашифруйте его. – WhozCraig

ответ

3

Позволяет сказать, ЕЦБ. Он шифрует 64 бита за раз

AES - это 128-битный блочный шифр. Он шифрует/расшифровывает 128-битное за раз. Это стандарт. Блок AES_encrypt/AES_decrypt ожидает 128 бит или 16 байтов длины входных и выходных данных.

Но с вышеприведенным кодом он не является эффективным. Когда я меняю с + = 8; в c + = 16; это нормально. Каков хороший способ сделать это? Я имею в виду, мы все знаем, что 8x8 = 64 бит, поэтому это должно быть правильно, но это не так, шифрование/дешифрование работает только тогда, когда у меня есть c + = 16;

Вот почему он работает отлично на

с + = 16

Помимо этого, есть несколько проблем в вашем коде.

unsigned char enc_out[encslength]; 

Пожалуйста держите размер dec_out из encslength, так как вы дешифрование encslength байт не inputslength в вашем коде.

unsigned char dec_out[encslength]; 
memset(enc_out, 0, sizeof(enc_out)); 
memset(dec_out, 0, sizeof(dec_out)); 

AES_KEY enc_key, dec_key; 
AES_set_encrypt_key(aes_key, keylength, &enc_key); 

В этом разделе увеличьте c на 16, поскольку AES - 128-разрядный шифр.

long c = 0; 
while(c < encslength) 
{ 
    AES_ecb_encrypt(paddedinput+c, enc_out+c, &enc_key, AES_ENCRYPT); 
    c += 16; 
} 

Похожие изменения здесь:

c = 0; 
AES_set_decrypt_key(aes_key, keylength, &dec_key); 
while(c < encslength) 
{ 
    AES_ecb_encrypt(enc_out+c, dec_out+c, &dec_key, AES_DECRYPT); 
    c += 16; 
} 

О других режимах:

  1. режим CFB Там нет необходимости раздуть данные. Используйте AES_cfb128_encrypt и вектор инициализации (IV) вместе с ключом.

Для шифрования:

AES_cfb128_encrypt (paddedinput, enc_out, inputlength, &enc_key, iv, AES_ENCRYPT); 

Для дешифрования:

AES_cfb128_decrypt (enc_out, dec_out, inputlength, &enc_key, iv, AES_ENCRYPT); 
  1. Режим OFB Аналогично в режиме OFB, нет никакой необходимости, чтобы дополнить данные. Используйте AES_ofb128_encrypt и IV вместе с ключом.

Для шифрования:

//Initialize num to 0. 
num = 0; 
AES_ofb128_encrypt (paddedinput, enc_out, inputlength, &enc_key, iv, &num); 

Для дешифрования:

num = 0; 
AES_ofb128_encrypt (enc_out, dec_out, inputlength, &enc_key, iv, &num); 

Вы, возможно, потребуется настроить код некоторый бит в соответствии с вашими потребностями.

Подробнее о block cipher mode of operation.

Смежные вопросы