fix incomplete EC key creation from curve name; make sure tests use curves that exist; add validation checks on EC key creation

This commit is contained in:
Alex Fabijanic 2017-09-28 15:17:15 -05:00
parent 03e97dd0f7
commit 528b5d615a
6 changed files with 398 additions and 258 deletions

View File

@ -79,6 +79,16 @@ public:
ECKeyImpl::Ptr impl() const; ECKeyImpl::Ptr impl() const;
/// Returns the impl object. /// Returns the impl object.
static std::string getCurveName(int nid = -1);
/// Returns elliptical curve name corresponding to
/// the given nid; if nid is not found, returns
/// empty string.
///
/// If nid is -1, returns first curve name.
///
/// If no curves are found, returns empty string;
private: private:
ECKeyImpl::Ptr _pImpl; ECKeyImpl::Ptr _pImpl;
}; };
@ -93,6 +103,12 @@ inline ECKeyImpl::Ptr ECKey::impl() const
} }
inline std::string ECKey::getCurveName(int nid)
{
return ECKeyImpl::getCurveName(nid);
}
} } // namespace Poco::Crypto } } // namespace Poco::Crypto

View File

@ -104,7 +104,17 @@ public:
/// If a null pointer is passed for a stream, the corresponding /// If a null pointer is passed for a stream, the corresponding
/// key is not exported. /// key is not exported.
static std::string getCurveName(int nid = -1);
/// Returns elliptical curve name corresponding to
/// the given nid; if nid is not found, returns
/// empty string.
///
/// If nid is -1, returns first curve name.
///
/// If no curves are found, returns empty string;
private: private:
void checkEC(const std::string& method, const std::string& func) const;
void freeEC(); void freeEC();
EC_KEY* _pEC; EC_KEY* _pEC;

View File

@ -196,7 +196,11 @@ private:
*ppKey = (K*)getFunc(pKey); *ppKey = (K*)getFunc(pKey);
EVP_PKEY_free(pKey); EVP_PKEY_free(pKey);
} }
else *ppKey = (K*)pKey; else
{
poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*));
*ppKey = (K*)pKey;
}
if(!*ppKey) goto error; if(!*ppKey) goto error;
return true; return true;
} }
@ -252,7 +256,11 @@ private:
*ppKey = (K*)getFunc(pKey); *ppKey = (K*)getFunc(pKey);
EVP_PKEY_free(pKey); EVP_PKEY_free(pKey);
} }
else *ppKey = (K*)pKey; else
{
poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*));
*ppKey = (K*)pKey;
}
if (!*ppKey) goto error; if (!*ppKey) goto error;
return true; return true;
} }
@ -282,10 +290,9 @@ private:
inline bool EVPPKey::operator == (const EVPPKey& other) const inline bool EVPPKey::operator == (const EVPPKey& other) const
{ {
poco_assert_dbg(other._pEVPPKey && _pEVPPKey); poco_check_ptr (other._pEVPPKey);
int r = EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey); poco_check_ptr (_pEVPPKey);
if (r < 0) throw OpenSSLException("EVPPKey::operator ==()"); return (1 == EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey));
return (1 == r);
} }

View File

@ -17,6 +17,7 @@
#include "Poco/Crypto/X509Certificate.h" #include "Poco/Crypto/X509Certificate.h"
#include "Poco/Crypto/PKCS12Container.h" #include "Poco/Crypto/PKCS12Container.h"
#include "Poco/FileStream.h" #include "Poco/FileStream.h"
#include "Poco/Format.h"
#include <sstream> #include <sstream>
#include <openssl/evp.h> #include <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER >= 0x00908000L #if OPENSSL_VERSION_NUMBER >= 0x00908000L
@ -32,7 +33,7 @@ ECKeyImpl::ECKeyImpl(const EVPPKey& key):
KeyPairImpl("ec", KT_EC_IMPL), KeyPairImpl("ec", KT_EC_IMPL),
_pEC(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>((const EVP_PKEY*)key))) _pEC(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>((const EVP_PKEY*)key)))
{ {
if (!_pEC) throw OpenSSLException("ECKeyImpl(const EVPPKey&)"); checkEC("ECKeyImpl(const EVPPKey&)", "EVP_PKEY_get1_EC_KEY()");
} }
@ -48,6 +49,7 @@ ECKeyImpl::ECKeyImpl(const X509Certificate& cert):
{ {
_pEC = EVP_PKEY_get1_EC_KEY(pKey); _pEC = EVP_PKEY_get1_EC_KEY(pKey);
EVP_PKEY_free(pKey); EVP_PKEY_free(pKey);
checkEC("ECKeyImpl(const const X509Certificate&)", "EVP_PKEY_get1_EC_KEY()");
return; return;
} }
} }
@ -59,7 +61,7 @@ ECKeyImpl::ECKeyImpl(const PKCS12Container& cont):
KeyPairImpl("ec", KT_EC_IMPL), KeyPairImpl("ec", KT_EC_IMPL),
_pEC(EVP_PKEY_get1_EC_KEY(cont.getKey())) _pEC(EVP_PKEY_get1_EC_KEY(cont.getKey()))
{ {
if (!_pEC) throw OpenSSLException(); checkEC("ECKeyImpl(const PKCS12Container&)", "EVP_PKEY_get1_EC_KEY()");
} }
@ -67,8 +69,11 @@ ECKeyImpl::ECKeyImpl(int curve):
KeyPairImpl("ec", KT_EC_IMPL), KeyPairImpl("ec", KT_EC_IMPL),
_pEC(EC_KEY_new_by_curve_name(curve)) _pEC(EC_KEY_new_by_curve_name(curve))
{ {
if (!EC_KEY_generate_key(_pEC)) poco_check_ptr(_pEC);
throw OpenSSLException("ECKeyImpl(int)"); EC_KEY_set_asn1_flag(_pEC, OPENSSL_EC_NAMED_CURVE);
if (!(EC_KEY_generate_key(_pEC)))
throw OpenSSLException("ECKeyImpl(int curve): EC_KEY_generate_key()");
checkEC("ECKeyImpl(int curve)", "EC_KEY_generate_key()");
} }
@ -77,13 +82,21 @@ ECKeyImpl::ECKeyImpl(const std::string& publicKeyFile,
const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0) const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
{ {
if (EVPPKey::loadKey(&_pEC, PEM_read_PrivateKey, EVP_PKEY_get1_EC_KEY, privateKeyFile, privateKeyPassphrase)) if (EVPPKey::loadKey(&_pEC, PEM_read_PrivateKey, EVP_PKEY_get1_EC_KEY, privateKeyFile, privateKeyPassphrase))
{
checkEC(Poco::format("ECKeyImpl(%s, %s, %s)",
publicKeyFile, privateKeyFile, privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
"PEM_read_PrivateKey() or EVP_PKEY_get1_EC_KEY()");
return; // private key is enough return; // private key is enough
}
// no private key, this must be public key only, otherwise throw // no private key, this must be public key only, otherwise throw
if (!EVPPKey::loadKey(&_pEC, PEM_read_PUBKEY, EVP_PKEY_get1_EC_KEY, publicKeyFile)) if (!EVPPKey::loadKey(&_pEC, PEM_read_PUBKEY, EVP_PKEY_get1_EC_KEY, publicKeyFile))
{ {
throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&"); throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&");
} }
checkEC(Poco::format("ECKeyImpl(%s, %s, %s)",
publicKeyFile, privateKeyFile, privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
"PEM_read_PUBKEY() or EVP_PKEY_get1_EC_KEY()");
} }
@ -92,13 +105,21 @@ ECKeyImpl::ECKeyImpl(std::istream* pPublicKeyStream,
const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0) const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
{ {
if (EVPPKey::loadKey(&_pEC, PEM_read_bio_PrivateKey, EVP_PKEY_get1_EC_KEY, pPrivateKeyStream, privateKeyPassphrase)) if (EVPPKey::loadKey(&_pEC, PEM_read_bio_PrivateKey, EVP_PKEY_get1_EC_KEY, pPrivateKeyStream, privateKeyPassphrase))
{
checkEC(Poco::format("ECKeyImpl(stream, stream, %s)",
privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
"PEM_read_bio_PrivateKey() or EVP_PKEY_get1_EC_KEY()");
return; // private key is enough return; // private key is enough
}
// no private key, this must be public key only, otherwise throw // no private key, this must be public key only, otherwise throw
if (!EVPPKey::loadKey(&_pEC, PEM_read_bio_PUBKEY, EVP_PKEY_get1_EC_KEY, pPublicKeyStream)) if (!EVPPKey::loadKey(&_pEC, PEM_read_bio_PUBKEY, EVP_PKEY_get1_EC_KEY, pPublicKeyStream))
{ {
throw OpenSSLException("ECKeyImpl(istream*, istream*, const string&"); throw OpenSSLException("ECKeyImpl(istream*, istream*, const string&");
} }
checkEC(Poco::format("ECKeyImpl(stream, stream, %s)",
privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
"PEM_read_bio_PUBKEY() or EVP_PKEY_get1_EC_KEY()");
} }
@ -108,6 +129,14 @@ ECKeyImpl::~ECKeyImpl()
} }
void ECKeyImpl::checkEC(const std::string& method, const std::string& func) const
{
if (!_pEC) throw OpenSSLException(Poco::format("%s: %s", method, func));
if (!EC_KEY_check_key(_pEC))
throw OpenSSLException(Poco::format("%s: EC_KEY_check_key()", method));
}
void ECKeyImpl::freeEC() void ECKeyImpl::freeEC()
{ {
if (_pEC) if (_pEC)
@ -150,4 +179,28 @@ int ECKeyImpl::groupId() const
} }
std::string ECKeyImpl::getCurveName(int nid)
{
std::string curveName;
size_t len = EC_get_builtin_curves(NULL, 0);
EC_builtin_curve* pCurves =
(EC_builtin_curve*) OPENSSL_malloc(sizeof(EC_builtin_curve) * len);
if (!pCurves) return curveName;
if (!EC_get_builtin_curves(pCurves, len))
{
OPENSSL_free(pCurves);
return curveName;
}
if (-1 == nid) nid = pCurves[0].nid;
int bufLen = 128;
char buf[bufLen] = {0};
OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(nid), 0);
curveName = buf;
OPENSSL_free(pCurves);
return curveName;
}
} } // namespace Poco::Crypto } } // namespace Poco::Crypto

View File

@ -37,24 +37,30 @@ void ECTest::testECNewKeys()
{ {
try try
{ {
ECKey key("secp521r1"); std::string curveName = ECKey::getCurveName();
std::ostringstream strPub; if (!curveName.empty())
std::ostringstream strPriv; {
key.save(&strPub, &strPriv, "testpwd"); ECKey key(curveName);
std::string pubKey = strPub.str(); std::ostringstream strPub;
std::string privKey = strPriv.str(); std::ostringstream strPriv;
key.save(&strPub, &strPriv, "testpwd");
std::string pubKey = strPub.str();
std::string privKey = strPriv.str();
// now do the round trip // now do the round trip
std::istringstream iPub(pubKey); std::istringstream iPub(pubKey);
std::istringstream iPriv(privKey); std::istringstream iPriv(privKey);
ECKey key2(&iPub, &iPriv, "testpwd"); ECKey key2(&iPub, &iPriv, "testpwd");
std::istringstream iPriv2(privKey); std::istringstream iPriv2(privKey);
ECKey key3(0, &iPriv2, "testpwd"); ECKey key3(0, &iPriv2, "testpwd");
std::ostringstream strPub3; std::ostringstream strPub3;
key3.save(&strPub3); key3.save(&strPub3);
std::string pubFromPrivate = strPub3.str(); std::string pubFromPrivate = strPub3.str();
assert (pubFromPrivate == pubKey); assert (pubFromPrivate == pubKey);
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {
@ -68,24 +74,30 @@ void ECTest::testECNewKeysNoPassphrase()
{ {
try try
{ {
ECKey key("secp521r1"); std::string curveName = ECKey::getCurveName();
std::ostringstream strPub; if (!curveName.empty())
std::ostringstream strPriv; {
key.save(&strPub, &strPriv); ECKey key(curveName);
std::string pubKey = strPub.str(); std::ostringstream strPub;
std::string privKey = strPriv.str(); std::ostringstream strPriv;
key.save(&strPub, &strPriv);
std::string pubKey = strPub.str();
std::string privKey = strPriv.str();
// now do the round trip // now do the round trip
std::istringstream iPub(pubKey); std::istringstream iPub(pubKey);
std::istringstream iPriv(privKey); std::istringstream iPriv(privKey);
ECKey key2(&iPub, &iPriv); ECKey key2(&iPub, &iPriv);
std::istringstream iPriv2(privKey); std::istringstream iPriv2(privKey);
ECKey key3(0, &iPriv2); ECKey key3(0, &iPriv2);
std::ostringstream strPub3; std::ostringstream strPub3;
key3.save(&strPub3); key3.save(&strPub3);
std::string pubFromPrivate = strPub3.str(); std::string pubFromPrivate = strPub3.str();
assert (pubFromPrivate == pubKey); assert (pubFromPrivate == pubKey);
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {
@ -99,21 +111,27 @@ void ECTest::testECDSASignSha256()
{ {
try try
{ {
std::string msg("Test this sign message"); std::string curveName = ECKey::getCurveName();
ECKey key("secp521r1"); if (!curveName.empty())
ECDSADigestEngine eng(key, "SHA256"); {
eng.update(msg.c_str(), static_cast<unsigned>(msg.length())); std::string msg("Test this sign message");
const Poco::DigestEngine::Digest& sig = eng.signature(); ECKey key(curveName);
ECDSADigestEngine eng(key, "SHA256");
eng.update(msg.c_str(), static_cast<unsigned>(msg.length()));
const Poco::DigestEngine::Digest& sig = eng.signature();
// verify // verify
std::ostringstream strPub; std::ostringstream strPub;
key.save(&strPub); key.save(&strPub);
std::string pubKey = strPub.str(); std::string pubKey = strPub.str();
std::istringstream iPub(pubKey); std::istringstream iPub(pubKey);
ECKey keyPub(&iPub); ECKey keyPub(&iPub);
ECDSADigestEngine eng2(keyPub, "SHA256"); ECDSADigestEngine eng2(keyPub, "SHA256");
eng2.update(msg.c_str(), static_cast<unsigned>(msg.length())); eng2.update(msg.c_str(), static_cast<unsigned>(msg.length()));
assert(eng2.verify(sig)); assert(eng2.verify(sig));
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {
@ -127,23 +145,29 @@ void ECTest::testECDSASignManipulated()
{ {
try try
{ {
std::string msg("Test this sign message"); std::string curveName = ECKey::getCurveName();
std::string msgManip("Test that sign message"); if (!curveName.empty())
ECKey key("secp521r1"); {
ECDSADigestEngine eng(key, "SHA256"); std::string msg("Test this sign message");
eng.update(msg.c_str(), static_cast<unsigned>(msg.length())); std::string msgManip("Test that sign message");
const Poco::DigestEngine::Digest& sig = eng.signature(); ECKey key(curveName);
std::string hexDig = Poco::DigestEngine::digestToHex(sig); ECDSADigestEngine eng(key, "SHA256");
eng.update(msg.c_str(), static_cast<unsigned>(msg.length()));
const Poco::DigestEngine::Digest& sig = eng.signature();
std::string hexDig = Poco::DigestEngine::digestToHex(sig);
// verify // verify
std::ostringstream strPub; std::ostringstream strPub;
key.save(&strPub); key.save(&strPub);
std::string pubKey = strPub.str(); std::string pubKey = strPub.str();
std::istringstream iPub(pubKey); std::istringstream iPub(pubKey);
ECKey keyPub(&iPub); ECKey keyPub(&iPub);
ECDSADigestEngine eng2(keyPub, "SHA256"); ECDSADigestEngine eng2(keyPub, "SHA256");
eng2.update(msgManip.c_str(), static_cast<unsigned>(msgManip.length())); eng2.update(msgManip.c_str(), static_cast<unsigned>(msgManip.length()));
assert (!eng2.verify(sig)); assert (!eng2.verify(sig));
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {

View File

@ -213,82 +213,88 @@ void EVPTest::testECEVPPKey()
{ {
try try
{ {
EVPPKey* pKey = new EVPPKey("secp521r1"); std::string curveName = ECKey::getCurveName();
assert (pKey != 0); if (!curveName.empty())
assert (!pKey->isSupported(0)); {
assert (!pKey->isSupported(-1)); EVPPKey*pKey = new EVPPKey(curveName);
assert (pKey->isSupported(pKey->type())); assert (pKey != 0);
assert (pKey->type() == EVP_PKEY_EC); assert (!pKey->isSupported(0));
assert (!pKey->isSupported(-1));
assert (pKey->isSupported(pKey->type()));
assert (pKey->type() == EVP_PKEY_EC);
BIO* bioPriv1 = BIO_new(BIO_s_mem()); BIO*bioPriv1 = BIO_new(BIO_s_mem());
BIO* bioPub1 = BIO_new(BIO_s_mem()); BIO*bioPub1 = BIO_new(BIO_s_mem());
assert (0 != PEM_write_bio_PrivateKey(bioPriv1, *pKey, NULL, NULL, 0, 0, NULL)); assert (0 != PEM_write_bio_PrivateKey(bioPriv1, *pKey, NULL, NULL, 0, 0, NULL));
assert (0 != PEM_write_bio_PUBKEY(bioPub1, *pKey)); assert (0 != PEM_write_bio_PUBKEY(bioPub1, *pKey));
char* pPrivData1; char*pPrivData1;
long sizePriv1 = BIO_get_mem_data(bioPriv1, &pPrivData1); long sizePriv1 = BIO_get_mem_data(bioPriv1, &pPrivData1);
char* pPubData1; char*pPubData1;
long sizePub1 = BIO_get_mem_data(bioPub1, &pPubData1); long sizePub1 = BIO_get_mem_data(bioPub1, &pPubData1);
// construct EVPPKey from EVP_PKEY* // construct EVPPKey from EVP_PKEY*
EVPPKey evpPKey(pKey->operator EVP_PKEY*()); EVPPKey evpPKey(pKey->operator EVP_PKEY*());
assert (evpPKey.type() == EVP_PKEY_EC); assert (evpPKey.type() == EVP_PKEY_EC);
// EVPPKey makes duplicate, so freeing the original must be ok // EVPPKey makes duplicate, so freeing the original must be ok
delete pKey; delete pKey;
BIO* bioPriv2 = BIO_new(BIO_s_mem()); BIO*bioPriv2 = BIO_new(BIO_s_mem());
BIO* bioPub2 = BIO_new(BIO_s_mem()); BIO*bioPub2 = BIO_new(BIO_s_mem());
assert (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey, NULL, NULL, 0, 0, NULL)); assert (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey, NULL, NULL, 0, 0, NULL));
assert (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey)); assert (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey));
char* pPrivData2; char*pPrivData2;
long sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2); long sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
char* pPubData2; char*pPubData2;
long sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2); long sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
assert (sizePriv1 && (sizePriv1 == sizePriv2)); assert (sizePriv1 && (sizePriv1 == sizePriv2));
assert (0 == memcmp(pPrivData1, pPrivData2, sizePriv1)); assert (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
assert (sizePub1 && (sizePub1 == sizePub2)); assert (sizePub1 && (sizePub1 == sizePub2));
assert (0 == memcmp(pPubData1, pPubData2, sizePub1)); assert (0 == memcmp(pPubData1, pPubData2, sizePub1));
BIO_free(bioPub2); BIO_free(bioPub2);
BIO_free(bioPriv2); BIO_free(bioPriv2);
// copy // copy
EVPPKey evpPKey2(evpPKey); EVPPKey evpPKey2(evpPKey);
assert (evpPKey2.type() == EVP_PKEY_EC); assert (evpPKey2.type() == EVP_PKEY_EC);
bioPriv2 = BIO_new(BIO_s_mem()); bioPriv2 = BIO_new(BIO_s_mem());
bioPub2 = BIO_new(BIO_s_mem()); bioPub2 = BIO_new(BIO_s_mem());
assert (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey2, NULL, NULL, 0, 0, NULL)); assert (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey2, NULL, NULL, 0, 0, NULL));
assert (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey2)); assert (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey2));
sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2); sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2); sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
assert (sizePriv1 && (sizePriv1 == sizePriv2)); assert (sizePriv1 && (sizePriv1 == sizePriv2));
assert (0 == memcmp(pPrivData1, pPrivData2, sizePriv1)); assert (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
assert (sizePub1 && (sizePub1 == sizePub2)); assert (sizePub1 && (sizePub1 == sizePub2));
assert (0 == memcmp(pPubData1, pPubData2, sizePub1)); assert (0 == memcmp(pPubData1, pPubData2, sizePub1));
BIO_free(bioPub2); BIO_free(bioPub2);
BIO_free(bioPriv2); BIO_free(bioPriv2);
// move // move
EVPPKey evpPKey3(std::move(evpPKey2)); EVPPKey evpPKey3(std::move(evpPKey2));
assert (evpPKey3.type() == EVP_PKEY_EC); assert (evpPKey3.type() == EVP_PKEY_EC);
bioPriv2 = BIO_new(BIO_s_mem()); bioPriv2 = BIO_new(BIO_s_mem());
bioPub2 = BIO_new(BIO_s_mem()); bioPub2 = BIO_new(BIO_s_mem());
assert (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey3, NULL, NULL, 0, 0, NULL)); assert (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey3, NULL, NULL, 0, 0, NULL));
assert (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey3)); assert (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey3));
sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2); sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2); sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
assert (sizePriv1 && (sizePriv1 == sizePriv2)); assert (sizePriv1 && (sizePriv1 == sizePriv2));
assert (0 == memcmp(pPrivData1, pPrivData2, sizePriv1)); assert (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
assert (sizePub1 && (sizePub1 == sizePub2)); assert (sizePub1 && (sizePub1 == sizePub2));
assert (0 == memcmp(pPubData1, pPubData2, sizePub1)); assert (0 == memcmp(pPubData1, pPubData2, sizePub1));
BIO_free(bioPub2); BIO_free(bioPub2);
BIO_free(bioPriv2); BIO_free(bioPriv2);
BIO_free(bioPub1); BIO_free(bioPub1);
BIO_free(bioPriv1); BIO_free(bioPriv1);
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {
@ -302,43 +308,49 @@ void EVPTest::testECEVPSaveLoadStream()
{ {
try try
{ {
EVPPKey key("secp521r1"); std::string curveName = ECKey::getCurveName();
std::ostringstream strPub; if (!curveName.empty())
std::ostringstream strPriv; {
key.save(&strPub, &strPriv, "testpwd"); EVPPKey key(curveName);
std::string pubKey = strPub.str(); std::ostringstream strPub;
std::string privKey = strPriv.str(); std::ostringstream strPriv;
key.save(&strPub, &strPriv, "testpwd");
std::string pubKey = strPub.str();
std::string privKey = strPriv.str();
// now do the round trip // now do the round trip
std::istringstream iPub(pubKey); std::istringstream iPub(pubKey);
std::istringstream iPriv(privKey); std::istringstream iPriv(privKey);
EVPPKey key2(&iPub, &iPriv, "testpwd"); EVPPKey key2(&iPub, &iPriv, "testpwd");
std::ostringstream strPubE; std::ostringstream strPubE;
std::ostringstream strPrivE; std::ostringstream strPrivE;
key2.save(&strPubE, &strPrivE, "testpwd"); key2.save(&strPubE, &strPrivE, "testpwd");
assert (strPubE.str() == pubKey); assert (strPubE.str() == pubKey);
/*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys /*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys
assert (key == key2); assert (key == key2);
assert (!(key != key2));*/ assert (!(key != key2));*/
ECKey ecKeyNE("secp112r2"); ECKey ecKeyNE("secp112r2");
EVPPKey keyNE(&ecKeyNE); EVPPKey keyNE(&ecKeyNE);
assert (key != keyNE); assert (key != keyNE);
assert (!(key == keyNE)); assert (!(key == keyNE));
assert (key2 != keyNE); assert (key2 != keyNE);
assert (!(key2 == keyNE)); assert (!(key2 == keyNE));
std::ostringstream strPub2; std::ostringstream strPub2;
std::ostringstream strPriv2; std::ostringstream strPriv2;
key2.save(&strPub2, &strPriv2, "testpwd"); key2.save(&strPub2, &strPriv2, "testpwd");
assert (strPub2.str() == pubKey); assert (strPub2.str() == pubKey);
std::istringstream iPriv2(strPriv2.str()); std::istringstream iPriv2(strPriv2.str());
EVPPKey key3(0, &iPriv2, "testpwd"); EVPPKey key3(0, &iPriv2, "testpwd");
std::ostringstream strPub3; std::ostringstream strPub3;
key3.save(&strPub3); key3.save(&strPub3);
std::string pubFromPrivate = strPub3.str(); std::string pubFromPrivate = strPub3.str();
assert (pubFromPrivate == pubKey); assert (pubFromPrivate == pubKey);
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {
@ -352,44 +364,50 @@ void EVPTest::testECEVPSaveLoadStreamNoPass()
{ {
try try
{ {
EVPPKey key("secp521r1"); std::string curveName = ECKey::getCurveName();
std::ostringstream strPub; if (!curveName.empty())
std::ostringstream strPriv; {
key.save(&strPub, &strPriv); EVPPKey key(curveName);
std::string pubKey = strPub.str(); std::ostringstream strPub;
std::string privKey = strPriv.str(); std::ostringstream strPriv;
key.save(&strPub, &strPriv);
std::string pubKey = strPub.str();
std::string privKey = strPriv.str();
// now do the round trip // now do the round trip
std::istringstream iPub(pubKey); std::istringstream iPub(pubKey);
std::istringstream iPriv(privKey); std::istringstream iPriv(privKey);
EVPPKey key2(&iPub, &iPriv); EVPPKey key2(&iPub, &iPriv);
std::ostringstream strPubE; std::ostringstream strPubE;
std::ostringstream strPrivE; std::ostringstream strPrivE;
key2.save(&strPubE, &strPrivE); key2.save(&strPubE, &strPrivE);
assert (strPubE.str() == pubKey); assert (strPubE.str() == pubKey);
/*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys /*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys
assert (key == key2); assert (key == key2);
assert (!(key != key2));*/ assert (!(key != key2));*/
ECKey ecKeyNE("secp112r2"); ECKey ecKeyNE("secp112r2");
EVPPKey keyNE(&ecKeyNE); EVPPKey keyNE(&ecKeyNE);
assert (key != keyNE); assert (key != keyNE);
assert (!(key == keyNE)); assert (!(key == keyNE));
assert (key2 != keyNE); assert (key2 != keyNE);
assert (!(key2 == keyNE)); assert (!(key2 == keyNE));
std::ostringstream strPub2; std::ostringstream strPub2;
std::ostringstream strPriv2; std::ostringstream strPriv2;
key2.save(&strPub2, &strPriv2); key2.save(&strPub2, &strPriv2);
assert (strPub2.str() == pubKey); assert (strPub2.str() == pubKey);
assert (strPriv2.str() == privKey); assert (strPriv2.str() == privKey);
std::istringstream iPriv2(privKey); std::istringstream iPriv2(privKey);
EVPPKey key3(0, &iPriv2); EVPPKey key3(0, &iPriv2);
std::ostringstream strPub3; std::ostringstream strPub3;
key3.save(&strPub3); key3.save(&strPub3);
std::string pubFromPrivate = strPub3.str(); std::string pubFromPrivate = strPub3.str();
assert (pubFromPrivate == pubKey); assert (pubFromPrivate == pubKey);
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {
@ -403,43 +421,49 @@ void EVPTest::testECEVPSaveLoadFile()
{ {
try try
{ {
EVPPKey key("secp521r1"); std::string curveName = ECKey::getCurveName();
TemporaryFile filePub; if (!curveName.empty())
TemporaryFile filePriv; {
key.save(filePub.path(), filePriv.path(), "testpwd"); EVPPKey key(curveName);
std::ifstream ifPub(filePub.path()); TemporaryFile filePub;
std::ifstream ifPriv(filePriv.path()); TemporaryFile filePriv;
std::string pubKey; key.save(filePub.path(), filePriv.path(), "testpwd");
std::string privKey; std::ifstream ifPub(filePub.path());
StreamCopier::copyToString(ifPub, pubKey); std::ifstream ifPriv(filePriv.path());
StreamCopier::copyToString(ifPriv, privKey); std::string pubKey;
std::string privKey;
StreamCopier::copyToString(ifPub, pubKey);
StreamCopier::copyToString(ifPriv, privKey);
EVPPKey key2(filePub.path(), filePriv.path(), "testpwd"); EVPPKey key2(filePub.path(), filePriv.path(), "testpwd");
std::ostringstream strPubE; std::ostringstream strPubE;
std::ostringstream strPrivE; std::ostringstream strPrivE;
key2.save(&strPubE, &strPrivE, "testpwd"); key2.save(&strPubE, &strPrivE, "testpwd");
assert (strPubE.str() == pubKey); assert (strPubE.str() == pubKey);
/*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys /*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys
assert (key == key2); assert (key == key2);
assert (!(key != key2));*/ assert (!(key != key2));*/
ECKey ecKeyNE("secp112r2"); ECKey ecKeyNE("secp112r2");
EVPPKey keyNE(&ecKeyNE); EVPPKey keyNE(&ecKeyNE);
assert (key != keyNE); assert (key != keyNE);
assert (!(key == keyNE)); assert (!(key == keyNE));
assert (key2 != keyNE); assert (key2 != keyNE);
assert (!(key2 == keyNE)); assert (!(key2 == keyNE));
std::ostringstream strPub2; std::ostringstream strPub2;
std::ostringstream strPriv2; std::ostringstream strPriv2;
key2.save(&strPub2, &strPriv2, "testpwd"); key2.save(&strPub2, &strPriv2, "testpwd");
assert (strPub2.str() == pubKey); assert (strPub2.str() == pubKey);
EVPPKey key3("", filePriv.path(), "testpwd"); EVPPKey key3("", filePriv.path(), "testpwd");
std::ostringstream strPub3; std::ostringstream strPub3;
key3.save(&strPub3); key3.save(&strPub3);
std::string pubFromPrivate = strPub3.str(); std::string pubFromPrivate = strPub3.str();
assert (pubFromPrivate == pubKey); assert (pubFromPrivate == pubKey);
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {
@ -453,28 +477,34 @@ void EVPTest::testECEVPSaveLoadFileNoPass()
{ {
try try
{ {
EVPPKey key("secp521r1"); std::string curveName = ECKey::getCurveName();
TemporaryFile filePub; if (!curveName.empty())
TemporaryFile filePriv; {
key.save(filePub.path(), filePriv.path()); EVPPKey key(curveName);
std::ifstream ifPub(filePub.path()); TemporaryFile filePub;
std::ifstream ifPriv(filePriv.path()); TemporaryFile filePriv;
std::string pubKey; key.save(filePub.path(), filePriv.path());
std::string privKey; std::ifstream ifPub(filePub.path());
StreamCopier::copyToString(ifPub, pubKey); std::ifstream ifPriv(filePriv.path());
StreamCopier::copyToString(ifPriv, privKey); std::string pubKey;
std::string privKey;
StreamCopier::copyToString(ifPub, pubKey);
StreamCopier::copyToString(ifPriv, privKey);
EVPPKey key2(filePub.path(), filePriv.path()); EVPPKey key2(filePub.path(), filePriv.path());
std::ostringstream strPub2; std::ostringstream strPub2;
std::ostringstream strPriv2; std::ostringstream strPriv2;
key2.save(&strPub2, &strPriv2); key2.save(&strPub2, &strPriv2);
assert (strPub2.str() == pubKey); assert (strPub2.str() == pubKey);
EVPPKey key3("", filePriv.path()); EVPPKey key3("", filePriv.path());
std::ostringstream strPub3; std::ostringstream strPub3;
key3.save(&strPub3); key3.save(&strPub3);
std::string pubFromPrivate = strPub3.str(); std::string pubFromPrivate = strPub3.str();
assert (pubFromPrivate == pubKey); assert (pubFromPrivate == pubKey);
}
else
std::cerr << "No elliptic curves found!" << std::endl;
} }
catch (Poco::Exception& ex) catch (Poco::Exception& ex)
{ {