【问题标题】:C - OpenSSL encryption using CBC (Cipher Block Chaining) modeC - 使用 CBC(密码块链接)模式的 OpenSSL 加密
【发布时间】:2019-03-08 05:30:01
【问题描述】:

我正在使用 OpenSSL 的 C-API,但我对如何在 OpenSSL 中使用 IV (Initialization Vector) 感到困惑。

说,我有

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

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

e5accdb667e8e569b1b34f423508c15422631198454e104ceb658f5918800c22

当我尝试这个时这是真的(密钥转换为十六进制):

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

我明白了:

xxd -p ciphertext.bin 
e5accdb667e8e569b1b34f423508c15422631198454e104ceb658f5918800c22

但我使用 C 得到了不同的 ciphertext 东西

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

密钥(示例)位于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 的方式是错误的。

【问题讨论】:

    标签: c encryption openssl cbc-mode


    【解决方案1】:

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

    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 调用的所有返回码,这将帮助您检测错误情况。

    【讨论】:

      猜你喜欢
      • 2017-08-28
      • 2013-08-11
      • 1970-01-01
      • 2013-12-07
      • 2022-06-11
      • 1970-01-01
      • 2019-08-17
      • 2020-04-15
      • 2019-04-14
      相关资源
      最近更新 更多