Расшифровка OpenSSL EVP не выполняется для ECB и CBC, но работает для OFB - PullRequest
0 голосов
/ 09 декабря 2018

Для AES-128 с режимом OFB мой код расшифровывается и работает отлично, но для ECB и CBC он просто дает случайный вывод, даже если я использую тот же ключ и тот же IV.

Вот мой код:

#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <stdio.h>
#define BUFFER_SIZE 4096
#define KEY_SIZE 16


int failed = 0;

void print_hex(char *s){
    while(*s){
        printf("%02x" , (unsigned int) *s++);
    }
}

int min(int a , int b){
    return a < b ? a : b;
}

void set_padding(unsigned char* array){
    for(int i= 0 ; i < KEY_SIZE; ++i){
        array[i] = ' ';
    }
}

int handleErrors(void)
{
    // ERR_print_errors_fp(stderr);
    // abort();
    failed = 1;
    return -1;
}

int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
  unsigned char *iv, unsigned char *ciphertext , char* mode)
{
  EVP_CIPHER_CTX *ctx;

  int len;

  int ciphertext_len;

  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

  if(strcmp(mode , "OFB") == 0){
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ofb(), NULL, key, iv))
        handleErrors();
  }
  else{
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
        handleErrors();
  }
  if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
    handleErrors();
  ciphertext_len = len;

  if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
  ciphertext_len += len;

  EVP_CIPHER_CTX_free(ctx);

  return ciphertext_len;
}

int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
  unsigned char *iv, unsigned char *plaintext , char* mode)
{
  EVP_CIPHER_CTX *ctx;

  int len;

  int plaintext_len;

  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

  if(strcmp(mode , "OFB") == 0){
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ofb(), NULL, key, iv))
        handleErrors();
  }
  else{
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
        handleErrors();
  }
  if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
    handleErrors();
  plaintext_len = len;

  if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
  plaintext_len += len;

  EVP_CIPHER_CTX_free(ctx);

  return plaintext_len;
}


void write_to_file(FILE* fd , unsigned char * hash , int size){
    for(int i = 0; i < size; ++i){
        fprintf(fd , "%02x" , hash[i]);
    }
}

void encrypt_and_write(unsigned char *plaintext, int plaintext_len, unsigned char *key,
  unsigned char *iv, char* mode , FILE *fd){
    unsigned char buffer[2 * BUFFER_SIZE];
    int size = 0;
    size = encrypt(plaintext , plaintext_len , key , iv , buffer , mode);
    write_to_file(fd , buffer , size);
}

int main(int argc , char** argv){
    FILE *plain_text , *crypto_text , *dictionary;
    unsigned char plain_text_buffer[BUFFER_SIZE];
    unsigned char crypto_text_buffer[2 * BUFFER_SIZE];
    unsigned int plain_text_size = 0;
    unsigned int crypto_text_size = 0;
    unsigned char iv[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
    unsigned char key[] = "\x73\x65\x63\x69\x6E\x66\x6F\x20\x20\x20\x20\x20\x20\x20\x20\x20";
    memset(plain_text_buffer, 0, sizeof(plain_text_buffer));
    memset(crypto_text_buffer, 0, sizeof(crypto_text_buffer));
    if(argc < 4){
        printf("Wrong number of arguments!\n");
        return 0;
    }
    if(strcmp(argv[3] , "OFB") != 0 && strcmp(argv[3] , "ECB") != 0){
        printf("Use OFB or ECB mode only!\n");
        return 0;
    }
    plain_text = fopen(argv[1] , "r");
    crypto_text = fopen(argv[2] , "r");
    dictionary = fopen("word_dict.txt" , "r");
    char c;
    while((c = fgetc(plain_text)) != EOF){
        plain_text_buffer[plain_text_size] = c;
        ++plain_text_size;
    }
    // encrypt_and_write(plain_text_buffer , plain_text_size , key , iv , argv[3] , crypto_text);
    unsigned int hexa = 0;
    while(fscanf(crypto_text , "%02x" , &hexa) != EOF){
        crypto_text_buffer[crypto_text_size] = hexa;
        ++crypto_text_size;
    }
    char * line = NULL;
    int attempts = 0;
    int len = 0;
    unsigned char decrypt_buffer[BUFFER_SIZE];
    size_t size = 0;
    while(getline(&line , &size , dictionary) != -1){
        set_padding(key);
        for(int i = 0; i < strlen(line); ++i){
            if(line[i] != '\n' && line[i] != '\0'){
                key[i] = line[i];
            }
        }
        key[KEY_SIZE] = '\0';
        decrypt(crypto_text_buffer , crypto_text_size , key , iv , decrypt_buffer , argv[3]);
        if(failed == 0){
            if(strcmp(plain_text_buffer , decrypt_buffer) == 0){
                printf("%i " , attempts);
                print_hex(key);
                printf(" %s" , line);
                break;
            }
            else
                ++attempts;
        }
        else
            ++attempts;
    }
    return 0;
}

Я пытался выяснить, в чем проблема, но не повезло.Он работает даже для DES в режиме OFB, но с ECB и CBC снова выходит из строя.

word_dict.txt - это просто файл, используемый для грубой силы ключа.

1 Ответ

0 голосов
/ 09 декабря 2018

Вы используете EVP_EncryptInit_ex для своих процедур дешифрования;Вы должны использовать EVP_DecryptInit_ex.OFB - это потоковый шифр, что означает, что процедуры шифрования / дешифрования очень похожи.Это не относится к ECB / CBC, потому что они требуют подпрограмм заполнения / распаковки.

Обратите внимание, что вам не следует вставлять / выгружать клавишу.Если вы используете пароль, вы должны использовать хэш пароля, также называемый функцией получения ключа на основе пароля.Поддержка PBKDF2 встроена в OpenSSL.

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