Skip to content

Commit

Permalink
EVPPKey constructor for modulus/exponent (#4025)
Browse files Browse the repository at this point in the history
* Create EVPPkey from modulus and exponent

Add constructor for creating EVPPkey (RSA) using modulus and exponent

* Add EVPPKey constructor for modulus/exponent

* Add testEVPKeyByModulus

* fix test for mudulus

* Update EVPTest.cpp
  • Loading branch information
micheleselea authored Jun 21, 2023
1 parent ade5f83 commit ead93ba
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 2 deletions.
8 changes: 7 additions & 1 deletion Crypto/include/Poco/Crypto/EVPPKey.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ class Crypto_API EVPPKey

#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
explicit EVPPKey(const std::vector<unsigned char>* public_key, const std::vector<unsigned char>* private_key, unsigned long exponent, int type);
#endif

explicit EVPPKey(EVP_PKEY* pEVPPKey);
/// Constructs EVPPKey from EVP_PKEY pointer.
/// The content behind the supplied pointer is internally duplicated.
Expand Down Expand Up @@ -173,7 +177,9 @@ class Crypto_API EVPPKey

private:
EVPPKey();

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
void SetKeyFromParameters(OSSL_PARAM* parameters);
#endif
static int type(const EVP_PKEY* pEVPPKey);
void checkType();
void newECKey(const char* group);
Expand Down
53 changes: 53 additions & 0 deletions Crypto/src/EVPPKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include "Poco/NumberFormatter.h"
#include <iostream>

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/param_build.h>
#endif

namespace Poco {
namespace Crypto {
Expand Down Expand Up @@ -66,7 +69,57 @@ EVPPKey::EVPPKey(const PKCS12Container& cont): EVPPKey(cont.getKey())
checkType();
}

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
void PushBuildParamBignum(OSSL_PARAM_BLD* param_bld, const char* key, const std::vector<unsigned char>& bytes) {
BIGNUM* bignum = BN_bin2bn(bytes.data(), (int)bytes.size(), nullptr);
OSSL_PARAM_BLD_push_BN(param_bld, key, bignum);
}
OSSL_PARAM* GetKeyParameters(const std::vector<unsigned char>* public_key, const std::vector<unsigned char>* private_key) {
auto param_bld = OSSL_PARAM_BLD_new();

if (public_key != nullptr) {
PushBuildParamBignum(param_bld, "n", *public_key);
}

if (private_key != nullptr) {
PushBuildParamBignum(param_bld, "d", *private_key);
}

// default rsa exponent
OSSL_PARAM_BLD_push_ulong(param_bld, "e", RSA_F4);

auto parameters = OSSL_PARAM_BLD_to_param(param_bld);
OSSL_PARAM_BLD_free(param_bld);

return parameters;
}
void EVPPKey::SetKeyFromParameters(OSSL_PARAM* parameters) {
auto ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr);
if (EVP_PKEY_fromdata_init(ctx) <= 0) {
OSSL_PARAM_free(parameters);
throw OpenSSLException("EVPPKey cannot init create key");
}

if (_pEVPPKey != 0) EVP_PKEY_free(_pEVPPKey);
if (EVP_PKEY_fromdata(ctx, &_pEVPPKey, EVP_PKEY_KEYPAIR, parameters) <= 0) {
OSSL_PARAM_free(parameters);
throw OpenSSLException("EVPPKey cannot create key");
}
}

EVPPKey::EVPPKey(const std::vector<unsigned char>* public_key, const std::vector<unsigned char>* private_key, unsigned long exponent, int type) : _pEVPPKey(0)
{
if ((EVP_PKEY_RSA != type) || (RSA_F4 != exponent)) {
std::string msg = Poco::format("EVPPKey(%d):Invalid format\n", type);
throw OpenSSLException(getError(msg));
}

OSSL_PARAM* parameters = GetKeyParameters(public_key, private_key);
SetKeyFromParameters(parameters);
OSSL_PARAM_free(parameters);
}
#endif

#if OPENSSL_VERSION_NUMBER >= 0x10000000L

EVPPKey::EVPPKey(int type, int param): _pEVPPKey(0)
Expand Down
37 changes: 37 additions & 0 deletions Crypto/testsuite/src/EVPTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#include "Poco/Crypto/Cipher.h"
#include "Poco/Crypto/X509Certificate.h"
#include "Poco/TemporaryFile.h"
#include "Poco/Base64Decoder.h"
#include "Poco/Base64Encoder.h"
#include "Poco/MemoryStream.h"
#include "Poco/StreamCopier.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
Expand Down Expand Up @@ -682,6 +685,39 @@ void EVPTest::testECEVPKeyByLength()
}
}

void EVPTest::testEVPKeyByModulus()
{
std::string e = "AQAB";
std::string n = "ylJgMkU_bDwCLzMlo47igdZ-AC8oUbtGJUOUHnuJdjflpim7FOxw0zXYf9m0tzND0Bt1y7MPyVtf-3rwInvdgi65CZEJ3kt5PE0g6trPbvyW6hJcVeOsQvSErj33mY6RsjndLhNE-RY36G8o603au64lTOYSb9HjzzRFo4F_faEgQ02jpEYkLIWwf7PboExDbd6NGMV0uume8YA6eB3z5BwfMMHyRZA0FcIzj6F0V-hDqBaJkWegpJsukgpfO7JDKaU5rlor7j6CdbfLaWorYTCUH3F-bXZ1ojBe0wHRGEgEZBNa46A3clgNohQuuNzf4K12NFGnEl_TIFRcLm6M0Q";
try
{
unsigned long exponent = 0;
if ((e == "AQAB") || (e == "AAEAAQ"))
{
exponent = RSA_F4; //Poco::Crypto::RSAKey::Exponent::EXP_LARGE
}
else
{
std::cerr << "invalid exponent" << std::endl;
throw;
}
std::string nBinary;
std::ostringstream ofs;
Poco::MemoryInputStream cIn(n.data(), n.length());
Poco::Base64Decoder decoder(cIn, Poco::Base64EncodingOptions::BASE64_URL_ENCODING | Poco::Base64EncodingOptions::BASE64_NO_PADDING);
Poco::StreamCopier::copyStream(decoder, ofs);
nBinary=ofs.str();
std::vector<unsigned char> public_key(nBinary.begin(), nBinary.end());
Poco::Crypto::EVPPKey cKey(&public_key, nullptr, exponent, EVP_PKEY_RSA);
Poco::SharedPtr<Poco::Crypto::RSAKey> pKey = new Poco::Crypto::RSAKey(cKey);
}
catch(Poco::Exception& ex)
{
std::cerr << ex.displayText() << std::endl;
throw;
}
}

#endif // OPENSSL_VERSION_NUMBER >= 0x30000000
#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L

Expand Down Expand Up @@ -714,6 +750,7 @@ CppUnit::Test* EVPTest::suite()
CppUnit_addTest(pSuite, EVPTest, testRSAEVPKeyByLength);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
CppUnit_addTest(pSuite, EVPTest, testECEVPKeyByLength);
CppUnit_addTest(pSuite, EVPTest, testEVPKeyByModulus);
#endif // OPENSSL_VERSION_NUMBER >= 0x30000000
#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L

Expand Down
3 changes: 2 additions & 1 deletion Crypto/testsuite/src/EVPTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class EVPTest: public CppUnit::TestCase
void testRSAEVPKeyByLength();
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
void testECEVPKeyByLength();
void testEVPKeyByModulus();
#endif // OPENSSL_VERSION_NUMBER >= 0x30000000L
#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L

Expand All @@ -53,4 +54,4 @@ class EVPTest: public CppUnit::TestCase
};


#endif // EVPTest_INCLUDED
#endif // EVPTest_INCLUDED

0 comments on commit ead93ba

Please sign in to comment.