如何使用openssl库使用多个公共密钥加密数据

时间:2019-05-16 09:13:17

标签: openssl

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

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函数实现此目标。

即使用多个密钥加密数据。

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

1 个答案:

答案 0 :(得分: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);