mirror of
https://github.com/pocoproject/poco.git
synced 2025-11-11 00:44:48 +01:00
add Crypto PKCS12/EC; update VS projects
This commit is contained in:
107
Crypto/src/CryptoException.cpp
Normal file
107
Crypto/src/CryptoException.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// CryptoException.cpp
|
||||
//
|
||||
//
|
||||
// Library: Crypto
|
||||
// Package: Crypto
|
||||
// Module: CryptoException
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Crypto/CryptoException.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include <typeinfo>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
POCO_IMPLEMENT_EXCEPTION(CryptoException, Exception, "Crypto Exception")
|
||||
|
||||
|
||||
OpenSSLException::OpenSSLException(int otherCode): CryptoException(otherCode)
|
||||
{
|
||||
setExtMessage();
|
||||
}
|
||||
|
||||
|
||||
OpenSSLException::OpenSSLException(const std::string& msg, int otherCode): CryptoException(msg, otherCode)
|
||||
{
|
||||
setExtMessage();
|
||||
}
|
||||
|
||||
|
||||
OpenSSLException::OpenSSLException(const std::string& msg, const std::string& arg, int otherCode): CryptoException(msg, arg, otherCode)
|
||||
{
|
||||
setExtMessage();
|
||||
}
|
||||
|
||||
|
||||
OpenSSLException::OpenSSLException(const std::string& msg, const Poco::Exception& exc, int otherCode): CryptoException(msg, exc, otherCode)
|
||||
{
|
||||
setExtMessage();
|
||||
}
|
||||
|
||||
|
||||
OpenSSLException::OpenSSLException(const OpenSSLException& exc): CryptoException(exc)
|
||||
{
|
||||
setExtMessage();
|
||||
}
|
||||
|
||||
|
||||
OpenSSLException::~OpenSSLException() throw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
OpenSSLException& OpenSSLException::operator = (const OpenSSLException& exc)
|
||||
{
|
||||
CryptoException::operator = (exc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
const char* OpenSSLException::name() const throw()
|
||||
{
|
||||
return "OpenSSLException";
|
||||
}
|
||||
|
||||
|
||||
const char* OpenSSLException::className() const throw()
|
||||
{
|
||||
return typeid(*this).name();
|
||||
}
|
||||
|
||||
|
||||
Poco::Exception* OpenSSLException::clone() const
|
||||
{
|
||||
return new OpenSSLException(*this);
|
||||
}
|
||||
|
||||
|
||||
void OpenSSLException::setExtMessage()
|
||||
{
|
||||
unsigned long e = ERR_get_error();
|
||||
char buf[128] = { 0 };
|
||||
char* pErr = ERR_error_string(e, buf);
|
||||
std::string err;
|
||||
if (pErr) err = pErr;
|
||||
else err = NumberFormatter::format(e);
|
||||
|
||||
extendedMessage(err);
|
||||
}
|
||||
|
||||
|
||||
void OpenSSLException::rethrow() const
|
||||
{
|
||||
throw *this;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
100
Crypto/src/ECDSADigestEngine.cpp
Normal file
100
Crypto/src/ECDSADigestEngine.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// ECDSADigestEngine.cpp
|
||||
//
|
||||
//
|
||||
// Library: Crypto
|
||||
// Package: ECDSA
|
||||
// Module: ECDSADigestEngine
|
||||
//
|
||||
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Crypto/ECDSADigestEngine.h"
|
||||
#include <openssl/ecdsa.h>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
ECDSADigestEngine::ECDSADigestEngine(const ECKey& key, const std::string &name):
|
||||
_key(key),
|
||||
_engine(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ECDSADigestEngine::~ECDSADigestEngine()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::size_t ECDSADigestEngine::digestLength() const
|
||||
{
|
||||
return _engine.digestLength();
|
||||
}
|
||||
|
||||
|
||||
void ECDSADigestEngine::reset()
|
||||
{
|
||||
_engine.reset();
|
||||
_digest.clear();
|
||||
_signature.clear();
|
||||
}
|
||||
|
||||
|
||||
const DigestEngine::Digest& ECDSADigestEngine::digest()
|
||||
{
|
||||
if (_digest.empty())
|
||||
{
|
||||
_digest = _engine.digest();
|
||||
}
|
||||
return _digest;
|
||||
}
|
||||
|
||||
|
||||
const DigestEngine::Digest& ECDSADigestEngine::signature()
|
||||
{
|
||||
if (_signature.empty())
|
||||
{
|
||||
digest();
|
||||
_signature.resize(_key.size());
|
||||
unsigned sigLen = static_cast<unsigned>(_signature.size());
|
||||
if (!ECDSA_sign(0, &_digest[0], static_cast<unsigned>(_digest.size()),
|
||||
&_signature[0], &sigLen, _key.impl()->getECKey()))
|
||||
{
|
||||
throw OpenSSLException();
|
||||
}
|
||||
if (sigLen < _signature.size()) _signature.resize(sigLen);
|
||||
}
|
||||
return _signature;
|
||||
}
|
||||
|
||||
|
||||
bool ECDSADigestEngine::verify(const DigestEngine::Digest& sig)
|
||||
{
|
||||
digest();
|
||||
EC_KEY* pKey = _key.impl()->getECKey();
|
||||
if (pKey)
|
||||
{
|
||||
int ret = ECDSA_verify(0, &_digest[0], static_cast<unsigned>(_digest.size()),
|
||||
&sig[0], static_cast<unsigned>(sig.size()),
|
||||
pKey);
|
||||
if (1 == ret) return true;
|
||||
else if (0 == ret) return false;
|
||||
}
|
||||
throw OpenSSLException();
|
||||
}
|
||||
|
||||
|
||||
void ECDSADigestEngine::updateImpl(const void* data, std::size_t length)
|
||||
{
|
||||
_engine.update(data, length);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
75
Crypto/src/ECKey.cpp
Normal file
75
Crypto/src/ECKey.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// ECKey.cpp
|
||||
//
|
||||
//
|
||||
// Library: Crypto
|
||||
// Package: EC
|
||||
// Module: ECKey
|
||||
//
|
||||
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Crypto/ECKey.h"
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
ECKey::ECKey(const EVPPKey& key):
|
||||
KeyPair(new ECKeyImpl(key)),
|
||||
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ECKey::ECKey(const X509Certificate& cert):
|
||||
KeyPair(new ECKeyImpl(cert)),
|
||||
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ECKey::ECKey(const PKCS12Container& cont):
|
||||
KeyPair(new ECKeyImpl(cont)),
|
||||
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ECKey::ECKey(const std::string& eccGroup):
|
||||
KeyPair(new ECKeyImpl(OBJ_txt2nid(eccGroup.c_str()))),
|
||||
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ECKey::ECKey(const std::string& publicKeyFile,
|
||||
const std::string& privateKeyFile,
|
||||
const std::string& privateKeyPassphrase):
|
||||
KeyPair(new ECKeyImpl(publicKeyFile, privateKeyFile, privateKeyPassphrase)),
|
||||
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ECKey::ECKey(std::istream* pPublicKeyStream,
|
||||
std::istream* pPrivateKeyStream,
|
||||
const std::string& privateKeyPassphrase):
|
||||
KeyPair(new ECKeyImpl(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase)),
|
||||
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ECKey::~ECKey()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
357
Crypto/src/ECKeyImpl.cpp
Normal file
357
Crypto/src/ECKeyImpl.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
//
|
||||
// ECKeyImpl.cpp
|
||||
//
|
||||
//
|
||||
// Library: Crypto
|
||||
// Package: EC
|
||||
// Module: ECKeyImpl
|
||||
//
|
||||
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Crypto/ECKeyImpl.h"
|
||||
#include "Poco/Crypto/X509Certificate.h"
|
||||
#include "Poco/Crypto/PKCS12Container.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include <sstream>
|
||||
#include <openssl/evp.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
|
||||
#include <openssl/bn.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
ECKeyImpl::ECKeyImpl(const EVPPKey& key):
|
||||
KeyPairImpl("ec", KT_EC_IMPL),
|
||||
_pEC(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>((const EVP_PKEY*)key)))
|
||||
{
|
||||
if (!_pEC) throw OpenSSLException("ECKeyImpl(const EVPPKey&)");
|
||||
}
|
||||
|
||||
|
||||
ECKeyImpl::ECKeyImpl(const X509Certificate& cert):
|
||||
KeyPairImpl("ec", KT_EC_IMPL),
|
||||
_pEC(0)
|
||||
{
|
||||
const X509* pCert = cert.certificate();
|
||||
if (pCert)
|
||||
{
|
||||
EVP_PKEY* pKey = X509_get_pubkey(const_cast<X509*>(pCert));
|
||||
if (pKey)
|
||||
{
|
||||
_pEC = EVP_PKEY_get1_EC_KEY(pKey);
|
||||
EVP_PKEY_free(pKey);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw OpenSSLException("ECKeyImpl(const X509Certificate&)");
|
||||
}
|
||||
|
||||
|
||||
ECKeyImpl::ECKeyImpl(const PKCS12Container& cont):
|
||||
KeyPairImpl("ec", KT_EC_IMPL),
|
||||
_pEC(EVP_PKEY_get1_EC_KEY(cont.getKey()))
|
||||
{
|
||||
if (!_pEC) throw OpenSSLException();
|
||||
}
|
||||
|
||||
|
||||
ECKeyImpl::ECKeyImpl(int curve):
|
||||
KeyPairImpl("ec", KT_EC_IMPL),
|
||||
_pEC(EC_KEY_new_by_curve_name(curve))
|
||||
{
|
||||
if (!EC_KEY_generate_key(_pEC))
|
||||
throw OpenSSLException("ECKeyImpl(int)");
|
||||
}
|
||||
|
||||
|
||||
ECKeyImpl::ECKeyImpl(const std::string& publicKeyFile,
|
||||
const std::string& privateKeyFile,
|
||||
const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
|
||||
{
|
||||
if (loadKey(PEM_read_PrivateKey, privateKeyFile, privateKeyPassphrase))
|
||||
return; // private key is enough
|
||||
|
||||
// no private key, this must be public key only, otherwise throw
|
||||
if (!loadKey(PEM_read_PUBKEY, publicKeyFile))
|
||||
{
|
||||
throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ECKeyImpl::ECKeyImpl(std::istream* pPublicKeyStream,
|
||||
std::istream* pPrivateKeyStream,
|
||||
const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
|
||||
{
|
||||
if (loadKey(PEM_read_bio_PrivateKey, pPrivateKeyStream, privateKeyPassphrase))
|
||||
return; // private key is enough
|
||||
|
||||
// no private key, this must be public key only, otherwise throw
|
||||
if (!loadKey(PEM_read_bio_PUBKEY, pPublicKeyStream))
|
||||
{
|
||||
throw OpenSSLException("ECKeyImpl(istream*, istream*, const string&");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ECKeyImpl::~ECKeyImpl()
|
||||
{
|
||||
freeEC();
|
||||
}
|
||||
|
||||
|
||||
void ECKeyImpl::freeEC()
|
||||
{
|
||||
if (_pEC)
|
||||
{
|
||||
EC_KEY_free(_pEC);
|
||||
_pEC = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ECKeyImpl::passCB(char* buf, int size, int, void* pass)
|
||||
{
|
||||
int len = (int) strlen((char*)pass);
|
||||
if (len > size) len = size;
|
||||
memcpy(buf, pass, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
bool ECKeyImpl::loadKey(PEM_read_Key_fn func, const std::string& keyFile, const std::string& pass)
|
||||
{
|
||||
if (!keyFile.empty())
|
||||
{
|
||||
EVP_PKEY* pKey = EVP_PKEY_new();
|
||||
if (pKey)
|
||||
{
|
||||
FILE* pFile = fopen(keyFile.c_str(), "r");
|
||||
if (pFile)
|
||||
{
|
||||
func(pFile, &pKey, passCB, pass.empty() ? (void*)0 : (void*)pass.c_str());
|
||||
_pEC = EVP_PKEY_get1_EC_KEY(pKey);
|
||||
EVP_PKEY_free(pKey);
|
||||
if (!_pEC) goto error;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
EVP_PKEY_free(pKey);
|
||||
throw IOException("ECKeyImpl, cannot open file", keyFile);
|
||||
}
|
||||
}
|
||||
else goto error;
|
||||
}
|
||||
return false;
|
||||
|
||||
error:
|
||||
throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&)");
|
||||
}
|
||||
|
||||
|
||||
bool ECKeyImpl::loadKey(PEM_read_bio_Key_fn func, std::istream* pIstr, const std::string& pass)
|
||||
{
|
||||
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)
|
||||
{
|
||||
EVP_PKEY* pKey = EVP_PKEY_new();
|
||||
if (pKey)
|
||||
{
|
||||
if (func(pBIO, &pKey, passCB, pass.empty() ? (void*)0 : (void*)pass.c_str()))
|
||||
{
|
||||
_pEC = EVP_PKEY_get1_EC_KEY(pKey);
|
||||
EVP_PKEY_free(pKey);
|
||||
BIO_free(pBIO);
|
||||
if (!_pEC) goto error;
|
||||
return true;
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_free(pBIO);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else goto error;
|
||||
}
|
||||
return false;
|
||||
|
||||
error:
|
||||
throw OpenSSLException("ECKeyImpl::ECKeyImpl(const string&, const string&, const string&)");
|
||||
}
|
||||
|
||||
|
||||
int ECKeyImpl::size() const
|
||||
{
|
||||
int sz = -1;
|
||||
EVP_PKEY* pKey = EVP_PKEY_new();
|
||||
if (pKey && EVP_PKEY_set1_EC_KEY(pKey, _pEC))
|
||||
{
|
||||
sz = EVP_PKEY_bits(pKey);
|
||||
EVP_PKEY_free(pKey);
|
||||
return sz;
|
||||
}
|
||||
throw OpenSSLException("ECKeyImpl::size()");
|
||||
}
|
||||
|
||||
|
||||
std::string ECKeyImpl::groupName() const
|
||||
{
|
||||
if (_pEC)
|
||||
{
|
||||
const EC_GROUP* ecGroup = EC_KEY_get0_group(_pEC);
|
||||
if (ecGroup)
|
||||
{
|
||||
return OBJ_nid2sn(EC_GROUP_get_curve_name(ecGroup));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw OpenSSLException("ECKeyImpl::groupName()");
|
||||
}
|
||||
}
|
||||
throw NullPointerException("ECKeyImpl::groupName() => _pEC");
|
||||
}
|
||||
|
||||
|
||||
void ECKeyImpl::save(const std::string& publicKeyFile,
|
||||
const std::string& privateKeyFile,
|
||||
const std::string& privateKeyPassphrase)
|
||||
{
|
||||
if (!publicKeyFile.empty())
|
||||
{
|
||||
BIO* bio = BIO_new(BIO_s_file());
|
||||
if (!bio) throw Poco::IOException("Cannot create BIO for writing public key file", publicKeyFile);
|
||||
try
|
||||
{
|
||||
if (BIO_write_filename(bio, const_cast<char*>(publicKeyFile.c_str())))
|
||||
{
|
||||
EVPPKey pKey(_pEC);
|
||||
if (!PEM_write_bio_PUBKEY(bio, pKey))
|
||||
{
|
||||
throw Poco::WriteFileException("Failed to write public key to file", publicKeyFile);
|
||||
}
|
||||
}
|
||||
else throw Poco::CreateFileException("Cannot create public key file");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BIO_free(bio);
|
||||
throw;
|
||||
}
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
if (!privateKeyFile.empty())
|
||||
{
|
||||
BIO* bio = BIO_new(BIO_s_file());
|
||||
if (!bio) throw Poco::IOException("Cannot create BIO for writing private key file", privateKeyFile);
|
||||
try
|
||||
{
|
||||
if (BIO_write_filename(bio, const_cast<char*>(privateKeyFile.c_str())))
|
||||
{
|
||||
EVPPKey pKey(_pEC);
|
||||
int rc = 0;
|
||||
if (privateKeyPassphrase.empty())
|
||||
{
|
||||
rc = PEM_write_bio_PrivateKey(bio, pKey, 0, 0, 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = PEM_write_bio_PrivateKey(bio, pKey, EVP_des_ede3_cbc(),
|
||||
reinterpret_cast<unsigned char*>(const_cast<char*>(privateKeyPassphrase.c_str())),
|
||||
static_cast<int>(privateKeyPassphrase.length()), 0, 0);
|
||||
}
|
||||
if (!rc)
|
||||
throw Poco::FileException("Failed to write private key to file", privateKeyFile);
|
||||
}
|
||||
else throw Poco::CreateFileException("Cannot create private key file", privateKeyFile);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BIO_free(bio);
|
||||
throw;
|
||||
}
|
||||
BIO_free(bio);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ECKeyImpl::save(std::ostream* pPublicKeyStream,
|
||||
std::ostream* pPrivateKeyStream,
|
||||
const std::string& privateKeyPassphrase)
|
||||
{
|
||||
if (pPublicKeyStream)
|
||||
{
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
if (!bio) throw Poco::IOException("Cannot create BIO for writing public key");
|
||||
EVPPKey pKey(_pEC);
|
||||
if (!PEM_write_bio_PUBKEY(bio, pKey))
|
||||
{
|
||||
BIO_free(bio);
|
||||
throw Poco::WriteFileException("Failed to write public key to stream");
|
||||
}
|
||||
char* pData;
|
||||
long size = BIO_get_mem_data(bio, &pData);
|
||||
pPublicKeyStream->write(pData, static_cast<std::streamsize>(size));
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
if (pPrivateKeyStream)
|
||||
{
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
if (!bio) throw Poco::IOException("Cannot create BIO for writing public key");
|
||||
EVPPKey pKey(_pEC);
|
||||
int rc = 0;
|
||||
if (privateKeyPassphrase.empty())
|
||||
rc = PEM_write_bio_PrivateKey(bio, pKey, 0, 0, 0, 0, 0);
|
||||
else
|
||||
rc = PEM_write_bio_PrivateKey(bio, pKey, EVP_des_ede3_cbc(),
|
||||
reinterpret_cast<unsigned char*>(const_cast<char*>(privateKeyPassphrase.c_str())),
|
||||
static_cast<int>(privateKeyPassphrase.length()), 0, 0);
|
||||
if (!rc)
|
||||
{
|
||||
BIO_free(bio);
|
||||
throw Poco::FileException("Failed to write private key to stream");
|
||||
}
|
||||
char* pData;
|
||||
long size = BIO_get_mem_data(bio, &pData);
|
||||
pPrivateKeyStream->write(pData, static_cast<std::streamsize>(size));
|
||||
BIO_free(bio);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ECKeyImpl::ByteVec ECKeyImpl::convertToByteVec(const BIGNUM* bn)
|
||||
{
|
||||
int numBytes = BN_num_bytes(bn);
|
||||
ByteVec byteVector(numBytes);
|
||||
|
||||
ByteVec::value_type* buffer = new ByteVec::value_type[numBytes];
|
||||
BN_bn2bin(bn, buffer);
|
||||
|
||||
for (int i = 0; i < numBytes; ++i)
|
||||
byteVector[i] = buffer[i];
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
return byteVector;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
134
Crypto/src/EVPPKey.cpp
Normal file
134
Crypto/src/EVPPKey.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// EVPPKey.cpp
|
||||
//
|
||||
//
|
||||
// Library: Crypto
|
||||
// Package: CryptoCore
|
||||
// Module: EVPPKey
|
||||
//
|
||||
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Crypto/EVPPKey.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
EVPPKey::EVPPKey(const std::string& ecCurveName): _pEVPPKey(0)
|
||||
{
|
||||
newECKey(ecCurveName.c_str());
|
||||
}
|
||||
|
||||
|
||||
EVPPKey::EVPPKey(const char* ecCurveName): _pEVPPKey(0)
|
||||
{
|
||||
newECKey(ecCurveName);
|
||||
}
|
||||
|
||||
|
||||
EVPPKey::EVPPKey(EVP_PKEY* pEVPPKey): _pEVPPKey(0)
|
||||
{
|
||||
duplicate(pEVPPKey);
|
||||
}
|
||||
|
||||
|
||||
EVPPKey::EVPPKey(const EVPPKey& other)
|
||||
{
|
||||
duplicate(other._pEVPPKey);
|
||||
}
|
||||
|
||||
|
||||
EVPPKey& EVPPKey::operator=(const EVPPKey& other)
|
||||
{
|
||||
duplicate(other._pEVPPKey);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
|
||||
EVPPKey::EVPPKey(EVPPKey&& other): _pEVPPKey(other._pEVPPKey)
|
||||
{
|
||||
other._pEVPPKey = nullptr;
|
||||
}
|
||||
|
||||
|
||||
EVPPKey& EVPPKey::operator=(EVPPKey&& other)
|
||||
{
|
||||
_pEVPPKey = other._pEVPPKey;
|
||||
other._pEVPPKey = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
|
||||
EVPPKey::~EVPPKey()
|
||||
{
|
||||
if (_pEVPPKey) EVP_PKEY_free(_pEVPPKey);
|
||||
}
|
||||
|
||||
|
||||
void EVPPKey::duplicate(EVP_PKEY* pEVPPKey)
|
||||
{
|
||||
if (!pEVPPKey) throw NullPointerException("EVPPKey::duplicate(): "
|
||||
"provided key pointer is null.");
|
||||
|
||||
_pEVPPKey = EVP_PKEY_new();
|
||||
if (!_pEVPPKey) throw NullPointerException("EVPPKey::duplicate(): "
|
||||
"EVP_PKEY_new() returned null.");
|
||||
|
||||
switch (pEVPPKey->type)
|
||||
{
|
||||
case EVP_PKEY_RSA:
|
||||
{
|
||||
RSA* pRSA = EVP_PKEY_get1_RSA(pEVPPKey);
|
||||
if (pRSA)
|
||||
{
|
||||
EVP_PKEY_set1_RSA(_pEVPPKey, pRSA);
|
||||
RSA_free(pRSA);
|
||||
}
|
||||
else throw OpenSSLException();
|
||||
break;
|
||||
}
|
||||
case EVP_PKEY_EC:
|
||||
{
|
||||
EC_KEY* pEC = EVP_PKEY_get1_EC_KEY(pEVPPKey);
|
||||
if (pEC)
|
||||
{
|
||||
EVP_PKEY_set1_EC_KEY(_pEVPPKey, pEC);
|
||||
EC_KEY_free(pEC);
|
||||
}
|
||||
else throw OpenSSLException();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw NotImplementedException("EVPPKey:duplicate(); Key type: " +
|
||||
NumberFormatter::format(pEVPPKey->type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EVPPKey::newECKey(const char* ecCurveName)
|
||||
{
|
||||
int curveID = OBJ_txt2nid(ecCurveName);
|
||||
EC_KEY* pEC = EC_KEY_new_by_curve_name(curveID);
|
||||
if (!pEC) goto err;
|
||||
if (!EC_KEY_generate_key(pEC)) goto err;
|
||||
_pEVPPKey = EVP_PKEY_new();
|
||||
if (!_pEVPPKey) goto err;
|
||||
if (!EVP_PKEY_set1_EC_KEY(_pEVPPKey, pEC)) goto err;
|
||||
EC_KEY_free(pEC);
|
||||
return;
|
||||
err:
|
||||
throw OpenSSLException();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
34
Crypto/src/KeyPair.cpp
Normal file
34
Crypto/src/KeyPair.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// KeyPair.cpp
|
||||
//
|
||||
//
|
||||
// Library: Crypto
|
||||
// Package: CryptoCore
|
||||
// Module: KeyPair
|
||||
//
|
||||
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Crypto/KeyPair.h"
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
KeyPair::KeyPair(KeyPairImpl::Ptr pKeyPairImpl): _pImpl(pKeyPairImpl)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
KeyPair::~KeyPair()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
35
Crypto/src/KeyPairImpl.cpp
Normal file
35
Crypto/src/KeyPairImpl.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// KeyPairImpl.cpp
|
||||
//
|
||||
//
|
||||
// Library: Crypto
|
||||
// Package: CryptoCore
|
||||
// Module: KeyPairImpl
|
||||
//
|
||||
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Crypto/KeyPairImpl.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
KeyPairImpl::KeyPairImpl(const std::string& name, Type type):
|
||||
_name(name),
|
||||
_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
KeyPairImpl::~KeyPairImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
135
Crypto/src/PKCS12Container.cpp
Normal file
135
Crypto/src/PKCS12Container.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// PKCS12Container.cpp
|
||||
//
|
||||
//
|
||||
// Library: Crypto
|
||||
// Package: Certificate
|
||||
// Module: PKCS12Container
|
||||
//
|
||||
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Crypto/PKCS12Container.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include <sstream>
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
PKCS12Container::PKCS12Container(std::istream& istr, const std::string& password): _pKey(0)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
Poco::StreamCopier::copyStream(istr, ostr);
|
||||
const std::string& cont = ostr.str();
|
||||
|
||||
BIO *pBIO = BIO_new_mem_buf(const_cast<char*>(cont.data()), static_cast<int>(cont.size()));
|
||||
if (pBIO)
|
||||
{
|
||||
PKCS12* pPKCS12 = 0;
|
||||
d2i_PKCS12_bio(pBIO, &pPKCS12);
|
||||
BIO_free(pBIO);
|
||||
if (!pPKCS12) throw OpenSSLException();
|
||||
load(pPKCS12, password);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw OpenSSLException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PKCS12Container::PKCS12Container(const std::string& path, const std::string& password): _pKey(0)
|
||||
{
|
||||
FILE* pFile = fopen(path.c_str(), "rb");
|
||||
if (pFile)
|
||||
{
|
||||
PKCS12* pPKCS12 = d2i_PKCS12_fp(pFile, NULL);
|
||||
fclose (pFile);
|
||||
if (!pPKCS12) throw OpenSSLException();
|
||||
load(pPKCS12, password);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Poco::OpenFileException("PKCS12Container: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PKCS12Container::PKCS12Container(const PKCS12Container& cont)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PKCS12Container& PKCS12Container::operator = (const PKCS12Container& cert)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PKCS12Container::~PKCS12Container()
|
||||
{
|
||||
if (_pKey) EVP_PKEY_free(_pKey);
|
||||
}
|
||||
|
||||
|
||||
void PKCS12Container::load(PKCS12* pPKCS12, const std::string& password)
|
||||
{
|
||||
if (pPKCS12)
|
||||
{
|
||||
X509* pCert = 0;
|
||||
STACK_OF(X509)* pCA = 0;
|
||||
if (PKCS12_parse(pPKCS12, password.c_str(), &_pKey, &pCert, &pCA))
|
||||
{
|
||||
if (pCert)
|
||||
{
|
||||
STACK_OF(PKCS12_SAFEBAG)* pBags = 0;
|
||||
_pX509Cert.reset(new X509Certificate(pCert, true));
|
||||
PKCS12_SAFEBAG* pBag = PKCS12_add_cert(&pBags, pCert);
|
||||
if (pBag)
|
||||
{
|
||||
char*pBuffer = PKCS12_get_friendlyname(pBag);
|
||||
if(pBuffer)
|
||||
{
|
||||
_pkcsFriendlyname = pBuffer;
|
||||
CRYPTO_free(pBuffer);
|
||||
}else _pkcsFriendlyname.clear();
|
||||
if(pBags) sk_PKCS12_SAFEBAG_pop_free(pBags, PKCS12_SAFEBAG_free);
|
||||
}
|
||||
else throw OpenSSLException();
|
||||
}
|
||||
else _pX509Cert.reset();
|
||||
|
||||
_caCertList.clear();
|
||||
if (pCA)
|
||||
{
|
||||
int certCount = sk_X509_num(pCA);
|
||||
for (int i = 0; i < certCount; ++i)
|
||||
{
|
||||
_caCertList.push_back(X509Certificate(sk_X509_value(pCA, i), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw OpenSSLException();
|
||||
}
|
||||
PKCS12_free(pPKCS12);
|
||||
sk_X509_pop_free(pCA, X509_free);
|
||||
X509_free(pCert);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw NullPointerException("PKCS12Container: struct PKCS12");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "Poco/DateTimeParser.h"
|
||||
#include <sstream>
|
||||
#include <openssl/pem.h>
|
||||
#ifdef _WIN32
|
||||
// fix for WIN32 header conflict
|
||||
#undef X509_NAME
|
||||
#endif
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
@@ -29,7 +33,7 @@ namespace Crypto {
|
||||
|
||||
X509Certificate::X509Certificate(std::istream& istr):
|
||||
_pCert(0)
|
||||
{
|
||||
{
|
||||
load(istr);
|
||||
}
|
||||
|
||||
@@ -103,17 +107,17 @@ X509Certificate::~X509Certificate()
|
||||
void X509Certificate::load(std::istream& istr)
|
||||
{
|
||||
poco_assert (!_pCert);
|
||||
|
||||
|
||||
std::stringstream certStream;
|
||||
Poco::StreamCopier::copyStream(istr, certStream);
|
||||
std::string cert = certStream.str();
|
||||
|
||||
|
||||
BIO *pBIO = BIO_new_mem_buf(const_cast<char*>(cert.data()), static_cast<int>(cert.size()));
|
||||
if (!pBIO) throw Poco::IOException("Cannot create BIO for reading certificate");
|
||||
_pCert = PEM_read_bio_X509(pBIO, 0, 0, 0);
|
||||
BIO_free(pBIO);
|
||||
|
||||
if (!_pCert) throw Poco::IOException("Faild to load certificate from stream");
|
||||
|
||||
if (!_pCert) throw Poco::IOException("Failed to load certificate from stream");
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -130,10 +134,10 @@ void X509Certificate::load(const std::string& path)
|
||||
BIO_free(pBIO);
|
||||
throw Poco::OpenFileException("Cannot open certificate file for reading", path);
|
||||
}
|
||||
|
||||
|
||||
_pCert = PEM_read_bio_X509(pBIO, 0, 0, 0);
|
||||
BIO_free(pBIO);
|
||||
|
||||
|
||||
if (!_pCert) throw Poco::ReadFileException("Faild to load certificate from", path);
|
||||
|
||||
init();
|
||||
@@ -205,24 +209,24 @@ std::string X509Certificate::commonName() const
|
||||
std::string X509Certificate::issuerName(NID nid) const
|
||||
{
|
||||
if (X509_NAME* issuer = X509_get_issuer_name(_pCert))
|
||||
{
|
||||
{
|
||||
char buffer[NAME_BUFFER_SIZE];
|
||||
if (X509_NAME_get_text_by_NID(issuer, nid, buffer, sizeof(buffer)) >= 0)
|
||||
return std::string(buffer);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
std::string X509Certificate::subjectName(NID nid) const
|
||||
{
|
||||
if (X509_NAME* subj = X509_get_subject_name(_pCert))
|
||||
{
|
||||
{
|
||||
char buffer[NAME_BUFFER_SIZE];
|
||||
if (X509_NAME_get_text_by_NID(subj, nid, buffer, sizeof(buffer)) >= 0)
|
||||
return std::string(buffer);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
@@ -230,16 +234,16 @@ void X509Certificate::extractNames(std::string& cmnName, std::set<std::string>&
|
||||
{
|
||||
domainNames.clear();
|
||||
if (STACK_OF(GENERAL_NAME)* names = static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(_pCert, NID_subject_alt_name, 0, 0)))
|
||||
{
|
||||
{
|
||||
for (int i = 0; i < sk_GENERAL_NAME_num(names); ++i)
|
||||
{
|
||||
{
|
||||
const GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i);
|
||||
if (name->type == GEN_DNS)
|
||||
{
|
||||
const char* data = reinterpret_cast<char*>(ASN1_STRING_data(name->d.ia5));
|
||||
std::size_t len = ASN1_STRING_length(name->d.ia5);
|
||||
domainNames.insert(std::string(data, len));
|
||||
}
|
||||
}
|
||||
}
|
||||
GENERAL_NAMES_free(names);
|
||||
}
|
||||
@@ -290,4 +294,19 @@ bool X509Certificate::equals(const X509Certificate& otherCertificate) const
|
||||
}
|
||||
|
||||
|
||||
void X509Certificate::print(std::ostream& out) const
|
||||
{
|
||||
out << "subjectName: " << subjectName() << std::endl;
|
||||
out << "issuerName: " << issuerName() << std::endl;
|
||||
out << "commonName: " << commonName() << std::endl;
|
||||
out << "country: " << subjectName(X509Certificate::NID_COUNTRY) << std::endl;
|
||||
out << "localityName: " << subjectName(X509Certificate::NID_LOCALITY_NAME) << std::endl;
|
||||
out << "stateOrProvince: " << subjectName(X509Certificate::NID_STATE_OR_PROVINCE) << std::endl;
|
||||
out << "organizationName: " << subjectName(X509Certificate::NID_ORGANIZATION_NAME) << std::endl;
|
||||
out << "organizationUnitName: " << subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME) << std::endl;
|
||||
out << "emailAddress: " << subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS) << std::endl;
|
||||
out << "serialNumber: " << subjectName(X509Certificate::NID_SERIAL_NUMBER) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
|
||||
Reference in New Issue
Block a user