我目前正在使用C中的EVP对蛮力强制一些简单文本进行一些测试。

提供了明文,密文,密钥大小,加密方法和方法。我们只需要尝试不同的键,这是一个已知的字典单词。

主要问题是是否要直接从以下方面调用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);
}

最佳答案

您实际上从未将iv设置为任何值。由于iv是局部变量,因此其内容未初始化,随后读取它会导致未定义的行为。

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

iv初始化为全零。然后,您将获得预期的行为。

unsigned char iv[16] = { 0 };

关于c - 实现openssl evp加密,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41917766/

10-12 12:42
查看更多