mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 02:22:57 +01:00
Crypto_Win (compile only, WIP)
This commit is contained in:
parent
5f9a2cb6c3
commit
06d18d2b9c
@ -48,7 +48,7 @@ public:
|
||||
Cipher* createCipher(const CipherKey& key);
|
||||
/// Creates a Cipher object for the given CipherKey.
|
||||
|
||||
//Cipher* createCipher(const RSAKey& key, RSAPaddingMode paddingMode = RSA_PADDING_PKCS1);
|
||||
Cipher* createCipher(const RSAKey& key, RSAPaddingMode paddingMode = RSA_PADDING_PKCS1);
|
||||
/// Creates a RSACipher using the given RSA key and padding mode
|
||||
/// for public key encryption/private key decryption.
|
||||
|
||||
|
@ -57,12 +57,12 @@ public:
|
||||
/// Returns the name of the digest algorithm.
|
||||
|
||||
// DigestEngine
|
||||
unsigned digestLength() const;
|
||||
std::size_t digestLength() const;
|
||||
void reset();
|
||||
const Poco::DigestEngine::Digest& digest();
|
||||
|
||||
protected:
|
||||
void updateImpl(const void* data, unsigned length);
|
||||
void updateImpl(const void* data, std::size_t length);
|
||||
|
||||
private:
|
||||
ServiceProvider _sp;
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
~RSADigestEngine();
|
||||
/// Destroys the RSADigestEngine.
|
||||
|
||||
unsigned digestLength() const;
|
||||
std::size_t digestLength() const;
|
||||
/// Returns the length of the digest in bytes.
|
||||
|
||||
void reset();
|
||||
@ -88,16 +88,16 @@ public:
|
||||
/// Returns true if the signature can be verified, false otherwise.
|
||||
|
||||
protected:
|
||||
void updateImpl(const void* data, unsigned length);
|
||||
void updateImpl(const void* data, std::size_t length);
|
||||
|
||||
private:
|
||||
RSAKey _key;
|
||||
Poco::DigestEngine& _engine;
|
||||
int _type;
|
||||
RSAKey _key;
|
||||
Poco::DigestEngine& _engine;
|
||||
LPSTR _type;
|
||||
Poco::DigestEngine::Digest _digest;
|
||||
Poco::DigestEngine::Digest _signature;
|
||||
Poco::MD5Engine _md5Engine;
|
||||
Poco::SHA1Engine _sha1Engine;
|
||||
Poco::MD5Engine _md5Engine;
|
||||
Poco::SHA1Engine _sha1Engine;
|
||||
};
|
||||
|
||||
|
||||
|
@ -28,12 +28,12 @@
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/*
|
||||
struct bignum_st;
|
||||
struct rsa_st;
|
||||
typedef struct bignum_st BIGNUM;
|
||||
typedef struct rsa_st RSA;
|
||||
|
||||
*/
|
||||
|
||||
namespace Poco {
|
||||
namespace Crypto {
|
||||
@ -90,6 +90,8 @@ public:
|
||||
/// Returns the underlying Windows-specific handle for the public key.
|
||||
|
||||
protected:
|
||||
const ServiceProvider& serviceProvider() const;
|
||||
|
||||
void loadPrivateKey(std::istream& istr);
|
||||
void loadPublicKey(std::istream& istr);
|
||||
void savePrivateKey(std::ostream& ostr);
|
||||
@ -99,19 +101,28 @@ private:
|
||||
ServiceProvider _sp;
|
||||
HCRYPTKEY _hPrivateKey;
|
||||
HCRYPTKEY _hPublicKey;
|
||||
|
||||
friend class RSACipherImpl;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
HCRYPTKEY RSAKeyImpl::privateKey() const
|
||||
|
||||
inline const ServiceProvider& RSAKeyImpl::serviceProvider() const
|
||||
{
|
||||
return _sp;
|
||||
}
|
||||
|
||||
|
||||
inline HCRYPTKEY RSAKeyImpl::privateKey() const
|
||||
{
|
||||
return _hPrivateKey;
|
||||
}
|
||||
|
||||
|
||||
HCRYPTKEY RSAKeyImpl::publicKey() const
|
||||
inline HCRYPTKEY RSAKeyImpl::publicKey() const
|
||||
{
|
||||
return _hPublicKey;
|
||||
}
|
||||
|
@ -17,9 +17,9 @@
|
||||
#include "Poco/Crypto/CipherFactory.h"
|
||||
#include "Poco/Crypto/Cipher.h"
|
||||
#include "Poco/Crypto/CipherKey.h"
|
||||
//#include "Poco/Crypto/RSAKey.h"
|
||||
#include "Poco/Crypto/RSAKey.h"
|
||||
#include "Poco/Crypto/CipherImpl.h"
|
||||
//#include "Poco/Crypto/RSACipherImpl.h"
|
||||
#include "Poco/Crypto/RSACipherImpl.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
|
||||
@ -55,12 +55,11 @@ Cipher* CipherFactory::createCipher(const CipherKey& key)
|
||||
return new CipherImpl(key);
|
||||
}
|
||||
|
||||
// TODO RSA
|
||||
/*
|
||||
|
||||
Cipher* CipherFactory::createCipher(const RSAKey& key, RSAPaddingMode paddingMode)
|
||||
{
|
||||
return new RSACipherImpl(key, paddingMode);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
|
@ -580,7 +580,7 @@ void CipherKeyImpl::generateKey(
|
||||
int keySz = keySize();
|
||||
int ivSz = ivSize();
|
||||
int requiredSz = keySz + ivSz;
|
||||
int availableSz = d.size();
|
||||
int availableSz = static_cast<int>(d.size());
|
||||
int k = 1;
|
||||
Poco::DigestEngine::Digest extraD(d);
|
||||
while (availableSz < requiredSz)
|
||||
@ -596,7 +596,7 @@ void CipherKeyImpl::generateKey(
|
||||
md5.update(&extraD[0], extraD.size());
|
||||
extraD = md5.digest();
|
||||
}
|
||||
availableSz += extraD.size();
|
||||
availableSz += static_cast<int>(extraD.size());
|
||||
d.insert(d.end(), extraD.begin(), extraD.end());
|
||||
}
|
||||
|
||||
@ -686,7 +686,7 @@ void CipherKeyImpl::importKey()
|
||||
HCRYPTKEY hPubPrivKey = 0;
|
||||
BOOL rc = CreatePrivateExponentOneKey(_sp.handle(), AT_KEYEXCHANGE, &hPubPrivKey);
|
||||
if (!rc) throw Poco::SystemException("cannot create private key for importing key", GetLastError());
|
||||
rc = ImportPlainSessionBlob(_sp.handle(), hPubPrivKey, _id, &_key[0], _key.size(), &_hKey);
|
||||
rc = ImportPlainSessionBlob(_sp.handle(), hPubPrivKey, _id, &_key[0], static_cast<DWORD>(_key.size()), &_hKey);
|
||||
CryptDestroyKey(hPubPrivKey);
|
||||
if (!rc) throw Poco::SystemException("cannot import key", GetLastError());
|
||||
}
|
||||
|
@ -37,12 +37,12 @@ DigestEngine::~DigestEngine()
|
||||
}
|
||||
|
||||
|
||||
unsigned DigestEngine::digestLength() const
|
||||
std::size_t DigestEngine::digestLength() const
|
||||
{
|
||||
DWORD hashLen;
|
||||
DWORD len = sizeof(hashLen);
|
||||
if (CryptGetHashParam(_handle, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashLen), &len, 0))
|
||||
return static_cast<unsigned>(hashLen);
|
||||
return static_cast<std::size_t>(hashLen);
|
||||
else
|
||||
throw Poco::SystemException("Failed to obtain hash size", GetLastError());
|
||||
}
|
||||
@ -80,9 +80,9 @@ void DigestEngine::reset()
|
||||
const Poco::DigestEngine::Digest& DigestEngine::digest()
|
||||
{
|
||||
_digest.clear();
|
||||
unsigned hashLen = digestLength();
|
||||
std::size_t hashLen = digestLength();
|
||||
_digest.resize(hashLen);
|
||||
DWORD len = hashLen;
|
||||
DWORD len = static_cast<DWORD>(hashLen);
|
||||
if (!CryptGetHashParam(_handle, HP_HASHVAL, &_digest[0], &len, 0))
|
||||
throw Poco::SystemException("Failed to obtain hash", GetLastError());
|
||||
reset();
|
||||
@ -90,9 +90,9 @@ const Poco::DigestEngine::Digest& DigestEngine::digest()
|
||||
}
|
||||
|
||||
|
||||
void DigestEngine::updateImpl(const void* data, unsigned length)
|
||||
void DigestEngine::updateImpl(const void* data, std::size_t length)
|
||||
{
|
||||
if (!CryptHashData(_handle, reinterpret_cast<const BYTE*>(data), length, 0))
|
||||
if (!CryptHashData(_handle, reinterpret_cast<const BYTE*>(data), static_cast<DWORD>(length), 0))
|
||||
throw Poco::SystemException("Failed to hash data", GetLastError());
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "Poco/Crypto/RSACipherImpl.h"
|
||||
#include "Poco/Crypto/CryptoTransform.h"
|
||||
#include "Poco/Error.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
@ -29,43 +30,79 @@ namespace
|
||||
{
|
||||
void throwError()
|
||||
{
|
||||
unsigned long err;
|
||||
std::string msg;
|
||||
|
||||
while ((err = ERR_get_error()))
|
||||
{
|
||||
if (!msg.empty())
|
||||
msg.append("; ");
|
||||
msg.append(ERR_error_string(err, 0));
|
||||
}
|
||||
|
||||
throw Poco::IOException(msg);
|
||||
DWORD err = Error::last();
|
||||
std::string errStr = Error::getMessage(err);
|
||||
throw Poco::IOException(errStr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int mapPaddingMode(RSAPaddingMode paddingMode)
|
||||
{
|
||||
switch (paddingMode)
|
||||
{
|
||||
case RSA_PADDING_PKCS1:
|
||||
return RSA_PKCS1_PADDING;
|
||||
return BCRYPT_PAD_PKCS1;
|
||||
case RSA_PADDING_PKCS1_OAEP:
|
||||
return RSA_PKCS1_OAEP_PADDING;
|
||||
case RSA_PADDING_SSLV23:
|
||||
return RSA_SSLV23_PADDING;
|
||||
return BCRYPT_PAD_OAEP;
|
||||
//case RSA_PADDING_SSLV23: ???
|
||||
// return RSA_SSLV23_PADDING;
|
||||
case RSA_PADDING_NONE:
|
||||
return RSA_NO_PADDING;
|
||||
return BCRYPT_PAD_NONE;
|
||||
default:
|
||||
poco_bugcheck();
|
||||
return RSA_NO_PADDING;
|
||||
return BCRYPT_PAD_NONE;
|
||||
// BCRYPT_PAD_PSS ???
|
||||
//
|
||||
// ???
|
||||
// #if (NTDDI_VERSION >= NTDDI_WINBLUE)
|
||||
// #define BCRYPT_PAD_PKCS1_OPTIONAL_HASH_OID 0x00000010 //BCryptVerifySignature
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
std::size_t rsaBlockSize(const ServiceProvider& rsa)
|
||||
{
|
||||
BYTE* pbData = NULL;
|
||||
DWORD dwDataLen = 0;
|
||||
// ??? (from documentation) "This function must not be used on a thread of a multithreaded program." ???
|
||||
if (CryptGetProvParam(rsa.handle(), PP_SESSION_KEYSIZE, NULL, &dwDataLen, 0))
|
||||
{
|
||||
std::vector<BYTE> data(dwDataLen);
|
||||
pbData = &data[0];
|
||||
if (CryptGetProvParam(rsa.handle(), PP_SESSION_KEYSIZE, pbData, &dwDataLen, 0))
|
||||
{
|
||||
// ??? what is in pbData? DWORD? BYTE? TODO: check at runtime
|
||||
}
|
||||
else // !CryptGetProvParam
|
||||
{
|
||||
DWORD err = Error::last();
|
||||
std::string errStr = "[RSAEncryptImpl::blockSize()]: ";
|
||||
errStr += Error::getMessage(err);
|
||||
switch (err)
|
||||
{
|
||||
case ERROR_INVALID_HANDLE: case ERROR_INVALID_PARAMETER:
|
||||
case ERROR_MORE_DATA: case NTE_BAD_FLAGS:
|
||||
case NTE_BAD_TYPE: case NTE_BAD_UID:
|
||||
throw Poco::InvalidArgumentException(errStr);
|
||||
default:
|
||||
throw Poco::SystemException(errStr);
|
||||
}
|
||||
}
|
||||
} // !CryptGetProvParam length
|
||||
else
|
||||
{
|
||||
throw Poco::SystemException("Cannot obtain length for block size value.");
|
||||
}
|
||||
|
||||
return static_cast<std::size_t>(dwDataLen);
|
||||
}
|
||||
|
||||
|
||||
class RSAEncryptImpl: public CryptoTransform
|
||||
{
|
||||
public:
|
||||
RSAEncryptImpl(const RSA* pRSA, RSAPaddingMode paddingMode);
|
||||
RSAEncryptImpl(const ServiceProvider& rsa, RSAPaddingMode paddingMode);
|
||||
~RSAEncryptImpl();
|
||||
|
||||
std::size_t blockSize() const;
|
||||
@ -80,15 +117,17 @@ namespace
|
||||
std::streamsize finalize(unsigned char* output, std::streamsize length);
|
||||
|
||||
private:
|
||||
const RSA* _pRSA;
|
||||
RSAPaddingMode _paddingMode;
|
||||
std::streamsize _pos;
|
||||
unsigned char* _pBuf;
|
||||
DWORD encrypt(unsigned char* output, std::streamsize outputLength, BOOL isFinal);
|
||||
|
||||
const ServiceProvider& _rsa;
|
||||
RSAPaddingMode _paddingMode;
|
||||
std::streamsize _pos;
|
||||
unsigned char* _pBuf;
|
||||
};
|
||||
|
||||
|
||||
RSAEncryptImpl::RSAEncryptImpl(const RSA* pRSA, RSAPaddingMode paddingMode):
|
||||
_pRSA(pRSA),
|
||||
RSAEncryptImpl::RSAEncryptImpl(const ServiceProvider& rsa, RSAPaddingMode paddingMode) :
|
||||
_rsa(rsa),
|
||||
_paddingMode(paddingMode),
|
||||
_pos(0),
|
||||
_pBuf(0)
|
||||
@ -105,12 +144,13 @@ namespace
|
||||
|
||||
std::size_t RSAEncryptImpl::blockSize() const
|
||||
{
|
||||
return RSA_size(_pRSA);
|
||||
return rsaBlockSize(_rsa);
|
||||
}
|
||||
|
||||
|
||||
std::size_t RSAEncryptImpl::maxDataSize() const
|
||||
{
|
||||
// ??? same as openssl?
|
||||
std::size_t size = blockSize();
|
||||
switch (_paddingMode)
|
||||
{
|
||||
@ -127,12 +167,27 @@ namespace
|
||||
return size;
|
||||
}
|
||||
|
||||
DWORD RSAEncryptImpl::encrypt(unsigned char* output, std::streamsize outputLength, BOOL isFinal)
|
||||
{
|
||||
DWORD n = static_cast<DWORD>(_pos + 1);
|
||||
if (!CryptEncrypt(_rsa.handle(), NULL, isFinal, 0, NULL, &n, 0))
|
||||
throwError();
|
||||
poco_assert(n > _pos);
|
||||
poco_assert_dbg(n <= maxDataSize());
|
||||
std::vector<BYTE> data(n);
|
||||
n = static_cast<DWORD>(_pos + 1);
|
||||
std::memcpy(&data[0], _pBuf, n);
|
||||
if (!CryptEncrypt(_rsa.handle(), NULL, isFinal, 0, &data[0], &n, n))
|
||||
throwError();
|
||||
poco_assert(n <= outputLength);
|
||||
std::memcpy(output, &data[0], n);
|
||||
return n;
|
||||
}
|
||||
|
||||
std::streamsize RSAEncryptImpl::transform(
|
||||
const unsigned char* input,
|
||||
std::streamsize inputLength,
|
||||
unsigned char* output,
|
||||
std::streamsize outputLength)
|
||||
std::streamsize RSAEncryptImpl::transform(const unsigned char* input,
|
||||
std::streamsize inputLength,
|
||||
unsigned char* output,
|
||||
std::streamsize outputLength)
|
||||
{
|
||||
// always fill up the buffer before writing!
|
||||
std::streamsize maxSize = static_cast<std::streamsize>(maxDataSize());
|
||||
@ -148,14 +203,13 @@ namespace
|
||||
if (missing == 0)
|
||||
{
|
||||
poco_assert (outputLength >= rsaSize);
|
||||
int n = RSA_public_encrypt(static_cast<int>(maxSize), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
|
||||
if (n == -1)
|
||||
throwError();
|
||||
//int n = 0;
|
||||
//int n = RSA_public_encrypt(static_cast<int>(maxSize), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
|
||||
DWORD n = encrypt(output, outputLength, FALSE);
|
||||
rc += n;
|
||||
output += n;
|
||||
outputLength -= n;
|
||||
_pos = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -179,8 +233,9 @@ namespace
|
||||
int rc = 0;
|
||||
if (_pos > 0)
|
||||
{
|
||||
rc = RSA_public_encrypt(static_cast<int>(_pos), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
|
||||
if (rc == -1) throwError();
|
||||
//rc = RSA_public_encrypt(static_cast<int>(_pos), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
|
||||
//if (rc == -1) throwError();
|
||||
rc = encrypt(output, length, TRUE);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -189,7 +244,7 @@ namespace
|
||||
class RSADecryptImpl: public CryptoTransform
|
||||
{
|
||||
public:
|
||||
RSADecryptImpl(const RSA* pRSA, RSAPaddingMode paddingMode);
|
||||
RSADecryptImpl(const ServiceProvider& rsa, RSAPaddingMode paddingMode);
|
||||
~RSADecryptImpl();
|
||||
|
||||
std::size_t blockSize() const;
|
||||
@ -205,15 +260,17 @@ namespace
|
||||
std::streamsize length);
|
||||
|
||||
private:
|
||||
const RSA* _pRSA;
|
||||
RSAPaddingMode _paddingMode;
|
||||
std::streamsize _pos;
|
||||
unsigned char* _pBuf;
|
||||
DWORD decrypt(unsigned char* output, std::streamsize outputLength, BOOL isFinal);
|
||||
|
||||
const ServiceProvider& _rsa;
|
||||
RSAPaddingMode _paddingMode;
|
||||
std::streamsize _pos;
|
||||
unsigned char* _pBuf;
|
||||
};
|
||||
|
||||
|
||||
RSADecryptImpl::RSADecryptImpl(const RSA* pRSA, RSAPaddingMode paddingMode):
|
||||
_pRSA(pRSA),
|
||||
RSADecryptImpl::RSADecryptImpl(const ServiceProvider& rsa, RSAPaddingMode paddingMode) :
|
||||
_rsa(rsa),
|
||||
_paddingMode(paddingMode),
|
||||
_pos(0),
|
||||
_pBuf(0)
|
||||
@ -230,7 +287,24 @@ namespace
|
||||
|
||||
std::size_t RSADecryptImpl::blockSize() const
|
||||
{
|
||||
return RSA_size(_pRSA);
|
||||
return rsaBlockSize(_rsa);
|
||||
}
|
||||
|
||||
DWORD RSADecryptImpl::decrypt(unsigned char* output, std::streamsize outputLength, BOOL isFinal)
|
||||
{
|
||||
DWORD n = static_cast<DWORD>(_pos + 1);
|
||||
if (!CryptDecrypt(_rsa.handle(), NULL, isFinal, 0, NULL, &n))
|
||||
throwError();
|
||||
poco_assert(n > _pos);
|
||||
//poco_assert_dbg(n <= maxDataSize());
|
||||
std::vector<BYTE> data(n);
|
||||
n = static_cast<DWORD>(_pos + 1);
|
||||
std::memcpy(&data[0], _pBuf, n);
|
||||
if (!CryptDecrypt(_rsa.handle(), NULL, isFinal, 0, &data[0], &n))
|
||||
throwError();
|
||||
poco_assert(n <= outputLength);
|
||||
std::memcpy(output, &data[0], n);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@ -253,7 +327,8 @@ namespace
|
||||
std::streamsize missing = rsaSize - _pos;
|
||||
if (missing == 0)
|
||||
{
|
||||
int tmp = RSA_private_decrypt(static_cast<int>(rsaSize), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
|
||||
//int tmp = RSA_private_decrypt(static_cast<int>(rsaSize), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
|
||||
DWORD tmp = decrypt(output, outputLength, FALSE);
|
||||
if (tmp == -1)
|
||||
throwError();
|
||||
rc += tmp;
|
||||
@ -283,7 +358,8 @@ namespace
|
||||
int rc = 0;
|
||||
if (_pos > 0)
|
||||
{
|
||||
rc = RSA_private_decrypt(static_cast<int>(_pos), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
|
||||
//rc = RSA_private_decrypt(static_cast<int>(_pos), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
|
||||
rc = decrypt(output, length, TRUE);
|
||||
if (rc == -1)
|
||||
throwError();
|
||||
}
|
||||
@ -306,13 +382,13 @@ RSACipherImpl::~RSACipherImpl()
|
||||
|
||||
CryptoTransform* RSACipherImpl::createEncryptor()
|
||||
{
|
||||
return new RSAEncryptImpl(_key.impl()->getRSA(), _paddingMode);
|
||||
return new RSAEncryptImpl(_key.impl()->serviceProvider(), _paddingMode);
|
||||
}
|
||||
|
||||
|
||||
CryptoTransform* RSACipherImpl::createDecryptor()
|
||||
{
|
||||
return new RSADecryptImpl(_key.impl()->getRSA(), _paddingMode);
|
||||
return new RSADecryptImpl(_key.impl()->serviceProvider(), _paddingMode);
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,10 +14,11 @@
|
||||
//
|
||||
|
||||
|
||||
#include "
|
||||
|
||||
|
||||
// TODO: this is still OpenSSL code
|
||||
#include "Poco/Crypto/RSADigestEngine.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Error.h"
|
||||
#include "Poco/Base64Encoder.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@ -27,7 +28,7 @@ namespace Crypto {
|
||||
RSADigestEngine::RSADigestEngine(const RSAKey& key, DigestType digestType):
|
||||
_key(key),
|
||||
_engine(digestType == DIGEST_MD5 ? static_cast<Poco::DigestEngine&>(_md5Engine) : static_cast<Poco::DigestEngine&>(_sha1Engine)),
|
||||
_type(digestType == DIGEST_MD5 ? NID_md5 : NID_sha1)
|
||||
_type(digestType == DIGEST_MD5 ? szOID_RSA_MD5 : szOID_ECDSA_SHA1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -37,7 +38,7 @@ RSADigestEngine::~RSADigestEngine()
|
||||
}
|
||||
|
||||
|
||||
unsigned RSADigestEngine::digestLength() const
|
||||
std::size_t RSADigestEngine::digestLength() const
|
||||
{
|
||||
return _engine.digestLength();
|
||||
}
|
||||
@ -66,27 +67,70 @@ const DigestEngine::Digest& RSADigestEngine::signature()
|
||||
if (_signature.empty())
|
||||
{
|
||||
digest();
|
||||
_signature.resize(_key.size());
|
||||
unsigned sigLen = static_cast<unsigned>(_signature.size());
|
||||
RSA_sign(_type, &_digest[0], static_cast<unsigned>(_digest.size()), &_signature[0], &sigLen, _key.impl()->getRSA());
|
||||
// truncate _sig to sigLen
|
||||
if (sigLen < _signature.size())
|
||||
_signature.resize(sigLen);
|
||||
|
||||
std::string begin = "-----BEGIN RSA PUBLIC KEY-----\n";
|
||||
//TODO: base64 encode data and pass to CryptImportKey API
|
||||
std::string sig(_digest.begin(), _digest.end());
|
||||
std::string end = "\n-----END RSA PUBLIC KEY-----";
|
||||
|
||||
std::ostringstream ostr;
|
||||
Base64Encoder encoder(ostr);
|
||||
encoder << sig;
|
||||
encoder.close();
|
||||
|
||||
begin.append(ostr.str()).append(end);
|
||||
_signature.assign(begin.begin(), begin.end());
|
||||
}
|
||||
return _signature;
|
||||
|
||||
return _signature;
|
||||
}
|
||||
|
||||
|
||||
bool RSADigestEngine::verify(const DigestEngine::Digest& sig)
|
||||
{
|
||||
digest();
|
||||
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());
|
||||
return ret != 0;
|
||||
|
||||
DWORD cbData = 0;
|
||||
BYTE* pbData = NULL;
|
||||
|
||||
if (CryptExportKey(_key.impl()->privateKey(), 0, PRIVATEKEYBLOB, 0/*???*/,
|
||||
NULL, &cbData))
|
||||
{
|
||||
std::vector<BYTE> pkData(cbData);
|
||||
pbData = &pkData[0];
|
||||
|
||||
if (CryptExportKey(_key.impl()->publicKey(), 0, PRIVATEKEYBLOB, 0/*???*/,
|
||||
pbData, &cbData))
|
||||
{
|
||||
// TODO: base64-decode pbData
|
||||
}
|
||||
else // !CryptExportKey
|
||||
{
|
||||
DWORD err = Error::last();
|
||||
std::string errStr = Error::getMessage(err);
|
||||
switch (err)
|
||||
{
|
||||
case ERROR_INVALID_HANDLE: case ERROR_INVALID_PARAMETER:
|
||||
case NTE_BAD_DATA: case NTE_BAD_FLAGS:
|
||||
case NTE_BAD_KEY: case NTE_BAD_KEY_STATE:
|
||||
case NTE_BAD_PUBLIC_KEY: case NTE_BAD_TYPE:
|
||||
case NTE_BAD_UID: case NTE_NO_KEY:
|
||||
throw Poco::InvalidArgumentException(errStr);
|
||||
default:
|
||||
throw Poco::SystemException("Cannot export public key.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else // !CryptExportKey length
|
||||
{
|
||||
throw Poco::SystemException("Cannot obtain key export length.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void RSADigestEngine::updateImpl(const void* data, unsigned length)
|
||||
void RSADigestEngine::updateImpl(const void* data, std::size_t length)
|
||||
{
|
||||
_engine.update(data, length);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ RSAKeyImpl::RSAKeyImpl(const X509Certificate& cert):
|
||||
_hPrivateKey(0),
|
||||
_hPublicKey(0)
|
||||
{
|
||||
DWORD rc = CryptImportPublicKeyInfo(_sp.handle(), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cert.system().pCertInfo->SubjectPublicKeyInfo, &_hPublicKey);
|
||||
DWORD rc = CryptImportPublicKeyInfo(_sp.handle(), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cert.system()->pCertInfo->SubjectPublicKeyInfo, &_hPublicKey);
|
||||
if (!rc) throw Poco::SystemException("Cannot import public key from certificate");
|
||||
}
|
||||
|
||||
@ -110,9 +110,9 @@ RSAKeyImpl::~RSAKeyImpl()
|
||||
|
||||
int RSAKeyImpl::size() const
|
||||
{
|
||||
DWORD keyLength;
|
||||
BYTE keyLength;
|
||||
DWORD size = sizeof(keyLength);
|
||||
if (!CryptGetKeyParam(_hKey, KP_KEYLEN, &keyLength, &size, 0))
|
||||
if (!CryptGetKeyParam(_hPrivateKey, KP_KEYLEN, &keyLength, &size, 0))
|
||||
throw Poco::SystemException("Cannot obtain key length");
|
||||
return static_cast<int>(keyLength);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user