mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-27 19:10:20 +01:00
backport EVPPKey file/stream load/save capabilities
This commit is contained in:
@@ -30,7 +30,6 @@
|
||||
#include <vector>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -102,16 +101,8 @@ public:
|
||||
/// key is not exported.
|
||||
|
||||
private:
|
||||
typedef EVP_PKEY* (*PEM_read_bio_Key_fn)(BIO*, EVP_PKEY**, pem_password_cb*, void*);
|
||||
typedef EVP_PKEY* (*PEM_read_Key_fn)(FILE*, EVP_PKEY**, pem_password_cb*, void*);
|
||||
|
||||
static int passCB(char* buf, int size, int, void* pass);
|
||||
bool loadKey(PEM_read_Key_fn func, const std::string& keyFile, const std::string& pass = "");
|
||||
bool loadKey(PEM_read_bio_Key_fn func, std::istream* pKeyStream, const std::string& pass = "");
|
||||
void freeEC();
|
||||
|
||||
static ByteVec convertToByteVec(const BIGNUM* bn);
|
||||
|
||||
EC_KEY* _pEC;
|
||||
};
|
||||
|
||||
@@ -131,6 +122,28 @@ inline const EC_KEY* ECKeyImpl::getECKey() const
|
||||
}
|
||||
|
||||
|
||||
inline std::string ECKeyImpl::groupName() const
|
||||
{
|
||||
return OBJ_nid2sn(groupId());
|
||||
}
|
||||
|
||||
|
||||
inline void ECKeyImpl::save(const std::string& publicKeyFile,
|
||||
const std::string& privateKeyFile,
|
||||
const std::string& privateKeyPassphrase)
|
||||
{
|
||||
EVPPKey(_pEC).save(publicKeyFile, privateKeyFile, privateKeyPassphrase);
|
||||
}
|
||||
|
||||
|
||||
inline void ECKeyImpl::save(std::ostream* pPublicKeyStream,
|
||||
std::ostream* pPrivateKeyStream,
|
||||
const std::string& privateKeyPassphrase)
|
||||
{
|
||||
EVPPKey(_pEC).save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
|
||||
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
|
||||
#include "Poco/Crypto/Crypto.h"
|
||||
#include "Poco/Crypto/CryptoException.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -57,12 +60,23 @@ public:
|
||||
|
||||
template<typename K>
|
||||
explicit EVPPKey(K* pKey): _pEVPPKey(EVP_PKEY_new())
|
||||
/// Constructs EVPPKey from a "native" key pointer.
|
||||
/// Constructs EVPPKey from a "native" OpenSSL (RSA or EC_KEY),
|
||||
/// or a Poco wrapper (RSAKey, ECKey) key pointer.
|
||||
{
|
||||
if (!_pEVPPKey) throw OpenSSLException();
|
||||
setKey(pKey);
|
||||
}
|
||||
|
||||
EVPPKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = "");
|
||||
/// Creates the EVPPKey, by reading public and private key from the given files and
|
||||
/// using the given passphrase for the private key. Can only by used for signing if
|
||||
/// a private key is available.
|
||||
|
||||
EVPPKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase = "");
|
||||
/// Creates the EVPPKey. Can only by used for signing if pPrivKey
|
||||
/// is not null. If a private key file is specified, you don't need to
|
||||
/// specify a public key file. OpenSSL will auto-create it from the private key.
|
||||
|
||||
EVPPKey(const EVPPKey& other);
|
||||
/// Copy constructor.
|
||||
|
||||
@@ -80,6 +94,18 @@ public:
|
||||
~EVPPKey();
|
||||
/// Destroys the EVPPKey.
|
||||
|
||||
void save(const std::string& publicKeyFile, const std::string& privateKeyFile = "", const std::string& privateKeyPassphrase = "");
|
||||
/// Exports the public and/or private keys to the given files.
|
||||
///
|
||||
/// If an empty filename is specified, the corresponding key
|
||||
/// is not exported.
|
||||
|
||||
void save(std::ostream* pPublicKeyStream, std::ostream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = "");
|
||||
/// Exports the public and/or private key to the given streams.
|
||||
///
|
||||
/// If a null pointer is passed for a stream, the corresponding
|
||||
/// key is not exported.
|
||||
|
||||
int type() const;
|
||||
/// Retuns the EVPPKey type NID.
|
||||
|
||||
@@ -103,8 +129,118 @@ private:
|
||||
void setKey(RSAKey* pKey);
|
||||
void setKey(EC_KEY* pKey);
|
||||
void setKey(RSA* pKey);
|
||||
static int passCB(char* buf, int size, int, void* pass);
|
||||
|
||||
typedef EVP_PKEY* (*PEM_read_FILE_Key_fn)(FILE*, EVP_PKEY**, pem_password_cb*, void*);
|
||||
typedef EVP_PKEY* (*PEM_read_BIO_Key_fn)(BIO*, EVP_PKEY**, pem_password_cb*, void*);
|
||||
typedef void* (*EVP_PKEY_get_Key_fn)(EVP_PKEY* pkey);
|
||||
|
||||
// The following load*() functions are used by both native and EVP_PKEY type key
|
||||
// loading from BIO/FILE.
|
||||
// When used for EVP key loading, getFunc is null (ie. native key is not extracted
|
||||
// from the loaded EVP_PKEY).
|
||||
template <typename K, typename F>
|
||||
static bool loadKey(K** ppKey,
|
||||
PEM_read_FILE_Key_fn readFunc,
|
||||
F getFunc,
|
||||
const std::string& keyFile,
|
||||
const std::string& pass = "")
|
||||
{
|
||||
poco_assert_dbg (((typeid(K) == typeid(RSA) || typeid(K) == typeid(EC_KEY)) && getFunc) ||
|
||||
((typeid(K) == typeid(EVP_PKEY)) && !getFunc));
|
||||
poco_check_ptr (ppKey);
|
||||
poco_assert_dbg (!*ppKey);
|
||||
|
||||
if (!keyFile.empty())
|
||||
{
|
||||
if (!getFunc) *ppKey = (K*)EVP_PKEY_new();
|
||||
EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey;
|
||||
if (pKey)
|
||||
{
|
||||
FILE* pFile = fopen(keyFile.c_str(), "r");
|
||||
if (pFile)
|
||||
{
|
||||
readFunc(pFile, &pKey, passCB, pass.empty() ? (void*)0 : (void*)pass.c_str());
|
||||
fclose(pFile);
|
||||
if (getFunc)
|
||||
{
|
||||
*ppKey = (K*)getFunc(pKey);
|
||||
EVP_PKEY_free(pKey);
|
||||
}
|
||||
else *ppKey = (K*)pKey;
|
||||
if (!*ppKey) goto error;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
EVP_PKEY_free(pKey);
|
||||
throw IOException("ECKeyImpl, cannot open file", keyFile);
|
||||
}
|
||||
}
|
||||
else goto error;
|
||||
}
|
||||
return false;
|
||||
|
||||
error:
|
||||
throw OpenSSLException("EVPKey::loadKey(string)");
|
||||
}
|
||||
|
||||
template <typename K, typename F>
|
||||
static bool loadKey(K** ppKey,
|
||||
PEM_read_BIO_Key_fn readFunc,
|
||||
F getFunc,
|
||||
std::istream* pIstr,
|
||||
const std::string& pass = "")
|
||||
{
|
||||
poco_assert_dbg (((typeid(K) == typeid(RSA) || typeid(K) == typeid(EC_KEY)) && getFunc) ||
|
||||
((typeid(K) == typeid(EVP_PKEY)) && !getFunc));
|
||||
poco_check_ptr(ppKey);
|
||||
poco_assert_dbg(!*ppKey);
|
||||
|
||||
if (pIstr)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
Poco::StreamCopier::copyStream(*pIstr, ostr);
|
||||
std::string key = ostr.str();
|
||||
BIO *pBIO = BIO_new_mem_buf(const_cast<char*>(key.data()), static_cast<int>(key.size()));
|
||||
if (pBIO)
|
||||
{
|
||||
if (!getFunc) *ppKey = (K*)EVP_PKEY_new();
|
||||
EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey;
|
||||
if (pKey)
|
||||
{
|
||||
if (readFunc(pBIO, &pKey, passCB, pass.empty() ? (void*)0 : (void*)pass.c_str()))
|
||||
{
|
||||
BIO_free(pBIO);
|
||||
if (getFunc)
|
||||
{
|
||||
*ppKey = (K*)getFunc(pKey);
|
||||
EVP_PKEY_free(pKey);
|
||||
}
|
||||
else *ppKey = (K*)pKey;
|
||||
if (!*ppKey) goto error;
|
||||
return true;
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_free(pBIO);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else goto error;
|
||||
}
|
||||
return false;
|
||||
|
||||
error:
|
||||
throw OpenSSLException("EVPKey::loadKey(stream)");
|
||||
}
|
||||
|
||||
EVP_PKEY* _pEVPPKey;
|
||||
|
||||
friend class ECKeyImpl;
|
||||
friend class RSAKeyImpl;
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user