Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

RSAPublicKey.cc

00001 /*
00002  * Copyright 2003 Michael A. Marsh, Cornell University. All rights reserved.
00003  * This software is released under the modified BSD license.
00004  * See the file LICENSE in the top-level directory for details.
00005  */
00006 //
00007 // $Id: RSAPublicKey.cc,v 1.4 2004/05/19 15:56:47 mmarsh Exp $
00008 //
00009 // $Log: RSAPublicKey.cc,v $
00010 // Revision 1.4  2004/05/19 15:56:47  mmarsh
00011 // *** empty log message ***
00012 //
00013 // Revision 1.3  2003/11/04 22:31:48  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include <fstream>
00019 #include "RSA.h"
00020 #include "CODEX_Exceptions/BignumExceptions.h"
00021 #include "CODEX_Exceptions/FileExceptions.h"
00022 
00023 #include "timing.h"
00024 
00025 using namespace CODEX_Ciphers;
00026 using namespace CODEX_Exceptions;
00027 
00028 RSAPublicKey::RSAPublicKey() :
00029    CODEX_ASN1::Base( false )
00030 {
00031 }
00032 
00033 RSAPublicKey::RSAPublicKey( BIGNUM * n,
00034                             BIGNUM * e ) :
00035    CODEX_ASN1::Base( true ),
00036    m_n( n ),
00037    m_e( e )
00038 {
00039 }
00040 
00041 RSAPublicKey::RSAPublicKey( const CODEX_ASN1::BigNumber& n,
00042                             const CODEX_ASN1::BigNumber& e ) :
00043    CODEX_ASN1::Base( true ),
00044    m_n( n ),
00045    m_e( e )
00046 {
00047 }
00048 
00050 RSAPublicKey::RSAPublicKey( const X509 * cert ) :
00051    CODEX_ASN1::Base( true )
00052 {
00053    EVP_PKEY * pkey = 0;
00054    RSA * rsaPublic = 0;
00055    try
00056    {
00057       pkey = X509_get_pubkey( (X509*)cert );
00058       rsaPublic = EVP_PKEY_get1_RSA( pkey );
00059       m_n = CODEX_ASN1::BigNumber( BN_dup( rsaPublic->n ) );
00060       m_e = CODEX_ASN1::BigNumber( BN_dup( rsaPublic->e ) );
00061       EVP_PKEY_free( pkey );
00062       RSA_free( rsaPublic );
00063    }
00064    catch ( ... )
00065    {
00066       if ( 0 != pkey ) EVP_PKEY_free( pkey );
00067       if ( 0 != rsaPublic ) RSA_free( rsaPublic );
00068       throw;
00069    }
00070 }
00071 
00072 RSAPublicKey::RSAPublicKey( const RSAPublicKey& aKey ) :
00073    CODEX_ASN1::Base( aKey.m_initialized ),
00074    m_n( aKey.m_n ),
00075    m_e( aKey.m_e )
00076 {
00077 }
00078 
00079 void
00080 RSAPublicKey::operator=( const RSAPublicKey& aKey )
00081 {
00082    m_initialized = aKey.m_initialized;
00083    m_n = aKey.m_n;
00084    m_e = aKey.m_e;
00085 }
00086 
00087 RSACipherText*
00088 RSAPublicKey::encrypt( const BIGNUM * message ) const
00089 {
00090    return new RSACipherText( exponentiate( message ) );
00091 }
00092 
00093 bool
00094 RSAPublicKey::verifySignature( const RSASignature& signature,
00095                                const BIGNUM * message ) const
00096 {
00097    if ( 0 == message )
00098    {
00099       throw BignumNullException( __FILE__ , __LINE__ );
00100    }
00101    if ( ! signature.initialized() )
00102    {
00103       throw BignumNullException( __FILE__ , __LINE__ );
00104    }
00105 
00106 #ifdef TIMING
00107    SignVerifyTimer.start();
00108 #endif
00109 
00110    BIGNUM * s = exponentiate( signature.value() );
00111 
00112    bool retVal = ( 0 == BN_cmp( message, s ) );
00113    BN_free( s );
00114 
00115 #ifdef TIMING
00116    SignVerifyTimer.stop();
00117 #endif
00118 
00119    return retVal;
00120 }
00121 
00122 BIGNUM *
00123 RSAPublicKey::exponentiate( const BIGNUM * aBN ) const
00124 {
00125    if ( 0 == aBN )
00126    {
00127       throw BignumNullException( __FILE__ , __LINE__ );
00128    }
00129 
00130    BN_CTX * ctx = 0;
00131    BIGNUM * retVal = 0;
00132 
00133    try
00134    {
00135       ctx = BN_CTX_new();
00136       if ( 0 == ctx )
00137       {
00138          throw BignumContextException( __FILE__ , __LINE__ );
00139       }
00140 
00141       retVal = BN_new();
00142       if ( 0 == retVal )
00143       {
00144          throw BignumNullException( __FILE__ , __LINE__ );
00145       }
00146       if ( ! BN_mod_exp( retVal, aBN, e().value(), n().value(), ctx ) )
00147       {
00148          throw BignumModExpException( __FILE__ , __LINE__ );
00149       }
00150       if ( 0 != ctx ) BN_CTX_free( ctx );
00151       return retVal;
00152    }
00153    catch ( ... )
00154    {
00155       if ( 0 != ctx ) BN_CTX_free( ctx );
00156       if ( 0 != retVal ) BN_free( retVal );
00157       throw;
00158    }
00159 }
00160 
00161 int
00162 RSAPublicKey::marshal( unsigned char ** pp ) const
00163 {
00164    int r=0;
00165    int ret=0;
00166    unsigned char * p;
00167 
00168    ret += m_n.marshal(0);
00169    ret += m_e.marshal(0);
00170    M_ASN1_I2D_seq_total();
00171    m_n.marshal(&p);
00172    m_e.marshal(&p);
00173    M_ASN1_I2D_finish();
00174 }
00175 
00176 void*
00177 RSAPublicKey::unmarshal( void* bogus,
00178                          unsigned char ** pp,
00179                          long length )
00180 {
00181    if ( m_initialized )
00182    {
00183       return 0;
00184    }
00185    if ( (0 == pp) || (0 == *pp) )
00186    {
00187       return 0;
00188    }
00189 
00190    ASN1_CTX c;
00191    c.pp = pp;
00192    c.q = *pp;
00193    c.error = ERR_R_NESTED_ASN1_ERROR;
00194    int i;
00195 
00196    M_ASN1_D2I_Init();
00197    M_ASN1_D2I_start_sequence();
00198    M_ASN1_D2I_get(i, m_n.unmarshal);
00199    M_ASN1_D2I_get(i, m_e.unmarshal);
00200    if ( !asn1_Finish(&c) )
00201    {
00202       return 0;
00203    }
00204    *pp=c.p;
00205    m_initialized = true;
00206    return this;
00207   err: // needed by ASN.1 macros
00208    return 0;
00209 }
00210 
00211 void
00212 RSAPublicKey::toFile(const char* fname) const
00213 {
00214    int length = marshal(0);
00215    if ( 0 == length ) return;
00216    unsigned char* buff = new unsigned char[length];
00217    unsigned char* p = buff;
00218    marshal(&p);
00219    ofstream os(fname);
00220    if ( ! os.is_open() )
00221    {
00222       delete [] buff;
00223       throw FileCannotCreateException( __FILE__ , __LINE__ , fname );
00224    }
00225    for ( int i = 0 ; i < length ; ++i )
00226    {
00227       os << buff[i];
00228    }
00229    os.close();
00230    delete [] buff;
00231 }
00232 
00233 void*
00234 RSAPublicKey::fromFile(const char* fname)
00235 {
00236    ifstream is(fname);
00237    if ( ! is.is_open() )
00238    {
00239       throw FileCannotOpenException( __FILE__ , __LINE__ , fname );
00240    }
00241    string s;
00242    char ch;
00243    while ( is.get(ch) )
00244    {
00245       s.push_back(ch);
00246    }
00247    //basic_string<unsigned char> s;
00248    //is >> s;
00249    unsigned int length = s.length();
00250    unsigned char* p = new unsigned char[ length ];
00251    unsigned char* pOrig = p;
00252    //unsigned char* p = (unsigned char*)s.data();
00253    for ( unsigned int i = 0 ; i < length ; ++i )
00254    {
00255       p[i] = s.data()[i];
00256    }
00257    void* retVal = unmarshal(0,&p,length);
00258    delete [] pOrig;
00259    return retVal;
00260 }

Generated on Fri May 6 17:41:02 2005 for COrnell Data EXchange (CODEX) by  doxygen 1.4.1