Как зашифровать данные несколькими открытыми ключами с помощью библиотеки openssl - PullRequest
0 голосов
/ 16 мая 2019

У меня есть два открытых ключа, и я использую приведенную ниже команду для шифрования данных с помощью этих двух открытых ключей

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 с помощью их закрытых ключей.

Пожалуйста, помогите мне, как я могу добиться этого, используя функции API openssl.

То есть шифрование данных несколькими ключами.

Эквивалент вышеупомянутой команде.

1 Ответ

1 голос
/ 16 мая 2019

Команда openssl smime -encrypt использует API PKCS7_encrypt для шифрования данных с помощью стека сертификатов.

Вот пример его использования, который воспроизводит указанную выше команду с использованием 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;
}

UPDATE:

API-интерфейс PKCS7_decrypt :

Хотя сертификат получателя не требуется для расшифровки данных необходимо найти подходящее (возможно несколько) получатели в структуре 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:

Существует память BIO , которую можно использовать только для памяти BIO, если вы хотите использовать ее в буферах памяти только с API openssl.

std::vector<char> data;
auto memory_bio = make_handle(BIO_new_mem_buf(data.data(), data.size()), BIO_free);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...