C возвращает нечитаемую строку при расшифровке сообщения в режиме openssl aes-128-cb c - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть один зашифрованный текст, iv и файл словаря, включающий пароли, один из которых использовался для получения ключа для расшифровки. Вот код C, использующий метод грубой силы. Проблема, с которой я сталкиваюсь, заключается в том, что она дает мне много расшифрованного текста, который невозможно прочитать. Я не понимаю, в чем проблема.
вот входные данные и метод:

  • зашифрованный текст (в шестнадцатеричном формате. 32 байта): 42296c688fbb3172ad74b3be52f74511031d3bdbd6359308f0e262cbe8609dc6 * 1008 (in6) 100 шестнадцатеричный формат. 16 байт): 00112233445566778899aabbccddeeff
  • Шифр ​​aes-128-cb c используется для шифрования
  • Пароль, используемый для шифрования открытого текста, - это английское sh слово
  • Длина открытого текста составляет 21 байт (код ASCII) и используется заполнение PKCS # 5 (Подсказка. Таким образом, заполнение будет 11 байтов 0x0b)

Что у меня есть попробовал:

Используя эту функцию KeyDerive Я сгенерировал ключ для всех паролей в файле словаря ("words.txt") и всех сгенерированных ключей, которые я использовал в расшифровать функция. Теперь проблема в том, что для одного из сгенерированных ключей расшифровка должна работать !! Но здесь я получаю много нечитаемых / мусорных строк как расшифрованных !!

#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>

int  KeyDerive(char * password, const char * cipher_name, const char * digest_name, unsigned char *key)
{
    const EVP_CIPHER *cipher;
    const EVP_MD *dgst;
    unsigned char derived_key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
    unsigned char *salt = NULL;
    int key_size;

    OpenSSL_add_all_algorithms();

    cipher = EVP_get_cipherbyname(cipher_name);
    if(!cipher) { fprintf(stderr, "no such cipher\n"); return 0; }

    dgst = EVP_get_digestbyname(digest_name);
    if(!dgst) { fprintf(stderr, "no such digest\n"); return 0; }

    if(!(key_size=EVP_BytesToKey(cipher,dgst, salt,
    (unsigned char *)password, strlen(password), 1, derived_key, iv))){
        fprintf(stderr, "EVP_BytesToKey failed\n");
        return 0;
    }
    memcpy(key, derived_key, key_size);

    return 1;
}

void handleErrors(void)
{
    ERR_print_errors_fp(stderr);
    //abort();
}

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

    int len, flag, plaintext_len;

    /* Create and initialise the context */
    if(!(ctx = EVP_CIPHER_CTX_new()))
    {
        printf("err inside EVP_CIPHER_CTX_new");
        handleErrors();
    }

    /*
    * Initialise the decryption operation. IMPORTANT - ensure you use a key
    * and IV size appropriate for your cipher
    * In this example we are using 256 bit AES (i.e. a 256 bit key). The
    * IV size for *most* modes is the same as the block size. For AES this
    * is 128 bits
    */
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
    {
        printf("err inside EVP_DecryptInit_ex");
        handleErrors();
    }
    //EVP_CIPHER_CTX_set_padding(ctx,1);
    /*
    * Provide the message to be decrypted, and obtain the plaintext output.
    * EVP_DecryptUpdate can be called multiple times if necessary.
    */
    if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
    {
        printf("err inside EVP_DecryptUpdate");
        handleErrors();
    }
    plaintext_len = len;

    /*
    * Finalise the decryption. Further plaintext bytes may be written at
    * this stage.
    */
    if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
    {
        //printf("\nerr inside EVP_DecryptFinal_ex\n");

        //handleErrors();
        return -2;
    }
    else
    {
        plaintext_len += len;

        /* Clean up */
        EVP_CIPHER_CTX_free(ctx);
        return plaintext_len;
    }
}

int main (void)
{
    char line[256];//each line assuming password in file
    char keystring[256];//each line assuming key in file
    const char * cipher_name = "aes-128-cbc";
    const char * digest_name = "md5";
    const int key_len = 16;//deriving key len
    unsigned char key[key_len];

    unsigned char ciphertext[32] =
    {0x42,0x29,0x6C,0x68,0x8f,0xbb,0x31,0x72,0xad,0x74,0xb3,0xbe,0x52,0xf7,0x45,0x11,0x03,0x1d,0x3b,
    0xdb,0xd6,0x35,0x93,0x08,0xf0,0xe2,0x62,0xcb,0xe8,0x60,0x9d,0xc6};


    unsigned char iv[16] =
    {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};

    int decryptedtext_len;
    unsigned char decryptedtext[32];

    FILE *fptr,*fp,*fp_decrypt;
    fptr = fopen("words.txt","r");
    fp = fopen("keylist.txt", "w+");
    fp_decrypt = fopen("decryptlist.txt", "wb+");
    if(fptr == NULL){
        printf("Error! opening file");
        // Program exits if the file pointer returns NULL.
        exit(1);
    }
    if(fp == NULL){
        printf("Error! opening file");
        // Program exits if the file pointer returns NULL.
        exit(1);
    }

    int i = 1;
    while (fgets(line, sizeof(line), fptr))
    {
        line[strcspn(line, "\n")] = 0; // removing newline if one is found
        printf("for line %d guessed pwd is: %s \n",i,line);
        printf("for line %d key is :",i);
        if(!KeyDerive(line, cipher_name, digest_name, key)){
            fprintf(stderr, "key derivation failed\n");
            return 0;
        }
        i++;

        for (int j=0; j<key_len; j++){
            fprintf(fp,"%02x",key[j] );//store hex key in a file
            printf("%02x", key[j]);
        }

        fprintf(fp,"\n");
        printf("\n");
    }

    fclose(fptr);
    fclose(fp);

    fp = fopen("keylist.txt", "r");
    while (fgets(keystring, sizeof(keystring), fp))
    {
        keystring[strcspn(keystring, "\n")] = 0; // removing newline if one is found
        printf("%s\n", keystring);
        decryptedtext_len = decrypt(ciphertext, 32, keystring, iv,decryptedtext);
        if(decryptedtext_len==-2)
        {
            continue;
        }
        // decryptedtext[decryptedtext_len] = '\0';
        fprintf(fp_decrypt,"%s",decryptedtext);
        fprintf(fp_decrypt,"\n");
        //printf("Decrypted text is :\n");
        // printf("%s\n", decryptedtext);
    }

    fclose(fp_decrypt);

    return 0;
}
...