28 #include "../detail/openssl-helper.hpp" 29 #include "../key-params.hpp" 30 #include "../../encoding/buffer-stream.hpp" 32 #include <boost/lexical_cast.hpp> 35 #define ENSURE_PRIVATE_KEY_LOADED(key) \ 37 if ((key) == nullptr) \ 38 BOOST_THROW_EXCEPTION(Error("Private key has not been loaded yet")); \ 41 #define ENSURE_PRIVATE_KEY_NOT_LOADED(key) \ 43 if ((key) != nullptr) \ 44 BOOST_THROW_EXCEPTION(Error("Private key has already been loaded")); \ 54 #if OPENSSL_VERSION_NUMBER < 0x1010000fL 55 static bool isInitialized =
false;
57 OpenSSL_add_all_algorithms();
60 #endif // OPENSSL_VERSION_NUMBER < 0x1010000fL 109 if (d2i_AutoPrivateKey(&m_impl->key, &buf, static_cast<long>(size)) ==
nullptr)
110 BOOST_THROW_EXCEPTION(
Error(
"Failed to load private key"));
140 BOOST_ASSERT(std::strlen(pw) == pwLen);
145 if (!membio.
write(buf, size))
146 BOOST_THROW_EXCEPTION(
Error(
"Failed to copy buffer"));
148 if (d2i_PKCS8PrivateKey_bio(membio, &m_impl->key,
nullptr, const_cast<char*>(pw)) ==
nullptr)
149 BOOST_THROW_EXCEPTION(
Error(
"Failed to load private key"));
155 BOOST_ASSERT(size >= 0);
157 return (*cb)(buf,
static_cast<size_t>(size), rwflag);
167 if (!membio.
write(buf, size))
168 BOOST_THROW_EXCEPTION(
Error(
"Failed to copy buffer"));
173 m_impl->key = d2i_PKCS8PrivateKey_bio(membio,
nullptr,
nullptr,
nullptr);
175 if (m_impl->key ==
nullptr)
176 BOOST_THROW_EXCEPTION(
Error(
"Failed to load private key"));
268 uint8_t* pkcs8 =
nullptr;
269 int len = i2d_PUBKEY(m_impl->key, &pkcs8);
271 BOOST_THROW_EXCEPTION(
Error(
"Failed to derive public key"));
273 auto result = make_shared<Buffer>(pkcs8, len);
287 BOOST_THROW_EXCEPTION(
Error(
"Failed to determine key type"));
289 return rsaDecrypt(cipherText, cipherLen);
291 BOOST_THROW_EXCEPTION(
Error(
"Decryption is not supported for key type " +
to_string(keyType)));
296 PrivateKey::getEvpPkey()
const 302 PrivateKey::toPkcs1()
const 308 if (!i2d_PrivateKey_bio(membio, m_impl->key))
309 BOOST_THROW_EXCEPTION(Error(
"Cannot convert key to PKCS #1 format"));
311 auto buffer = make_shared<Buffer>(BIO_pending(membio));
312 membio.read(buffer->data(), buffer->size());
318 PrivateKey::toPkcs8(
const char* pw,
size_t pwLen)
const 320 BOOST_ASSERT(std::strlen(pw) == pwLen);
324 detail::Bio membio(BIO_s_mem());
325 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_des_ede3_cbc(),
nullptr, 0,
326 nullptr, const_cast<char*>(pw)))
327 BOOST_THROW_EXCEPTION(Error(
"Cannot convert key to PKCS #8 format"));
329 auto buffer = make_shared<Buffer>(BIO_pending(membio));
330 membio.read(buffer->data(), buffer->size());
336 PrivateKey::toPkcs8(PasswordCallback pwCallback)
const 341 detail::Bio membio(BIO_s_mem());
342 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_des_ede3_cbc(),
nullptr, 0,
344 BOOST_THROW_EXCEPTION(Error(
"Cannot convert key to PKCS #8 format"));
346 auto buffer = make_shared<Buffer>(BIO_pending(membio));
347 membio.read(buffer->data(), buffer->size());
353 PrivateKey::rsaDecrypt(
const uint8_t* cipherText,
size_t cipherLen)
const 355 detail::EvpPkeyCtx ctx(m_impl->key);
357 if (EVP_PKEY_decrypt_init(ctx) <= 0)
358 BOOST_THROW_EXCEPTION(Error(
"Failed to initialize decryption context"));
360 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
361 BOOST_THROW_EXCEPTION(Error(
"Failed to set padding"));
365 if (EVP_PKEY_decrypt(ctx,
nullptr, &outlen, cipherText, cipherLen) <= 0)
366 BOOST_THROW_EXCEPTION(Error(
"Failed to estimate output length"));
368 auto out = make_shared<Buffer>(outlen);
369 if (EVP_PKEY_decrypt(ctx, out->data(), &outlen, cipherText, cipherLen) <= 0)
370 BOOST_THROW_EXCEPTION(Error(
"Failed to decrypt ciphertext"));
376 unique_ptr<PrivateKey>
377 PrivateKey::generateRsaKey(uint32_t keySize)
379 detail::EvpPkeyCtx kctx(EVP_PKEY_RSA);
381 if (EVP_PKEY_keygen_init(kctx) <= 0)
382 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Failed to initialize RSA keygen context"));
384 if (EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, static_cast<int>(keySize)) <= 0)
385 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Failed to set RSA key length"));
387 auto privateKey = make_unique<PrivateKey>();
388 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
389 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Failed to generate RSA key"));
394 unique_ptr<PrivateKey>
395 PrivateKey::generateEcKey(uint32_t keySize)
397 detail::EvpPkeyCtx pctx(EVP_PKEY_EC);
399 if (EVP_PKEY_paramgen_init(pctx) <= 0)
400 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Failed to initialize EC paramgen context"));
405 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1);
408 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_secp384r1);
411 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Unsupported EC key length"));
414 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Failed to set EC curve"));
417 if (EVP_PKEY_paramgen(pctx, ¶ms.key) <= 0)
418 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Failed to generate EC parameters"));
420 detail::EvpPkeyCtx kctx(params.key);
421 if (EVP_PKEY_keygen_init(kctx) <= 0)
422 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Failed to initialize EC keygen context"));
424 auto privateKey = make_unique<PrivateKey>();
425 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
426 BOOST_THROW_EXCEPTION(PrivateKey::Error(
"Failed to generate EC key"));
431 unique_ptr<PrivateKey>
437 return PrivateKey::generateRsaKey(rsaParams.
getKeySize());
441 return PrivateKey::generateEcKey(ecParams.
getKeySize());
444 BOOST_THROW_EXCEPTION(std::invalid_argument(
"Unsupported asymmetric key type " +
445 boost::lexical_cast<std::string>(keyParams.
getKeyType())));
Copyright (c) 2011-2015 Regents of the University of California.
int getEvpPkeyType(EVP_PKEY *key)
#define ENSURE_PRIVATE_KEY_NOT_LOADED(key)
RSA key, supports sign/verify and encrypt/decrypt operations.
#define ENSURE_PRIVATE_KEY_LOADED(key)
KeyType
The type of a cryptographic key.
Elliptic Curve key (e.g. for ECDSA), supports sign/verify operations.
KeyType getKeyType() const
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
Base class of key parameters.
uint32_t getKeySize() const
implements an output stream that constructs ndn::Buffer
std::string to_string(const V &v)
unique_ptr< T > make_unique(Args &&... args)
SimplePublicKeyParams is a template for public keys with only one parameter: size.
shared_ptr< const Buffer > ConstBufferPtr
bool write(const uint8_t *buf, size_t buflen) noexcept