Реализация шифрования openssl evp
В настоящее время я провожу некоторое тестирование по грубому принуждению с помощью простого EVP на C.
Доступны текст, шифр, размер ключа, метод и метод шифрования. Нам просто нужно попробовать другой ключ, который является известным словарным словом.
ОСНОВНОЙ ВОПРОС - ЭТО, ЕСЛИ Я ПЫТАЮСЬ НАЗВАТЬ МЕТОД EVP, ПРЯМО ИЗ ГЛАВНОГО, КАК ЭТО:
int main(int argc, char const *argv[]) {
evp((unsigned char *)"This is a top secret.");
return 0;
}
Не удается найти ключ (не может сгенерировать тот же шифр)
Но звонок с clock();
называется:
int main(int argc, char const *argv[])
{
clock_t begin = clock();
evp((unsigned char *)"This is a top secret.");
return 0;
}
Работает нормально! Почему это происходит? Что я делаю неправильно? Может кто-нибудь объяснить, в чем проблема?
Шифрование использует aes-128-cbc для шифрования открытого текста, в то время как значение iv равно 16 байтам NULL, а ключ представляет собой одно словарное слово длиной менее 16 и будет заполнено пустым пространством, если его длина меньше 16.
Следующий код используется для выполнения всего процесса:
void evp(unsigned char * plaintext) {
FILE *fp = fopen("words.txt", "r");
const char cipher[] ="8d20e5056a8d24d0462ce74e4904c1b513e10d1df4a2ef2ad4540fae1ca0aaf9";
unsigned char iv[16];
unsigned char ciphertext[256];
/**Init OpenSSL**/
ERR_load_crypto_strings();
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
unsigned char word[17];
while(read_word(fp, word)==0) {
if(strlen((char *)word) < 16) {
add_space(word, sizeof(word));
encrypt(plaintext, strlen((char *)plaintext), word, iv, ciphertext);
if(strcmp((char *)ciphertext, cipher) == 0 ) {
printf("The key is : %s\n", word);
fclose(fp);
exit(0);
};
}
}
fclose(fp);
}
add_space
Метод просто введите ключ с пустым пространством:
int add_space(unsigned char *str, size_t len) {
int eol_pos = strlen((char *)str);
int empty_space = len - eol_pos - 1 ;
//set space and eol
memset(str+eol_pos, ' ', empty_space);
memset(str+len, '\0', 0);
return 0;
}
read_word
Метод чтения одного слова из словаря:
int read_word(FILE *file, unsigned char * word) {
//Using fscanf
unsigned char word_buf[255];
if(fscanf(file, "%s", word_buf) != EOF) {
if( strlen( (char *)word_buf ) < 15 ) {
strcpy((char *)word,(char *) word_buf);
}
return 0;
}
return 1;
}
И encrypt
Метод является основным процессом для шифрования открытого текста:
void encrypt(unsigned char *plaintext, int plain_len ,unsigned char *key, unsigned char * iv, unsigned char * ciphertext) {
EVP_CIPHER_CTX *ctx;
int out_len;
int ciphertext_len;
char *buff;
if(! (ctx = EVP_CIPHER_CTX_new()) ) {
handleErrors();
}
if( EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1 )
handleErrors();
if( EVP_EncryptUpdate(ctx, ciphertext, &out_len, plaintext, plain_len ) != 1 ) {
handleErrors();
}
ciphertext_len = out_len;
if( EVP_EncryptFinal_ex(ctx, ciphertext+out_len, &out_len) != 1 ) {
handleErrors();
}
ciphertext_len += out_len;
EVP_CIPHER_CTX_cleanup(ctx);
buff = malloc(ciphertext_len*2+1);
memset(buff, 0, ciphertext_len*2+1);
for (int i = 0; i < ciphertext_len; ++i)
{
char tmp[3];
sprintf(tmp, "%02x", ciphertext[i]);
strcat(buff, tmp);
}
strcpy((char *)ciphertext, buff);
free(buff);
}
1 ответ
Вы никогда не устанавливаете iv
ни к чему. Так как iv
является локальной переменной, ее содержимое неинициализировано, и последующее чтение приводит к неопределенному поведению.
Что, вероятно, происходит, когда вы звоните clock
является то, что пространство стека, которое использовалось этой функцией, вероятно, оставило несколько нулевых байтов где-то в стеке, что так и происходит, где iv
будет проживать, когда encrypt
функция называется. Вы не можете зависеть от этого поведения, однако.
инициализировать iv
на все нули. Тогда вы получите поведение, которое вы ожидаете.
unsigned char iv[16] = { 0 };