C代码加密的文件无法使用OpenSSL解密

qybjjes1  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(153)

这是将文件test.txt加密为test.enc的代码。密钥对key.pemkey.pub是使用openssl生成的:

openssl genrsa -out key.pem
openssl rsa -in key.pem -out key.pub -pubout

个字符
然后使用openssl命令对加密文件进行解密:

openssl rsautl -in test.enc -out test.dec -inkey key.pem -decrypt


然后出现此错误:

RSA operation error
407D290301000000:error:0200009F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error:crypto/rsa/rsa_pk1.c:269:
407D290301000000:error:02000072:rsa routines:rsa_ossl_private_decrypt:padding check failed:crypto/rsa/rsa_ossl.c:499:


似乎有一个问题与填充,但我不知道如何解决它。先谢谢你。

sqxo8psd

sqxo8psd1#

“看起来填充有问题,”--实际上问题是你只做了一半的工作。
EVP_Seal/Open执行混合加密,也称为信封(envelope)加密。这是described almost correctly in wikipedia,但我将重新措辞以匹配OpenSSL实现和我的首选项。
加密由三个步骤和 * 两种不同的 * 加密组成:
1.为对称算法(称为DEK)生成随机数密钥
1.使用RSA和收件人的公钥加密DEK(您必须已经有了,所以这可能被认为是第-1步,但不需要对每个消息重复)
1.使用对称密码(在您的示例中为AES-256-CBC)使用DEK加密数据,有时根据模式随机IV/nonce(CBC使用IV);还取决于模式,这可以另外产生认证标签(CBC不)
加密步骤1和2可以按任意顺序完成,但我相信这种顺序更常见,它肯定是OpenSSL中使用的顺序(SealInit执行0和1,SealUpdateSealFinal一起执行2)。

解密需要步骤1和步骤2生成的所有2-4个数据项:RSA加密-DEK、IV(如果适用)、加密数据和标签(如果适用)。在真实的系统中,存在将这些数据项打包的数据结构,以及附加的元数据:维基百科提到PKCS 7(现在被CMS及其变体SMIME取代)和PGP;还有JOSE/JWE、XMLenc等。解密同样需要 * 两个步骤 *:

1.使用RSA和本地已知的私钥解密传输的加密DEK
1.使用相同的对称算法、解密的DEK、如果适用的话发送的IV/nonce以及如果适用的话发送的标签来解密发送的加密数据
(and这一次你必须按这个顺序做)。
但是,要使用OpenSSL命令行 * 解密 *,您需要将这些项放在单独的文件中(除了用于身份验证模式的标记,enc命令行根本无法处理)。因此,我修改了你的程序,将加密的DEK,IV和密文写入3个文件,并稍微重构以减少混乱,更改文件名以避免冲突,并添加最小的错误处理:

// SO76696165
#include <stdio.h>
#include <stdlib.h>

//#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>

#define BUFFER_SIZE 1024

static int evp_aes_encrypt(FILE *fin, FILE *fek, FILE *fiv, FILE *fenc, EVP_PKEY *pkey)
{
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    if (!ctx) return -1;

    unsigned char iv[EVP_MAX_IV_LENGTH];
    unsigned char* ek = malloc(EVP_PKEY_get_size(pkey));
    int ekl, ivl;

    if (EVP_SealInit(ctx, EVP_aes_256_cbc(), &ek, &ekl, iv, &pkey, 1) != 1)
    { EVP_CIPHER_CTX_free(ctx); free(ek); return -2; }
    ivl = 16; // or EVP_CIPHER_CTX_get_iv_length(EVP_aes_256_cbc());
    fwrite (ek,ekl,1,fek); fwrite (iv,ivl,1,fiv);

    unsigned char in_buffer[BUFFER_SIZE];
    unsigned char out_buffer[BUFFER_SIZE + EVP_MAX_IV_LENGTH];
    // actually this only needs + cipher_blocksize, but bytes are cheap now

    int bytes_read, bytes_written;
    while ((bytes_read = fread(in_buffer, 1, BUFFER_SIZE, fin)) > 0)
    {
        if (EVP_SealUpdate(ctx, out_buffer, &bytes_written, in_buffer, bytes_read) != 1) {
            EVP_CIPHER_CTX_free(ctx); free(ek); return -3; }
        fwrite(out_buffer, 1, bytes_written, fenc);
    }

    if (EVP_SealFinal(ctx, out_buffer, &bytes_written) != 1) {
        EVP_CIPHER_CTX_free(ctx); free(ek); return -4; }

    fwrite(out_buffer, 1, bytes_written, fenc);
    EVP_CIPHER_CTX_free(ctx); free(ek); 
    return 0;
}

int main(void)
{
    FILE *pub = fopen("76696165.pub", "rb");
    EVP_PKEY *pkey = PEM_read_PUBKEY(pub, NULL, NULL, NULL);
    FILE *fin = fopen("76696165.in", "rb");
    FILE *fek = fopen("76696165.ek", "wb");
    FILE *fiv = fopen("76696165.iv", "wb");
    FILE *fenc = fopen("76696165.enc", "wb");
    int err = evp_aes_encrypt(fin, fek, fiv, fenc, pkey);
    if( err ){ printf ("error in step %d\n", err);
        ERR_print_errors_fp(stdout); return 1; }
    // fclose not needed when exiting normally
    return 0;
}

字符串
在运行这个之后,我有:

$ ls -rt1 76696165*
76696165.pub
76696165.prv
76696165.c
76696165.exe
76696165.in
76696165.iv
76696165.enc
76696165.ek
$ # STEP 1
$ openssl rsautl -decrypt -inkey 76696165.prv <76696165.ek >76696165.dek
$ xxd 76696165.dek; xxd 76696165.iv
0000000: a46e 5084 e28b 8f9c 7fe3 a465 fbeb 4ed7  .nP........e..N.
0000010: 7c4b 38f5 3174 f905 3034 52df d992 da3d  |K8.1t..04R....=
0000000: 959b a611 3fbb 5486 b6c6 2056 f9ee 6f03  ....?.T... V..o.
$ # STEP 2
$ keyhex=$(xxd -p -c32 <76696165.dek) ivhex=$(xxd -p <76696165.iv) 
$ openssl enc -aes-256-cbc -d -K $keyhex -iv $ivhex <76696165.enc
Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore—
While I nodded, nearly napping, suddenly there came a tapping,
As of some one gently rapping, rapping at my chamber door.
"'Tis some visiter," I muttered, "tapping at my chamber door—
            Only this and nothing more."
-- Edgar Allan Poe

相关问题