mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-27 19:10:20 +01:00
Improve RSADigestEngine, using Poco::Crypto::DigestEngine to calculate
the hash before signing. That way we can then support RSA signatures with any hash supported by OpenSSL, not only MD5 and SHA1. It was also required a new method on DigestEngine to obtain the NID (numeric ID) of the algorithm, to be used on the OpenSSL RSA_sign call.
This commit is contained in:
@@ -67,6 +67,9 @@ public:
|
|||||||
const std::string& algorithm() const;
|
const std::string& algorithm() const;
|
||||||
/// Returns the name of the digest algorithm.
|
/// Returns the name of the digest algorithm.
|
||||||
|
|
||||||
|
int nid() const;
|
||||||
|
/// Returns the NID (OpenSSL object identifier) of the digest algorithm.
|
||||||
|
|
||||||
// DigestEngine
|
// DigestEngine
|
||||||
std::size_t digestLength() const;
|
std::size_t digestLength() const;
|
||||||
void reset();
|
void reset();
|
||||||
|
|||||||
@@ -43,8 +43,7 @@
|
|||||||
#include "Poco/Crypto/Crypto.h"
|
#include "Poco/Crypto/Crypto.h"
|
||||||
#include "Poco/Crypto/RSAKey.h"
|
#include "Poco/Crypto/RSAKey.h"
|
||||||
#include "Poco/DigestEngine.h"
|
#include "Poco/DigestEngine.h"
|
||||||
#include "Poco/MD5Engine.h"
|
#include "Poco/Crypto/DigestEngine.h"
|
||||||
#include "Poco/SHA1Engine.h"
|
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
@@ -58,10 +57,10 @@ class Crypto_API RSADigestEngine: public Poco::DigestEngine
|
|||||||
/// This class implements a Poco::DigestEngine that can be
|
/// This class implements a Poco::DigestEngine that can be
|
||||||
/// used to compute a secure digital signature.
|
/// used to compute a secure digital signature.
|
||||||
///
|
///
|
||||||
/// First another Poco::DigestEngine (Poco::MD5Engine
|
/// First another Poco::Crypto::DigestEngine is created and
|
||||||
/// or Poco::SHA1Engine) is used to compute a cryptographic
|
/// used to compute a cryptographic hash of the data to be
|
||||||
/// hash of the data to be signed. Then, the hash value is
|
/// signed. Then, the hash value is encrypted, using
|
||||||
/// encrypted, using the RSA private key.
|
/// the RSA private key.
|
||||||
///
|
///
|
||||||
/// To verify a signature, pass it to the verify()
|
/// To verify a signature, pass it to the verify()
|
||||||
/// member function. It will decrypt the signature
|
/// member function. It will decrypt the signature
|
||||||
@@ -75,9 +74,19 @@ public:
|
|||||||
DIGEST_SHA1
|
DIGEST_SHA1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//@ deprecated
|
||||||
RSADigestEngine(const RSAKey& key, DigestType digestType = DIGEST_SHA1);
|
RSADigestEngine(const RSAKey& key, DigestType digestType = DIGEST_SHA1);
|
||||||
/// Creates the RSADigestEngine with the given RSA key,
|
/// Creates the RSADigestEngine with the given RSA key,
|
||||||
/// using the SHA-1 hash algorithm.
|
/// using the MD5 or SHA-1 hash algorithm.
|
||||||
|
/// Kept for backward compatibility
|
||||||
|
|
||||||
|
RSADigestEngine(const RSAKey& key, const std::string &name);
|
||||||
|
/// Creates the RSADigestEngine with the given RSA key,
|
||||||
|
/// using the hash algorithm with the given name
|
||||||
|
/// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.).
|
||||||
|
/// See the OpenSSL documentation for a list of supported digest algorithms.
|
||||||
|
///
|
||||||
|
/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
|
||||||
|
|
||||||
~RSADigestEngine();
|
~RSADigestEngine();
|
||||||
/// Destroys the RSADigestEngine.
|
/// Destroys the RSADigestEngine.
|
||||||
@@ -113,12 +122,9 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
RSAKey _key;
|
RSAKey _key;
|
||||||
Poco::DigestEngine& _engine;
|
Poco::Crypto::DigestEngine _engine;
|
||||||
int _type;
|
|
||||||
Poco::DigestEngine::Digest _digest;
|
Poco::DigestEngine::Digest _digest;
|
||||||
Poco::DigestEngine::Digest _signature;
|
Poco::DigestEngine::Digest _signature;
|
||||||
Poco::MD5Engine _md5Engine;
|
|
||||||
Poco::SHA1Engine _sha1Engine;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ DigestEngine::~DigestEngine()
|
|||||||
EVP_MD_CTX_destroy(_ctx);
|
EVP_MD_CTX_destroy(_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DigestEngine::nid() const
|
||||||
|
{
|
||||||
|
return EVP_MD_nid(_ctx->digest);
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t DigestEngine::digestLength() const
|
std::size_t DigestEngine::digestLength() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "Poco/Crypto/RSADigestEngine.h"
|
#include "Poco/Crypto/RSADigestEngine.h"
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -44,8 +45,13 @@ namespace Crypto {
|
|||||||
|
|
||||||
RSADigestEngine::RSADigestEngine(const RSAKey& key, DigestType digestType):
|
RSADigestEngine::RSADigestEngine(const RSAKey& key, DigestType digestType):
|
||||||
_key(key),
|
_key(key),
|
||||||
_engine(digestType == DIGEST_MD5 ? static_cast<Poco::DigestEngine&>(_md5Engine) : static_cast<Poco::DigestEngine&>(_sha1Engine)),
|
_engine(digestType == DIGEST_MD5 ? "MD5" : "SHA1")
|
||||||
_type(digestType == DIGEST_MD5 ? NID_md5 : NID_sha1)
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RSADigestEngine::RSADigestEngine(const RSAKey& key, const std::string &algorithm):
|
||||||
|
_key(key),
|
||||||
|
_engine(algorithm)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +92,7 @@ const DigestEngine::Digest& RSADigestEngine::signature()
|
|||||||
digest();
|
digest();
|
||||||
_signature.resize(_key.size());
|
_signature.resize(_key.size());
|
||||||
unsigned sigLen = static_cast<unsigned>(_signature.size());
|
unsigned sigLen = static_cast<unsigned>(_signature.size());
|
||||||
RSA_sign(_type, &_digest[0], static_cast<unsigned>(_digest.size()), &_signature[0], &sigLen, _key.impl()->getRSA());
|
RSA_sign(_engine.nid(), &_digest[0], static_cast<unsigned>(_digest.size()), &_signature[0], &sigLen, _key.impl()->getRSA());
|
||||||
// truncate _sig to sigLen
|
// truncate _sig to sigLen
|
||||||
if (sigLen < _signature.size())
|
if (sigLen < _signature.size())
|
||||||
_signature.resize(sigLen);
|
_signature.resize(sigLen);
|
||||||
@@ -99,7 +105,7 @@ bool RSADigestEngine::verify(const DigestEngine::Digest& sig)
|
|||||||
{
|
{
|
||||||
digest();
|
digest();
|
||||||
DigestEngine::Digest sigCpy = sig; // copy becausse RSA_verify can modify sigCpy
|
DigestEngine::Digest sigCpy = sig; // copy becausse RSA_verify can modify sigCpy
|
||||||
int ret = RSA_verify(_type, &_digest[0], static_cast<unsigned>(_digest.size()), &sigCpy[0], static_cast<unsigned>(sigCpy.size()), _key.impl()->getRSA());
|
int ret = RSA_verify(_engine.nid(), &_digest[0], static_cast<unsigned>(_digest.size()), &sigCpy[0], static_cast<unsigned>(sigCpy.size()), _key.impl()->getRSA());
|
||||||
return ret != 0;
|
return ret != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,26 @@ void RSATest::testSign()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSATest::testSignSha256()
|
||||||
|
{
|
||||||
|
std::string msg("Test this sign message");
|
||||||
|
RSAKey key(RSAKey::KL_2048, RSAKey::EXP_LARGE);
|
||||||
|
RSADigestEngine 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
|
||||||
|
std::ostringstream strPub;
|
||||||
|
key.save(&strPub);
|
||||||
|
std::string pubKey = strPub.str();
|
||||||
|
std::istringstream iPub(pubKey);
|
||||||
|
RSAKey keyPub(&iPub);
|
||||||
|
RSADigestEngine eng2(key,"SHA256");
|
||||||
|
eng2.update(msg.c_str(), static_cast<unsigned>(msg.length()));
|
||||||
|
assert (eng2.verify(sig));
|
||||||
|
}
|
||||||
|
|
||||||
void RSATest::testSignManipulated()
|
void RSATest::testSignManipulated()
|
||||||
{
|
{
|
||||||
std::string msg("Test this sign message");
|
std::string msg("Test this sign message");
|
||||||
@@ -244,6 +264,7 @@ CppUnit::Test* RSATest::suite()
|
|||||||
|
|
||||||
CppUnit_addTest(pSuite, RSATest, testNewKeys);
|
CppUnit_addTest(pSuite, RSATest, testNewKeys);
|
||||||
CppUnit_addTest(pSuite, RSATest, testSign);
|
CppUnit_addTest(pSuite, RSATest, testSign);
|
||||||
|
CppUnit_addTest(pSuite, RSATest, testSignSha256);
|
||||||
CppUnit_addTest(pSuite, RSATest, testSignManipulated);
|
CppUnit_addTest(pSuite, RSATest, testSignManipulated);
|
||||||
CppUnit_addTest(pSuite, RSATest, testRSACipher);
|
CppUnit_addTest(pSuite, RSATest, testRSACipher);
|
||||||
CppUnit_addTest(pSuite, RSATest, testRSACipherLarge);
|
CppUnit_addTest(pSuite, RSATest, testRSACipherLarge);
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public:
|
|||||||
|
|
||||||
void testNewKeys();
|
void testNewKeys();
|
||||||
void testSign();
|
void testSign();
|
||||||
|
void testSignSha256();
|
||||||
void testSignManipulated();
|
void testSignManipulated();
|
||||||
void testRSACipher();
|
void testRSACipher();
|
||||||
void testRSACipherLarge();
|
void testRSACipherLarge();
|
||||||
|
|||||||
Reference in New Issue
Block a user