0

I have one ciphertext, iv and a dictionary file including passwords, one of them has been used to derive a key for the decryption. Here is the C code using the brute force method. What problem I am facing is it's giving me many decrypted text which is unreadable. I don't understand what is the problem.
here is the inputs and the method:

  • Ciphertext (in hex format. 32 bytes): 42296c688fbb3172ad74b3be52f74511031d3bdbd6359308f0e262cbe8609dc6
  • IV (in hex format. 16 bytes): 00112233445566778899aabbccddeeff
  • The aes-128-cbc cipher is used for the encryption
  • The password used to encrypt the plaintext is an English word
  • The length of the plaintext is 21 bytes (ASCII code) and PKCS#5 padding is used (Hint. So, the padding will be 11 bytes of 0x0b)

What I have tried:

Using this KeyDerive function I have generated key for all passwords in the dictionary file("words.txt")and all of the generated keys I have used in decrypt function. Now the problem is: for one of the generated keys the decryption should work!! But here I am getting lots of unreadable/garbage strings as decrypted !!

#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;
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
tanni
  • 3
  • 4
  • Are you using _string_ (null terminated char array) techniques to work with `unsigned char` arrays, and visa versa? – ryyker Feb 14 '20 at 19:24
  • @ryyker What do you mean? I didn't get your answer. I am here decrypting a given ciphertext not encrypting ... – tanni Feb 14 '20 at 19:25
  • That was a question, not an answer. I was asking if it is possible that at some point in your opening and closing files to read data that you are handling binary data as you would handle text data, or strings, or is it possible that you are handling string data, i.e. from a text file as you would handle binary data. It would not be the first time I have seen that happen, but I am not sure from what you have shown if you are indeed doing that. If you are doing either, it would explain the mangled results you describe. – ryyker Feb 14 '20 at 19:33

0 Answers0