Невозможно найти ключ шифрования aes-128 - PullRequest
0 голосов
/ 07 марта 2020

Я не могу найти никаких ошибок ..

Что я хочу сделать:

  • прочитать ключ (из списка общих слов) из файл
  • попробуйте все возможные ключи для шифрования
  • получите ключ, способный выдавать предпочтительный шифрованный текст

Примечание:

  • encrpytion используйте AES-128-CB C
  • прочитанная клавиша, содержащая менее 16 символов, будет дополнена символом "#" (шестнадцатеричный код: 0x23)
  • правильный список слов

Вот мой код:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/evp.h>

void pad(char *s,int length);
int strcicmp(char const *a, char const *b);

int main(){


    int i;

    char words[16],t;
    FILE *key;
    unsigned char outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
    unsigned char iv[] = {0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};

    int outlen, tmplen;


    EVP_CIPHER_CTX ctx;
    EVP_CIPHER_CTX_init(&ctx);
    char inText[] = "This is a top secret.";
    char cipherTextGiven[] = "764aa26b55a4da654df6b19e4bce00f4ed05e09346fb0e762583cb7da2ac93a2";
    key = fopen("wordList.txt","r");


    while(fgets(words,16, key)) {

        i=strlen(words);
        words[i-1]='\0';
        i=strlen(words);

        if(i<16){
            pad(words,16);
        }
        EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(),NULL, words, iv);
        if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, inText, strlen(inText))){
            EVP_CIPHER_CTX_cleanup(&ctx);
            return 0;
        }
        if(!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen)){
            EVP_CIPHER_CTX_cleanup(&ctx);
            return 0;
        }
        outlen += tmplen;

        int i;
        char* buf_str = (char*) malloc (2*outlen + 1);
        char* buf_ptr = buf_str;
        for(i=0;i<outlen;i++)
            buf_ptr += sprintf(buf_ptr, "%02X", outbuf[i]);

        *(buf_ptr + 1) = '\0';

        printf("%s\n",buf_str);
        if(strcicmp(cipherTextGiven, buf_str) == 0){

            printf("Key: %s\nwith corresponding cipher: ", words);
            for(i=0; i < outlen; i++)
                printf("%02x",outbuf[i]);
            printf("\n");

        }

    }
    fclose(key);

    return 1;
}

//provide padding function to key
void pad(char *s,int length){

    int l;
    l = strlen(s);

    while(l<length){
        s[l] = 0x23;
        l++;
    }
    s[l] = '\0'; //add termination char for the array

}

int strcicmp(char const *a, char const *b){

    for(;;a++,b++){
        int d = tolower(*a) - tolower(*b);
        if(d != 0 || !*a)
            return d;
    }

}

1 Ответ

3 голосов
/ 07 марта 2020

Ошибки

Измените char words[16] на char words[18]. Вам нужно 18 элементов в words, потому что вы хотите обрабатывать ключи длиной до 16 символов, потому что fgets будет читать ключ плюс символ новой строки, а буфер будет содержать нулевой символ после этого.

Изменить fgets(word,16, key) на fgets(word, sizeof word, key). fgets необходимо знать полный размер доступного буфера, включая пространство для символа новой строки и завершающего нулевого символа, а не только количество требуемых ключевых символов.

Удалить *(buf_ptr + 1) = '\0';. Это не нужно, потому что sprintf записывает завершающий нулевой символ и потому что правильное расположение для него будет buf_ptr, а не buf_ptr+1. Таким образом, это утверждение записывается за пределы места, выделенного для buf_str.

Неверный код

Следующий код не вызывает проблем, с которыми вы сталкиваетесь, но он может быть написан лучше.

Объявите main как int main(void) или int main(int argc, char *argv[]), а не int main().

Не пишите s[l] = 0x23;, если только вам не нужно написать программу, которая использует набор символов, отличный от набора символов реализации C, с которой он компилируется и выполняется. Чтобы установить символ «#», используйте s[l] = '#';.

. Если в sprintf(buf_ptr, "%02X", outbuf[i]); вы измените %02X на %02x, тогда он будет использовать нижний регистр для шестнадцатеричного числа, и вы можете использовать стандарт strcmp для сравнения буфера с cipherTextGiven вместо необходимости использования пользовательской функции strcicmp. Еще лучше, когда программа запускается, преобразует cipherTextGiven из шестнадцатеричного в необработанный двоичный файл и, при тестировании ключей-кандидатов, сравнивает этот необработанный двоичный файл с вычисленным текстом шифра, используя memcmp.

В этом:

i=strlen(words);
words[i-1]='\0';
i=strlen(words);

Измените последнюю строку на i = i-1;, потому что мы знаем, что предыдущая строка уменьшила длину на единицу, поэтому мы можем установить длину напрямую, не вызывая strlen снова. Многие программисты пишут эти строки примерно так:

i = strlen(words);
words[--i] = '\0';
...