121 lines
3.4 KiB
C++
121 lines
3.4 KiB
C++
#include "RsaPrivateKey.hpp"
|
|
|
|
#include <openssl/rsa.h>
|
|
#include <openssl/evp.h>
|
|
#include <openssl/x509.h>
|
|
|
|
#include "utils/serialize/basics.hpp"
|
|
|
|
|
|
namespace drp::util::crypto {
|
|
|
|
|
|
RsaPrivateKey::RsaPrivateKey() = default;
|
|
|
|
RsaPrivateKey::RsaPrivateKey(const std::vector<std::uint8_t>& data, const int padMode) {
|
|
this->_data = data;
|
|
this->padMode = padMode;
|
|
}
|
|
|
|
|
|
std::vector<std::uint8_t> RsaPrivateKey::decrypt(const std::vector<std::uint8_t>& encryptedData) const {
|
|
const auto key = this->getOpenSslKey();
|
|
|
|
// initialize the encryption context
|
|
const std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> context(
|
|
EVP_PKEY_CTX_new(key.get(), nullptr),
|
|
EVP_PKEY_CTX_free
|
|
);
|
|
|
|
if (context == nullptr)
|
|
throw std::runtime_error("Could not create EVP_PKEY_CTX.");
|
|
|
|
// initialize the encryption operation
|
|
if (EVP_PKEY_decrypt_init(context.get()) <= 0)
|
|
throw std::runtime_error("Could not initialize encryption.");
|
|
|
|
// set the padding
|
|
if (EVP_PKEY_CTX_set_rsa_padding(context.get(), RSA_PKCS1_OAEP_PADDING) <= 0)
|
|
throw std::runtime_error("Could not set RSA padding.");
|
|
|
|
// get the size of the output buffer
|
|
std::size_t decryptedDataLength;
|
|
if (EVP_PKEY_decrypt(
|
|
context.get(),
|
|
nullptr,
|
|
&decryptedDataLength,
|
|
encryptedData.data(),
|
|
encryptedData.size()
|
|
) <= 0)
|
|
throw std::runtime_error("Could not determine output length.");
|
|
|
|
std::vector<std::uint8_t> decryptedData(decryptedDataLength);
|
|
|
|
// encrypt the data
|
|
if (EVP_PKEY_decrypt(
|
|
context.get(),
|
|
decryptedData.data(),
|
|
&decryptedDataLength,
|
|
encryptedData.data(),
|
|
encryptedData.size()
|
|
) <= 0)
|
|
throw std::runtime_error("Could not decrypt data.");
|
|
|
|
decryptedData.resize(decryptedDataLength);
|
|
|
|
return decryptedData;
|
|
}
|
|
|
|
|
|
std::vector<std::uint8_t> RsaPrivateKey::serialize() const {
|
|
// serialize the members
|
|
const auto serializedData = serialize::serializeVector(this->_data);
|
|
const auto serializedPadMode = serialize::serializeObject(static_cast<std::uint8_t>(this->padMode));
|
|
|
|
// create a buffer to store our members
|
|
std::vector<std::uint8_t> data;
|
|
|
|
// store our members
|
|
data.insert(data.end(), serializedData.begin(), serializedData.end());
|
|
data.insert(data.end(), serializedPadMode.begin(), serializedPadMode.end());
|
|
|
|
return data;
|
|
}
|
|
|
|
RsaPrivateKey RsaPrivateKey::deserialize(std::vector<std::uint8_t>& data) {
|
|
// deserialize the members
|
|
const auto keyData = serialize::deserializeVector<std::uint8_t>(data);
|
|
const auto keyPadding = static_cast<int>(serialize::deserializeObject<std::uint8_t>(data));
|
|
|
|
return RsaPrivateKey(keyData, keyPadding);
|
|
}
|
|
|
|
|
|
[[nodiscard]] std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> RsaPrivateKey::getOpenSslKey() const {
|
|
// get the bio from the private key data
|
|
const std::unique_ptr<BIO, decltype(&BIO_free)> bio(
|
|
BIO_new_mem_buf(
|
|
this->_data.data(),
|
|
static_cast<int>(this->_data.size())
|
|
),
|
|
BIO_free
|
|
);
|
|
if (bio == nullptr)
|
|
throw std::runtime_error("Could not create BIO for private key.");
|
|
|
|
// get the key from the bio
|
|
EVP_PKEY* rawKey = nullptr;
|
|
if (!d2i_PrivateKey_bio(
|
|
bio.get(),
|
|
&rawKey
|
|
))
|
|
throw std::runtime_error("Could not deserialize RSA private key.");
|
|
|
|
return {
|
|
rawKey,
|
|
EVP_PKEY_free
|
|
};
|
|
}
|
|
|
|
|
|
}
|