98 lines
2.8 KiB
C++
98 lines
2.8 KiB
C++
#include "RsaKeyPair.hpp"
|
|
|
|
#include <openssl/x509.h>
|
|
|
|
|
|
namespace drp::util::crypto {
|
|
|
|
|
|
RsaKeyPair::RsaKeyPair(const std::size_t size, const int padMode) {
|
|
// create the context
|
|
const std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> context(
|
|
EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr),
|
|
EVP_PKEY_CTX_free
|
|
);
|
|
|
|
if (context == nullptr)
|
|
throw std::runtime_error("Could not create an EVP context.");
|
|
|
|
if (EVP_PKEY_keygen_init(context.get()) <= 0)
|
|
throw std::runtime_error("Could not initialize the EVP context.");
|
|
|
|
// configure the context
|
|
if (EVP_PKEY_CTX_set_rsa_keygen_bits(context.get(), static_cast<int>(size)) <= 0)
|
|
throw std::runtime_error("Error setting RSA key size.");
|
|
|
|
// create the key pair
|
|
EVP_PKEY* rawKeyPair = nullptr;
|
|
if (EVP_PKEY_keygen(context.get(), &rawKeyPair) <= 0)
|
|
throw std::runtime_error("Could not generate RSA key pair.");
|
|
if (rawKeyPair == nullptr)
|
|
throw std::runtime_error("Could not generate RSA key pair.");
|
|
|
|
std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> keyPair(
|
|
rawKeyPair,
|
|
EVP_PKEY_free
|
|
);
|
|
|
|
// extract the private key
|
|
const std::unique_ptr<BIO, decltype(&BIO_free)> privateBio(
|
|
BIO_new(BIO_s_mem()),
|
|
BIO_free
|
|
);
|
|
if (privateBio == nullptr)
|
|
throw std::runtime_error("Could not create RSA private key.");
|
|
|
|
if (!i2d_PrivateKey_bio(
|
|
privateBio.get(),
|
|
keyPair.get()
|
|
))
|
|
throw std::runtime_error("Could not generate RSA private key.");
|
|
|
|
std::vector<std::uint8_t> privateKeyData(BIO_pending(privateBio.get()));
|
|
if (BIO_read(
|
|
privateBio.get(),
|
|
privateKeyData.data(),
|
|
static_cast<int>(privateKeyData.size())
|
|
) <= 0)
|
|
throw std::runtime_error("Could not read RSA private key.");
|
|
|
|
this->privateKey = RsaPrivateKey(privateKeyData, padMode);
|
|
|
|
// extract the public key
|
|
const std::unique_ptr<BIO, decltype(&BIO_free)> publicBio(
|
|
BIO_new(BIO_s_mem()),
|
|
BIO_free
|
|
);
|
|
if (publicBio == nullptr)
|
|
throw std::runtime_error("Could not create RSA public key.");
|
|
|
|
if (!i2d_PUBKEY_bio(
|
|
publicBio.get(),
|
|
keyPair.get()
|
|
))
|
|
throw std::runtime_error("Could not generate RSA public key.");
|
|
|
|
std::vector<std::uint8_t> publicKeyData(BIO_pending(publicBio.get()));
|
|
if (BIO_read(
|
|
publicBio.get(),
|
|
publicKeyData.data(),
|
|
static_cast<int>(publicKeyData.size())
|
|
) <= 0)
|
|
throw std::runtime_error("Could not read RSA public key.");
|
|
|
|
this->publicKey = RsaPublicKey(publicKeyData, padMode);
|
|
}
|
|
|
|
|
|
RsaPublicKey RsaKeyPair::getPublicKey() const {
|
|
return this->publicKey;
|
|
}
|
|
|
|
|
|
RsaPrivateKey RsaKeyPair::getPrivateKey() const {
|
|
return this->privateKey;
|
|
}
|
|
|
|
|
|
}
|