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

我正在使用OpenSSL的 C-API,但我对如何在OpenSSL中使用IV ( 初始化向量 )感到困惑。

说,我有

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

当我使用OpenSSL AES-128-CBC加密时,我应该得到:

 e5accdb667e8e569b1b34f423508c15422631198454e104ceb658f5918800c22 

当我尝试这个时(密钥转换为hex),这是真的:

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

我明白了:

 xxd -p ciphertext.bin e5accdb667e8e569b1b34f423508c15422631198454e104ceb658f5918800c22 

但是我用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)位于words.txt文件中。


我的加密过程:

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

当我检查密文匹配键“示例”时,我得到了一个完全不同的密文。 哪一部分我错了? 我假设IV的格式或我实现IV的方式是错误的。

看起来你很近。 通过将问题缩小到仅加密,可以生成正确的密文。 因此,不要从文件中读取密钥,而是将其定义为无符号字符数组,类似于您对其他变量所做的操作:

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

然后,以下代码(重用您的变量)显示成功加密:

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

因为它打印

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

这意味着问题在于您如何从文件中读取密钥。 这比加密问题更容易分析:-)而且我会把它留给你来弄清楚那部分……

顺便说一句,确保检查OpenSSL调用的所有返回代码,它将帮助您检测错误情况。