在C中使用OpenSSL进行AEAD解密

沉默的虚空

我有以下代码来解密一些AEAD加密密码:

int aead_decrypt(char *cipher_password, int len_cipher_password, char *tag, char *key, char *iv, int len_iv, char **plaintext_password) {
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;

    // Cipher_password len always greater or equal to plaintext
    *plaintext_password = (unsigned char *)malloc(len_cipher_password);
    if(*plaintext_password == 0) {
        fprintf(stderr, "malloc() failure\n");
        free(*plaintext_password);
        return -1;
    }

    if(!(ctx = EVP_CIPHER_CTX_new())) {
        fprintf(stderr, "EVP_CIPHER_CTX_new() failure\n");
        ERR_print_errors_fp(stderr);
        return -1;
    }

    if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
        fprintf(stderr, "EVP_DecryptInit_ex() failure\n");
        ERR_print_errors_fp(stderr);
        return -1;
    }

    if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
        fprintf(stderr, "EVP_DecryptInit_ex() failure\n");
        ERR_print_errors_fp(stderr);
        return -1;
    }

    if(!EVP_DecryptUpdate(ctx, *plaintext_password, &len, cipher_password, len_cipher_password)) {
        //if(!EVP_DecryptUpdate(ctx, *plaintext_password, &len, padded_cipher_password, len_padded_cipher_password)) {
        fprintf(stderr, "EVP_DecryptUpdate() failure\n");
        ERR_print_errors_fp(stderr);
        return -1;
    }

    if(1!=EVP_DecryptFinal_ex(ctx, *plaintext_password+len, &len)) {
        fprintf(stderr, "EVP_DecryptFinal_ex() failure\n");
        ERR_print_errors_fp(stderr);
        ERR_print_errors_fp(stdout);
        return -1;
    }

    plaintext_len += len;
    (*plaintext_password)[plaintext_len] = '\0';
    EVP_CIPHER_CTX_free(ctx);

    return 1;
}

我的问题是该EVP_DecryptFinal_ex()功能始终会失败,但不会显示任何错误。我的plaintext_password解密后出来了,但是最后有16个字节的垃圾,因为该EVP_DecryptUpdate()函数没有返回好值plaintext_password_len我以为起初是因为填充,我的cipher_password通常是24-25字节长,所以我尝试添加一些内容,正如我们在不同的注释中看到的那样,但是没有成功。(我也知道我传递了一些我不使用的参数,但这在这里并不重要)。我不知道问题可能在哪里,我也不熟悉OpenSSL库。

沉默的虚空

知道了,我实际上是混淆了aad和tag值。在经过身份验证的加密中,标记值始终会生成(不能为null)。在我的示例中,它是默认大小:16个字节。然后将标记值附加到密码数据。您可以使用它来验证解密的数据。

这是我的固定代码:

int aead_decrypt(char *cipher_password, int len_cipher_password, char *key, char *iv, int len_iv, char **plaintext_password) {
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;

    // The tag is appended at the end of the cipher data
    int tag_offset = len_cipher_password-16;

    // Cipher_password len always greater or equal to plaintext
    *plaintext_password = (unsigned char *)malloc(len_cipher_password);
    if(*plaintext_password == 0) {
            fprintf(stderr, "malloc() failure\n");
            free(*plaintext_password);
            return -1;
    }

    if(!(ctx = EVP_CIPHER_CTX_new())) {
            fprintf(stderr, "EVP_CIPHER_CTX_new() failure\n");
            ERR_print_errors_fp(stderr);
            return -1;
    }

    if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
            fprintf(stderr, "EVP_DecryptInit_ex() failure\n");
            ERR_print_errors_fp(stderr);
            return -1;
    }

    if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
            fprintf(stderr, "EVP_DecryptInit_ex() failure\n");
            ERR_print_errors_fp(stderr);
            return -1;
    }

    // Set the expected tag value for authenticated data
    if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, cipher_password+tag_offset)) {
            fprintf(stderr, "EVP_CIPHER_CTX_ctrl() failure\n");
            ERR_print_errors_fp(stderr);
            return -1;
    }

    if(!EVP_DecryptUpdate(ctx, *plaintext_password, &len, cipher_password, tag_offset)) {
            fprintf(stderr, "EVP_DecryptUpdate() failure\n");
            ERR_print_errors_fp(stderr);
            return -1;
    }

    plaintext_len = len;

    if(1!=EVP_DecryptFinal_ex(ctx, *plaintext_password+len, &len)) {
            fprintf(stderr, "EVP_DecryptFinal_ex() failure\n");
            ERR_print_errors_fp(stderr);
            ERR_print_errors_fp(stdout);
    }

    plaintext_len += len;
    (*plaintext_password)[plaintext_len] = '\0';
    EVP_CIPHER_CTX_free(ctx);

    return 1;}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用 openssl 进行 phpseclib RSA 解密

来自分类Dev

在C#中使用MachineKey进行加密和解密

来自分类Dev

在 C++ 中使用 OpenSSL RSA 函数解密消息时出错

来自分类Dev

使用C语言中的openssl库进行简单的AES加密解密

来自分类Dev

使用OpenSSL Qt,C ++解密DES

来自分类Dev

使用OpenSSL进行AES_128_CBC加密/解密

来自分类Dev

使用openssl C进行AES(AES-IGE-128,AES-IGE-192,AES-IGE-256)加密/解密

来自分类Dev

使用C ++进行加密和解密

来自分类Dev

使用C#进行AES解密

来自分类Dev

OpenSSL中的TripleDES加密和使用C#解密

来自分类Dev

OpenSSL中的TripleDES加密和使用C#解密

来自分类Dev

如何使用openssl EVP解密?

来自分类Dev

无法使用OpenSSL解密AES

来自分类Dev

使用CryptoJS解密openssl AES

来自分类Dev

OpenSSL在C中使用RAW EC生成的密钥进行签名和验证

来自分类Dev

如何使用PyCrypto读取标准的openssl rsa私钥并对其进行解密

来自分类Dev

如何在命令行中通过password参数使用openssl进行解密

来自分类Dev

使用OpenSSL的enc命令进行Unix文件许可和解密

来自分类Dev

使用OpenSSL解密字符串只能在终端中使用,而不能在PHP脚本中使用

来自分类Dev

RNCryptor:使用rncrypt(cli)进行加密,然后在iOS中使用RNDecryptor进行解密

来自分类Dev

无法在C#中使用CryptEncrypt / CryptDecrypt解密

来自分类Dev

使用C#中的证书进行加密和解密

来自分类Dev

使用C#进行SQL Server加密/解密

来自分类Dev

Laravel使用C#进行加密和解密

来自分类Dev

无法使用Scala解密OpenSSL生成的私钥

来自分类Dev

使用OpenSSL rsa密钥解密时出错

来自分类Dev

如何使用OpenSSL解密加密的私钥?

来自分类Dev

如何使用openssl解密加密文件?

来自分类Dev

使用私钥进行Python解密

Related 相关文章

  1. 1

    使用 openssl 进行 phpseclib RSA 解密

  2. 2

    在C#中使用MachineKey进行加密和解密

  3. 3

    在 C++ 中使用 OpenSSL RSA 函数解密消息时出错

  4. 4

    使用C语言中的openssl库进行简单的AES加密解密

  5. 5

    使用OpenSSL Qt,C ++解密DES

  6. 6

    使用OpenSSL进行AES_128_CBC加密/解密

  7. 7

    使用openssl C进行AES(AES-IGE-128,AES-IGE-192,AES-IGE-256)加密/解密

  8. 8

    使用C ++进行加密和解密

  9. 9

    使用C#进行AES解密

  10. 10

    OpenSSL中的TripleDES加密和使用C#解密

  11. 11

    OpenSSL中的TripleDES加密和使用C#解密

  12. 12

    如何使用openssl EVP解密?

  13. 13

    无法使用OpenSSL解密AES

  14. 14

    使用CryptoJS解密openssl AES

  15. 15

    OpenSSL在C中使用RAW EC生成的密钥进行签名和验证

  16. 16

    如何使用PyCrypto读取标准的openssl rsa私钥并对其进行解密

  17. 17

    如何在命令行中通过password参数使用openssl进行解密

  18. 18

    使用OpenSSL的enc命令进行Unix文件许可和解密

  19. 19

    使用OpenSSL解密字符串只能在终端中使用,而不能在PHP脚本中使用

  20. 20

    RNCryptor:使用rncrypt(cli)进行加密,然后在iOS中使用RNDecryptor进行解密

  21. 21

    无法在C#中使用CryptEncrypt / CryptDecrypt解密

  22. 22

    使用C#中的证书进行加密和解密

  23. 23

    使用C#进行SQL Server加密/解密

  24. 24

    Laravel使用C#进行加密和解密

  25. 25

    无法使用Scala解密OpenSSL生成的私钥

  26. 26

    使用OpenSSL rsa密钥解密时出错

  27. 27

    如何使用OpenSSL解密加密的私钥?

  28. 28

    如何使用openssl解密加密文件?

  29. 29

    使用私钥进行Python解密

热门标签

归档