对于具有OFB模式的AES-128,我的代码可以解密并正常工作,但是对于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;
}
我试图找出问题所在,但是没有运气。它甚至适用于OFB模式下的DES,但对于ECB和CBC,它再次失败。
word_dict.txt
只是用于暴力破解密钥的文件。
答案 0 :(得分:2)
您将EVP_EncryptInit_ex
用于解密例程;您应该使用EVP_DecryptInit_ex
。 OFB是流密码,这意味着加密/解密例程非常相似。 ECB / CBC并非如此,因为它们需要填充/去填充例程。
请注意,您不应按键盘上的按键。如果使用密码,则应该使用密码哈希,也称为基于密码的密钥派生功能。 OpenPB内置了对PBKDF2的支持。