00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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:
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
00248
00249 unsigned int length = s.length();
00250 unsigned char* p = new unsigned char[ length ];
00251 unsigned char* pOrig = p;
00252
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 }