0

I am currently doing some testing on brute forcing some simple text using EVP in C.

The plaintext, ciphertext, key size, encryption method and methodology are provided. We simply need to try different key which is a known dictionary word.

THE MAIN ISSUE IS IF I TRY TO CALL THE EVP METHOD DIRECTLY FROM MAIN LIKE THIS:

int main(int argc, char const *argv[]) {
    evp((unsigned char *)"This is a top secret.");
    return 0;
}

It fails to find the key(cannot generate the same cipher)

But the call with clock(); called:

int main(int argc, char const *argv[])
{
    clock_t begin = clock();
    evp((unsigned char *)"This is a top secret.");
    return 0;
}

It works fine! Why is this happening? What am I doing wrong? Can someone explain what the problem is?

The encryption using aes-128-cbc to encrypt the plaintext, while the iv is 16 bytes NULL and the key is a single dictionary word with the length smaller than 16 and will be feed with empty space when its length is smaller than 16.

The Following code is used to perform the whole process:

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);
}

The add_space method simply feed the key with empty 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;
}

The read_word method read a single word from the dictionary:

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;
}

And the encrypt method is the main process to encrypt the plaintext:

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);
}
4

1 回答 1

0

你从来没有真正设置iv任何东西。因为iv是一个局部变量,它的内容是未初始化的,随后读取它会导致未定义的行为。

调用时可能发生的情况clock是,此函数使用的堆栈空间可能在堆栈的某个位置留下了一些空字节,而这些字节恰好是调用该函数iv时将驻留的位置。encrypt但是,您不能依赖这种行为。

初始化iv为全零。然后你会得到你期望的行为。

unsigned char iv[16] = { 0 };
于 2017-01-29T05:11:08.607 回答