Logo Search packages:      
Sourcecode: poco version File versions  Download package

RSAKeyImpl.cpp

//
// RSAKeyImpl.cpp
//
// $Id: //poco/1.3/Crypto/src/RSAKeyImpl.cpp#2 $
//
// Library: Crypto
// Package: CryptoCore
// Module:  RSAKeyImpl
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//


#include "Poco/Crypto/RSAKeyImpl.h"
#include "Poco/FileStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/TemporaryFile.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/X509Certificate.h"
#include <openssl/pem.h>
#include <openssl/rsa.h>


namespace Poco {
namespace Crypto {


RSAKeyImpl::RSAKeyImpl(const Poco::Net::X509Certificate& cert):
      _pRSA(0)
{
      const X509* pCert = cert.certificate();
      EVP_PKEY* pKey = X509_get_pubkey(const_cast<X509*>(pCert));
      
      RSA* pRSA = pKey->pkey.rsa;
      _pRSA = RSAPublicKey_dup(pRSA);
}


00062 RSAKeyImpl::RSAKeyImpl(int keyLength, unsigned long exponent):
      _pRSA(0)
{
      //dummy access to SSLMananger so that the SSLInitializer of NetSSL gets called!
      Poco::Net::SSLManager::instance();
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
      _pRSA = RSA_new();
      int ret = 0;
      BIGNUM *bn = 0;
      try
      {
            bn = BN_new();
            BN_set_word(bn, exponent);
            ret = RSA_generate_key_ex(_pRSA, keyLength, bn, 0);
            BN_free(bn);
      }
      catch (...)
      {
            BN_free(bn);
            throw;
      }
      if (!ret) throw Poco::InvalidArgumentException("Failed to create RSA context");
#else
      _pRSA = RSA_generate_key(keyLength, exponent, 0, 0);
      if (!_pRSA) throw Poco::InvalidArgumentException("Failed to create RSA context");
#endif
}


00091 RSAKeyImpl::RSAKeyImpl(
            const std::string& publicKey, 
            const std::string& privateKeyFile, 
            const std::string& privateKeyPwd):
      _pRSA(0)
{
      //dummy access to SSLMananger so that the SSLInitializer of NetSSL gets called!
      Poco::Net::SSLManager::instance();
      init(publicKey, privateKeyFile, privateKeyPwd);
}


00103 RSAKeyImpl::RSAKeyImpl(std::istream* pubKey, std::istream* privKey, const std::string& privKeyPwd):
      _pRSA(0)
{
      //dummy access to SSLMananger so that the SSLInitializer of NetSSL gets called!
      Poco::Net::SSLManager::instance();
      // due to C lib not supporting streams, we create two temporary files
      std::string pubKeyFile;
      Poco::TemporaryFile pubFile;
      if (pubKey)
      {
            if (!pubFile.createFile())
                  throw Poco::FileException("No temporary file could be created for public file!");
            pubKeyFile = pubFile.path();
            Poco::FileOutputStream fout(pubKeyFile);
            Poco::StreamCopier::copyStream(*pubKey, fout);
      }
      std::string privKeyFile;
      Poco::TemporaryFile privFile;
      if (privKey)
      {
            if (!privFile.createFile())
                  throw Poco::FileException("No temporary file could be created for private file!");
            privKeyFile = privFile.path();
            Poco::FileOutputStream fout(privKeyFile);
            Poco::StreamCopier::copyStream(*privKey, fout);

      }
      init(pubKeyFile, privKeyFile, privKeyPwd);
}


00134 void RSAKeyImpl::init(const std::string& pubKeyFile, const std::string& privKeyFile, const std::string& privKeyPwd)
{
      poco_assert_dbg(_pRSA == 0);
      _pRSA = RSA_new();
      if (!pubKeyFile.empty())
      {
            BIO *out=BIO_new(BIO_s_file());
            const char* pFN = pubKeyFile.c_str();
            BIO_read_filename(out, (void*)pFN);
            if (out)
            {
                  RSA* pubKey = PEM_read_bio_RSAPublicKey(out, &_pRSA, 0, 0);
                  BIO_free(out);
                  if (!pubKey)
                  {
                        freeRSA();
                        throw Poco::FileException("Failed to load public key: " + pubKeyFile);
                  }
            }
            else
            {
                  freeRSA();
                  throw Poco::FileNotFoundException("Public key file not found: " + pubKeyFile);
            }
      }

      if (!privKeyFile.empty())
      {
            BIO* out=BIO_new(BIO_s_file());
            const char* pFN = privKeyFile.c_str();
            BIO_read_filename(out, (void*)pFN);
            
            if (out)
            {
                  RSA* privKey = 0;
                  if (privKeyPwd.empty())
                        privKey = PEM_read_bio_RSAPrivateKey(out, &_pRSA, 0, 0);
                  else
                        privKey = PEM_read_bio_RSAPrivateKey(out, &_pRSA, 0, (void*)privKeyPwd.c_str());
                  BIO_free(out);
                  if (!privKey)
                  {
                        freeRSA();
                        throw Poco::FileException("Failed to load private key: " + privKeyFile);
                  }
            }
            else
            {
                  freeRSA();
                  throw Poco::FileNotFoundException("Private key file not found: " + privKeyFile);
            }
      }
}


00189 RSAKeyImpl::~RSAKeyImpl()
{
}


00194 void RSAKeyImpl::freeRSA()
{
      if (_pRSA)
            RSA_free(_pRSA);
      _pRSA = 0;
}


00202 int RSAKeyImpl::size() const
{
      return RSA_size(_pRSA);
}




00210 void RSAKeyImpl::save(const std::string& pubKeyFile, const std::string& privKeyFile, const std::string& privKeyPwd)
{
      if (!pubKeyFile.empty())
      {
            BIO *out=BIO_new(BIO_s_file());
            const char* pFN = pubKeyFile.c_str();
            BIO_write_filename(out, (void*)pFN);
            if (!PEM_write_bio_RSAPublicKey(out,_pRSA))
                  throw Poco::FileException("Failed to write public key to file:" + pubKeyFile);
            BIO_free(out);
      }
      if (!privKeyFile.empty())
      {
            BIO *out=BIO_new(BIO_s_file());
            const char* pFN = privKeyFile.c_str();
            BIO_write_filename(out, (void*)pFN);

            int ret = 0;
            if (privKeyPwd.empty())
                  ret = PEM_write_bio_RSAPrivateKey(out, _pRSA, EVP_des_ede3_cbc(), 0, 0, 0, 0);
            else
                  ret = PEM_write_bio_RSAPrivateKey(out, _pRSA, EVP_des_ede3_cbc(), (unsigned char *)privKeyPwd.c_str(), privKeyPwd.length(), 0, 0);

            if (!ret)
                  throw Poco::FileException("Failed to write private key to file:" + privKeyFile);
            BIO_free(out);
      }
}


00240 void RSAKeyImpl::save(std::ostream* pPubKey, std::ostream* pPrivKey, const std::string& privateKeyPwd)
{
      if (!pPubKey && !pPrivKey)
            return;
      // due to C lib not supporting streams, we create two temporary files
      std::string pubKeyFile;
      Poco::TemporaryFile pubFile;
      if (pPubKey)
      {
            pubKeyFile = pubFile.path();
            if (!pubFile.createFile())
                  throw Poco::FileException("No temporary file could be created for public file!");
      }
      std::string privKeyFile;
      Poco::TemporaryFile privFile;
      if (pPrivKey)
      {
            if (!privFile.createFile())
                  throw Poco::FileException("No temporary file could be created for private file!");
            privKeyFile = privFile.path();
      }
      save(pubKeyFile, privKeyFile, privateKeyPwd);
      // now copy everything from the temp files to the original streams
      if (pPubKey)
      {
            Poco::FileInputStream fPub(pubKeyFile);
            Poco::StreamCopier::copyStream(fPub, *pPubKey);
      }
      if (pPrivKey)
      {
            Poco::FileInputStream fPriv(privKeyFile);
            Poco::StreamCopier::copyStream(fPriv, *pPrivKey);
      }
}


} } // namespace Poco::Crypto

Generated by  Doxygen 1.6.0   Back to index