【问题标题】:How to encrypt data with multi public keys using openssl library如何使用 openssl 库使用多个公钥加密数据
【发布时间】:2019-10-03 12:27:53
【问题描述】:

我有两个公钥,我使用下面的命令用这两个公钥加密数据

openssl smime -encrypt -binary -aes256 -in secret.txt -out secret_multi.enc -outform PEM alice.pub bob.pub

所以基本上使用 alice.pub 和 bob.pub 我可以用他们的私钥解密数据 secret_multi.enc。

请帮助我如何使用 openssl API 函数来实现这一点。

即使用多个密钥对数据进行加密。

相当于我上面提到的命令。

【问题讨论】:

    标签: openssl


    【解决方案1】:

    openssl smime -encrypt 命令使用PKCS7_encrypt API 使用证书堆栈加密数据。

    这是一个使用它的示例,它使用 C API 的 C++ 使用重现上述命令。

    template<typename T, typename D>
    std::unique_ptr<T, D> make_handle(T* handle, D deleter)
    {
        return std::unique_ptr<T, D>{handle, deleter};
    }
    
    bool encrypt_data()
    {
        // load the stack of certificates
        auto const encrypt_certificate_stack = make_handle(sk_X509_new_null(), [](auto handle){ sk_X509_pop_free(handle, X509_free); });
        if(!encrypt_certificate_stack) return false;
    
        auto file = make_handle(BIO_new_file("alice.pem", "r"), BIO_free);
        auto cert = PEM_read_bio_X509(file.get(), nullptr, nullptr, nullptr);
        if(!cert) return false;
        sk_X509_push(encrypt_certificate_stack.get(), cert);
    
        file = make_handle(BIO_new_file("bob.pem", "r"), BIO_free);
        cert = PEM_read_bio_X509(file.get(), nullptr, nullptr, nullptr);
        if(!cert) return false;
        sk_X509_push(encrypt_certificate_stack.get(), cert);
    
        // input file
        auto const infile = make_handle(BIO_new_file("secret.txt", "rb"), BIO_free);
        if(!infile) return false;
    
        // encrypt
        auto const flags = PKCS7_DETACHED | PKCS7_BINARY;
        auto const p7 = make_handle(PKCS7_encrypt(encrypt_certificate_stack.get(), infile.get(), EVP_aes_256_cbc(), flags), PKCS7_free);
        if(!p7) return false;
    
        // write the output file as PEM format
        auto const outfile = make_handle(BIO_new_file("secret.out.pem", "w"), BIO_free);
        if(!outfile) return false;
        if(PEM_write_bio_PKCS7_stream(outfile.get(), p7.get(), infile.get(), flags) == 0) return false;
    
        return true;
    }
    

    更新:

    PKCS7_decrypt API 声明:

    虽然解密数据不需要收件人证书 需要找到合适的(可能的几个) PKCS#7 结构中的接收者。

    意味着证书是可选的,因此您可以将 nullptr 传递给该参数,它在您的简单示例中可以正常工作。

    如果您确实传递了证书,它会将证书与私钥匹配,如果失败,解密将失败。

    所以没有证书的解密代码如下所示:

    bool decrypt_data()
    {
        // read in private key
        auto file = make_handle(BIO_new_file("aliceprivatekey.pem", "r"), BIO_free);
        auto const key = make_handle(PEM_read_bio_PrivateKey(file.get(), nullptr, nullptr, (void*)"password"), EVP_PKEY_free);
        file.reset();
        if(!key) return false;
    
        // read in PKCS7 data
        auto infile = make_handle(BIO_new_file("secret.out.pem", "rb"), BIO_free);
        if(!infile) return false;
    
        auto const p7 = make_handle(PEM_read_bio_PKCS7(infile.get(), nullptr, nullptr, nullptr), PKCS7_free);
        if (!p7) return false;
        infile.reset();
    
        // decrypt and write to stdout
        auto const out = BIO_new_fp(stdout, BIO_NOCLOSE);
        auto const flags = PKCS7_DETACHED;
        return PKCS7_decrypt(p7.get(), key.get(), nullptr, out, flags) != 0;
    }
    

    更新 2:

    如果您只想通过 openssl API 在内存缓冲区中使用,则有一个 memory BIO 可用于仅内存 BIO。

    std::vector<char> data;
    auto memory_bio = make_handle(BIO_new_mem_buf(data.data(), data.size()), BIO_free);
    

    【讨论】:

    • 谢谢。另外我想如何仅使用私钥解密数据?我看到用于解密的 API 需要私钥和公钥(证书),但我只需要使用私钥解密这可能吗? int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags);
    • 谢谢。另外我想如何仅使用私钥解密数据?我看到用于解密的 API 需要私钥和公钥(证书),但我只需要使用私钥解密这可能吗? int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags); openssl smime -decrypt -in secret_single.enc -inform PEM -inkey alice.key 以上命令我需要执行但没有公钥
    • 这些所有示例都适用于文件选项假设如果我有像 vector 纯文本这样的流数据,那么我需要先用这些数据创建一个文件来获取 BIO* 或那里有什么直接的方法可以从 vector plaintext 获取 BIO * 吗?
    • 添加了内存生物示例。
    • 有没有办法从 BIO 读取数据。我看到了 BIOS_read() 但它需要复制缓冲区长度,但我怎么知道我需要复制的字节,因为数据将在 BIO 结构中
    猜你喜欢
    • 2020-03-15
    • 2014-07-01
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 2022-10-22
    • 2020-02-28
    • 1970-01-01
    相关资源
    最近更新 更多