【问题标题】:Why does aes_128_cbc() work but not aes_128_gcm() for encryption/decryption using EVP?为什么使用 EVP 加密/解密 aes_128_cbc() 有效,但 aes_128_gcm() 无效?
【发布时间】:2018-04-17 06:25:38
【问题描述】:

下面的代码使用aes_128_cbc,它正确地加密了代码,但是当我把它改成aes_128_gcm时,没有输出加密。下面的代码是我原来的工作代码。我的密钥是 128 位(长度 16),而 iv 也是长度 16。

    #include <stdlib.h>
    #include <openssl/evp.h>
    #include <openssl/aes.h>
    #include <string.h>


    EVP_CIPHER_CTX *ctx;
    char key[]="somerandomkey123"; /*length 16*/
    char output[1024];
    char input[]= "Message here.";
    int len;
    FILE *binfile;


    if(!ctx = EVP_CIPHER_CTX_new()){
        (error message)
    }
    if(1 != EVP_EncryptInit_ex(ctx,EVP_aes_128_cbc(),NULL,key,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\")){
        (error message)
    }
    if(1 != EVP_EncryptUpdate(ctx,output,&len,input,strlen(input))){
        (error message)
    }
    if(1 != EVP_EncryptFinal_ex(ctx, output+len, &len)){
        (error message)
    }

    EVP_CIPHER_CTX_free(ctx)

    /*This prints out 0 when I change cbc to gcm, but prints a correct    size when I use cbc*/
    printf("Output size: %d \n", len);

    /*Properly writes to file when cbc used but not when gcm used. Nothing is in encrypted.bin when gcm is used when encrypted text should be there.*/
    binfile = fopen("encrypted.bin","wb");
    fwrite(outbuf,len,1,binfile);

当我将 EVP_aes_128_cbc() 更改为 EVP_aes_128_gcm() 时,代码不再起作用。我还将 iv 更改为长度 12(“\0\0\0\0\0\0\0\0\0\0\0\0”)。最后,我在 EVP_EncryptFinal_ex 之后添加了这个代码块:

    char tag[] = "1234567890123456";

    if(1 != EVP_CIPHER_CTX_ctrl(ctx,EVP_CTRL_GCM_GET_TAG,16,tag)){
        (error message)
    }

打印时我的最终输出大小为 0,其中没有任何内容(在原始代码中注明)。我的问题是为什么我只将 cbc 更改为 gcm 时没有得到任何加密?是由于 key/iv 大小问题还是更大的问题?

【问题讨论】:

  • 您的原始代码不完整。它也有语法错误。而且你没有解释“不起作用”是什么意思?
  • 嘿,对不起。我编辑了我的问题并移动了一些东西,我可能已经删除了一些信息。以上是我完全拥有的代码(可能错过了包含语句),但总的来说这就是我所拥有的。对于 cbc 它可以工作,但是将其更改为 gcm,我的输出缓冲区是空的,最后没有发生加密。我希望这个澄清会有所帮助。
  • AES 加密字节,而不是字符串。如果第一个字节变成0x00,那么strlen 将报告0。不要使用strlen,使用你现有的len 变量。
  • stelen 是错字吗?
  • 哎呀,我修好了。是的,那应该是strlen。如果我将缓冲区输出写入一个名为 encrypted.bin 的文件,则该文件完全为空。我将其添加到问题中以展示这一点。

标签: c authentication encryption openssl aes-gcm


【解决方案1】:

EncryptUpdate 和 EncryptFinal 都添加到输出缓冲区(或不添加)。 碰巧,对于您的短明文消息,在 CBC 模式下,所有输出均由 EncryptFinal 写入,而对于 GCM 模式,所有输出均由 EncryptUpdate 写入。

您的代码中的问题是,您在 EncryptUpdate 和 EncryptFinal 中都重用了“len”变量。他们都(覆盖)通过调用添加的数据量来写入 len 。因此,在 CBC 模式下,EncryptFinal 将初始 0 覆盖为 16,而在 GCM 模式下,初始 13 将被 0 覆盖。

您应该按照 openssl wiki (https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption) 中的说明进行操作:

/* Provide the message to be encrypted, and obtain the encrypted output.
 * EVP_EncryptUpdate can be called multiple times if necessary
 */
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
  handleErrors();
ciphertext_len = len;

/* Finalise the encryption. Further ciphertext bytes may be written at
 * this stage.
 */
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) 
  handleErrors();
ciphertext_len += len;

顺便说一句:您可以继续使用 strlen 作为输入数据的长度,如果它只是文本,但请记住,这不会加密零终止符,因此您必须在解密后手动添加它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 2017-11-08
    • 2015-02-16
    • 2018-06-18
    相关资源
    最近更新 更多