简体   繁体   English

C-使用CBC(密码块链接)模式的OpenSSL加密

[英]C - OpenSSL encryption using CBC (Cipher Block Chaining) mode

I am using C-API of OpenSSL , but I am confused on how IV ( Initialization Vector ) is used in OpenSSL. 我正在使用OpenSSL的 C-API,但是对于在OpenSSL中如何使用IV初始化向量 )感到困惑。

Say, I have 说,我有

plaintext.txt file = "This is a top secret."
Key                = "example#########"
IV                 = 010203040506070809000a0b0c0d0e0f

when I encrypt this using OpenSSL AES-128-CBC , I should get: 当我使用OpenSSL AES-128-CBC对此进行加密时,我应该得到:

e5accdb667e8e569b1b34f423508c15422631198454e104ceb658f5918800c22

Which is true when I try this (key converted to hex): 当我尝试这样做(密钥转换为十六进制)时,这是正确的:

openssl enc -aes-128-cbc -e -in plaintext.txt -out ciphertext.bin 
-K 6578616d706c65232323232323232323 -iv 010203040506070809000a0b0c0d0e0f

I get: 我得到:

xxd -p ciphertext.bin 
e5accdb667e8e569b1b34f423508c15422631198454e104ceb658f5918800c22

But I got different ciphertext thing using C 但是我使用C得到了不同的密文

char plaintext[] = "This is a top secret.";

unsigned char iv[16] = {
    0x01, 0x02, 0x03, 0x04, 
    0x05, 0x06, 0x07, 0x08, 
    0x09, 0x00, 0x0A, 0x0B, 
    0x0C, 0x0D, 0x0E, 0x0F
};

unsigned char ciphertext[] = {
    0xe5, 0xac, 0xcd, 0xb6, 
    0x67, 0xe8, 0xe5, 0x69, 
    0xb1, 0xb3, 0x4f, 0x42, 
    0x35, 0x08, 0xc1, 0x54, 
    0x22, 0x63, 0x11, 0x98, 
    0x45, 0x4e, 0x10, 0x4c, 
    0xeb, 0x65, 0x8f, 0x59, 
    0x18, 0x80, 0x0c, 0x22
};

key (example) is in a words.txt file. 键(示例)在words.txt文件中。


My encryption process: 我的加密过程:

while(fgets(words, 16, wordsfile)) { //for getting key and padding
    index = strlen(words) - 1;       //key "example" is the last word in words.txt
    while(index < 16) {
        words[index] = 0x20;
        index++;
    }
    words[index] = '\0';
    EVP_CIPHER_CTX ctx;
    EVP_CIPHER_CTX_init(&ctx);
    EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, words, iv, 1);
    EVP_CipherUpdate(&ctx, outbuf, &outlen, plaintext, strlen(plaintext));
    EVP_CipherFinal_ex(&ctx, outbuf + outlen, &templ);
    outlen += templ;
    EVP_CIPHER_CTX_cleanup(&ctx);
}

When I check the ciphertext matches to key "example", I got a completely different ciphertext. 当我检查密文与密钥“ example”的匹配时,我得到了完全不同的密文。 Which part I was wrong? 我错了哪一部分? I am assuming the format of IV or the way I implemented IV is wrong. 我认为IV的格式或实现IV的方式是错误的。

It looks like you are pretty close. 看来您已经很接近了。 By narrowing down the problem to just the encryption, the correct ciphertext can be produced. 通过将问题缩小到仅加密,就可以生成正确的密文。 So in stead of reading the key from the file, define it as an array of unsigned chars, similar to what you did for the other variables: 因此,与其从文件中读取密钥,不如将其定义为无符号字符数组,类似于您对其他变量所做的操作:

unsigned char key[]={0x65,0x78,0x61,0x6d,0x70,0x6c,0x65,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23};

Then the following code (reusing your variables) shows the successful encryption: 然后以下代码(重用您的变量)显示加密成功:

EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(),NULL, key, iv, 1);
EVP_CipherUpdate(&ctx, outbuf, &outlen, (unsigned char *)plaintext, strlen(plaintext));
EVP_CipherFinal_ex(&ctx, outbuf+outlen, &templ);
outlen+=templ;
EVP_CIPHER_CTX_cleanup(&ctx);
int cmpres = memcmp(outbuf, ciphertext, sizeof(ciphertext));
printf("cmpres is %d, sizeof(ciphertext) is %lu, outlen is %d\n",
    cmpres, sizeof(ciphertext), outlen);

because it prints 因为它打印

$ ./main
cmpres is 0, sizeof(ciphertext) is 32, outlen is 32

This means that the problem is in how you read the key from the file. 这意味着问题出在如何从文件中读取密钥。 That is much easier to analyze than cryptographic issues :-) and I will leave it up to you to figure out that part... 这比加密问题更容易分析:-),我将由您自己决定这部分...

By the way, make sure to check all return codes for your OpenSSL calls, it will help you to detect error situations. 顺便说一句,请确保检查您的OpenSSL调用的所有返回码,这将帮助您检测错误情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM