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

RSAPrivateKey.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: RSAPrivateKey.cc,v 1.4 2004/05/19 15:56:47 mmarsh Exp $
00008 //
00009 // $Log: RSAPrivateKey.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 <openssl/pem.h>
00020 #include "RSA.h"
00021 #include "CODEX_Exceptions/BignumExceptions.h"
00022 #include "CODEX_Exceptions/FileExceptions.h"
00023 
00024 #include "timing.h"
00025 
00026 using namespace CODEX_Ciphers;
00027 using namespace CODEX_Exceptions;
00028 using CODEX_ASN1::BigNumber;
00029 using CODEX_ASN1::SecureBigNumber;
00030 
00031 RSAPrivateKey::RSAPrivateKey() :
00032    CODEX_ASN1::Base( false )
00033 {
00034 }
00035 
00036 RSAPrivateKey::RSAPrivateKey( BIGNUM * p,
00037                               BIGNUM * q,
00038                               BIGNUM * d,
00039                               BIGNUM * n,
00040                               BIGNUM * phi ) :
00041    CODEX_ASN1::Base( true ),
00042    m_p( p ),
00043    m_q( q ),
00044    m_d( d ),
00045    m_n( n ),
00046    m_phi( phi )
00047 {
00048    BN_CTX * ctx = 0;
00049    BIGNUM * temp1 = 0;
00050    BIGNUM * temp2 = 0;
00051    bool ownN = false;
00052    bool ownPhi = false;
00053    try
00054    {
00055       if ( 0 == n )
00056       {
00057          if ( 0 == ctx )
00058          {
00059             ctx = BN_CTX_new();
00060             if ( 0 == ctx )
00061             {
00062                throw BignumContextException( __FILE__ , __LINE__ );
00063             }
00064          }
00065          n = BN_new();
00066          if ( 0 == n )
00067          {
00068             throw BignumNullException( __FILE__ , __LINE__ );
00069          }
00070          ownN = true;
00071          if ( ! BN_mul( n, p, q, ctx ) )
00072          {
00073             throw BignumMulException( __FILE__ , __LINE__ );
00074          }
00075          m_n = CODEX_ASN1::SecureBigNumber( n );
00076       }
00077       if ( 0 == phi )
00078       {
00079          if ( 0 == ctx )
00080          {
00081             ctx = BN_CTX_new();
00082             if ( 0 == ctx )
00083             {
00084                throw BignumContextException( __FILE__ , __LINE__ );
00085             }
00086          }
00087          phi = BN_new();
00088          if ( 0 == phi )
00089          {
00090             throw BignumNullException( __FILE__ , __LINE__ );
00091          }
00092          ownPhi = true;
00093          temp1 = BN_new();
00094          if ( 0 == temp1 )
00095          {
00096             throw BignumNullException( __FILE__ , __LINE__ );
00097          }
00098          temp2 = BN_new();
00099          if ( 0 == temp2 )
00100          {
00101             throw BignumNullException( __FILE__ , __LINE__ );
00102          }
00103          if ( ! BN_sub( temp1, p, BN_value_one() ) )
00104          {
00105             throw BignumSubException( __FILE__ , __LINE__ );
00106          }
00107          if ( ! BN_sub( temp2, q, BN_value_one() ) )
00108          {
00109             throw BignumSubException( __FILE__ , __LINE__ );
00110          }
00111          if ( ! BN_mul( phi, temp1, temp2, ctx ) )
00112          {
00113             throw BignumMulException( __FILE__ , __LINE__ );
00114          }
00115          m_phi = CODEX_ASN1::SecureBigNumber( phi );
00116       }
00117    }
00118    catch ( ... )
00119    {
00120       if ( 0 != ctx ) BN_CTX_free( ctx );
00121       if ( 0 != temp1 ) BN_clear_free( temp1 );
00122       if ( 0 != temp2 ) BN_clear_free( temp2 );
00123       if ( ownN ) BN_clear_free( n );
00124       if ( ownPhi ) BN_clear_free( phi );
00125       throw;
00126    }
00127    if ( 0 != ctx   ) BN_CTX_free( ctx );
00128    if ( 0 != temp1 ) BN_clear_free( temp1 );
00129    if ( 0 != temp2 ) BN_clear_free( temp2 );
00130 }
00131 
00132 RSAPrivateKey::RSAPrivateKey( const CODEX_ASN1::BigNumber& p,
00133                               const CODEX_ASN1::BigNumber& q,
00134                               const CODEX_ASN1::BigNumber& d ) :
00135    CODEX_ASN1::Base( true ),
00136    m_p( p ),
00137    m_q( q ),
00138    m_d( d )
00139 {
00140    BN_CTX * ctx = 0;
00141    BIGNUM * temp1 = 0;
00142    BIGNUM * temp2 = 0;
00143    BIGNUM * nbn = 0;
00144    BIGNUM * phibn = 0;
00145    const BIGNUM * pbn = p.value();
00146    const BIGNUM * qbn = q.value();
00147 
00148    try
00149    {
00150       ctx = BN_CTX_new();
00151       if ( 0 == ctx )
00152       {
00153          throw BignumContextException( __FILE__ , __LINE__ );
00154       }
00155       nbn = BN_new();
00156       if ( 0 == nbn )
00157       {
00158          throw BignumNullException( __FILE__ , __LINE__ );
00159       }
00160       if ( ! BN_mul( nbn, pbn, qbn, ctx ) )
00161       {
00162          throw BignumMulException( __FILE__ , __LINE__ );
00163       }
00164       m_n = CODEX_ASN1::SecureBigNumber( nbn );
00165 
00166       phibn = BN_new();
00167       if ( 0 == phibn )
00168       {
00169          throw BignumNullException( __FILE__ , __LINE__ );
00170       }
00171       temp1 = BN_new();
00172       if ( 0 == temp1 )
00173       {
00174          throw BignumNullException( __FILE__ , __LINE__ );
00175       }
00176       temp2 = BN_new();
00177       if ( 0 == temp2 )
00178       {
00179          throw BignumNullException( __FILE__ , __LINE__ );
00180       }
00181       if ( ! BN_sub( temp1, pbn, BN_value_one() ) )
00182       {
00183             throw BignumSubException( __FILE__ , __LINE__ );
00184       }
00185       if ( ! BN_sub( temp2, qbn, BN_value_one() ) )
00186       {
00187          throw BignumSubException( __FILE__ , __LINE__ );
00188       }
00189       if ( ! BN_mul( phibn, temp1, temp2, ctx ) )
00190       {
00191          throw BignumMulException( __FILE__ , __LINE__ );
00192       }
00193       m_phi = CODEX_ASN1::SecureBigNumber( phibn );
00194    }
00195    catch ( ... )
00196    {
00197       if ( 0 != ctx ) BN_CTX_free( ctx );
00198       if ( 0 != temp1 ) BN_clear_free( temp1 );
00199       if ( 0 != temp2 ) BN_clear_free( temp2 );
00200       if ( 0 != nbn ) BN_free( nbn );
00201       if ( 0 != phibn ) BN_clear_free( phibn );
00202       throw;
00203    }
00204    if ( 0 != ctx ) BN_CTX_free( ctx );
00205    if ( 0 != temp1 ) BN_clear_free( temp1 );
00206    if ( 0 != temp2 ) BN_clear_free( temp2 );
00207 }
00208 
00209 RSAPrivateKey::RSAPrivateKey( const RSAPrivateKey& aKey ) :
00210    CODEX_ASN1::Base( aKey.m_initialized ),
00211    m_p( aKey.m_p ),
00212    m_q( aKey.m_q ),
00213    m_d( aKey.m_d ),
00214    m_n( aKey.m_n ),
00215    m_phi( aKey.m_phi )
00216 {
00217 }
00218 
00219 RSAPrivateKey::~RSAPrivateKey()
00220 {
00221 }
00222 
00223 void
00224 RSAPrivateKey::operator=( const RSAPrivateKey& aKey )
00225 {
00226    m_initialized = aKey.m_initialized;
00227    m_p           = aKey.m_p;
00228    m_q           = aKey.m_q;
00229    m_d           = aKey.m_d;
00230    m_n           = aKey.m_n;
00231    m_phi         = aKey.m_phi;
00232 }
00233 
00234 BIGNUM *
00235 RSAPrivateKey::decrypt( const RSACipherText& cipherText ) const
00236 {
00237    return exponentiate( cipherText.value() );
00238 }
00239 
00240 RSASignature*
00241 RSAPrivateKey::sign( const BIGNUM * message ) const
00242 {
00243    return new RSASignature( exponentiate( message ) );
00244 }
00245 
00246 BIGNUM *
00247 RSAPrivateKey::exponentiate( const BIGNUM * aBN ) const
00248 {
00249    if ( 0 == aBN )
00250    {
00251       throw BignumNullException( __FILE__ , __LINE__ );
00252    }
00253 
00254 #ifdef TIMING
00255    SignTimer.start();
00256 #endif
00257 
00258    BN_CTX * ctx = 0;
00259    BIGNUM * retVal = 0;
00260 
00261    try
00262    {
00263       ctx = BN_CTX_new();
00264       if ( 0 == ctx )
00265       {
00266          throw BignumContextException( __FILE__ , __LINE__ );
00267       }
00268 
00269       retVal = BN_new();
00270       if ( 0 == retVal )
00271       {
00272          throw BignumNullException( __FILE__ , __LINE__ );
00273       }
00274       if ( ! BN_mod_exp( retVal, aBN, d().value(), n().value(), ctx ) )
00275       {
00276          throw BignumModExpException( __FILE__ , __LINE__ );
00277       }
00278    }
00279    catch ( ... )
00280    {
00281       if ( 0 != ctx ) BN_CTX_free( ctx );
00282       if ( 0 != retVal ) BN_free( retVal );
00283       throw;
00284    }
00285 
00286    if ( 0 != ctx ) BN_CTX_free( ctx );
00287 
00288 #ifdef TIMING
00289    SignTimer.stop();
00290 #endif
00291 
00292    return retVal;
00293 }
00294 
00295 int
00296 RSAPrivateKey::marshal( unsigned char ** pp ) const
00297 {
00298    int r=0;
00299    int ret=0;
00300    unsigned char * p;
00301 
00302    ret += m_p.marshal(0);
00303    ret += m_q.marshal(0);
00304    ret += m_d.marshal(0);
00305    ret += m_n.marshal(0);
00306    ret += m_phi.marshal(0);
00307    M_ASN1_I2D_seq_total();
00308    m_p.marshal(&p);
00309    m_q.marshal(&p);
00310    m_d.marshal(&p);
00311    m_n.marshal(&p);
00312    m_phi.marshal(&p);
00313    M_ASN1_I2D_finish();
00314 }
00315 
00316 void*
00317 RSAPrivateKey::unmarshal( void* bogus, unsigned char ** pp, long length )
00318 {
00319    if ( m_initialized )
00320    {
00321       return 0;
00322    }
00323    if ( (0 == pp) || (0 == *pp) )
00324    {
00325       return 0;
00326    }
00327 
00328    ASN1_CTX c;
00329    c.pp = pp;
00330    c.q = *pp;
00331    c.error = ERR_R_NESTED_ASN1_ERROR;
00332    int i;
00333 
00334    M_ASN1_D2I_Init();
00335    M_ASN1_D2I_start_sequence();
00336    M_ASN1_D2I_get(i, m_p.unmarshal);
00337    M_ASN1_D2I_get(i, m_q.unmarshal);
00338    M_ASN1_D2I_get(i, m_d.unmarshal);
00339    M_ASN1_D2I_get(i, m_n.unmarshal);
00340    M_ASN1_D2I_get(i, m_phi.unmarshal);
00341    if ( !asn1_Finish(&c) )
00342    {
00343       return 0;
00344    }
00345    *pp=c.p;
00346    m_initialized = true;
00347    return this;
00348   err: // needed by ASN.1 macros
00349    return 0;
00350 }
00351 
00352 void
00353 RSAPrivateKey::toFile(const char* fname) const
00354 {
00355    int length = marshal(0);
00356    if ( 0 == length ) return;
00357    unsigned char* buff = new unsigned char[length];
00358    unsigned char* p = buff;
00359    marshal(&p);
00360    ofstream os(fname);
00361    if ( ! os.is_open() )
00362    {
00363       delete [] buff;
00364       throw FileCannotCreateException( __FILE__ , __LINE__ , fname );
00365    }
00366    for ( int i = 0 ; i < length ; ++i )
00367    {
00368       os << buff[i];
00369    }
00370    os.close();
00371    delete [] buff;
00372 }
00373 
00375 void*
00376 RSAPrivateKey::fromFile(const char* fname)
00377 {
00378    ifstream is(fname);
00379    if ( ! is.is_open() )
00380    {
00381       throw FileCannotOpenException( __FILE__ , __LINE__ , fname );
00382    }
00383    string s;
00384    char ch;
00385    while ( is.get(ch) )
00386    {
00387       s.push_back(ch);
00388    }
00389    //basic_string<unsigned char> s;
00390    //is >> s;
00391    unsigned int length = s.length();
00392    unsigned char* p = new unsigned char[ length ];
00393    unsigned char* pOrig = p;
00394    //unsigned char* p = (unsigned char*)s.data();
00395    for ( unsigned int i = 0 ; i < length ; ++i )
00396    {
00397       p[i] = s.data()[i];
00398    }
00399    void* retVal = unmarshal(0,&p,length);
00400    delete [] pOrig;
00401    return retVal;
00402 }
00403 
00404 void
00405 RSAPrivateKey::fromPEMFile(const char* fname, const char* phrase)
00406 {
00407    FILE* fp = 0;
00408    RSA * key = 0;
00409    BIGNUM * phibn = 0;
00410    BIGNUM * temp1 = 0;
00411    BIGNUM * temp2 = 0;
00412    BN_CTX * ctx = 0;
00413 
00414    try
00415    {
00416       fp = fopen( fname, "r" );
00417       if ( 0 == fp )
00418       {
00419          throw FileCannotOpenException( __FILE__ , __LINE__ , fname );
00420       }
00421       if ( ! PEM_read_RSAPrivateKey( fp, &key, 0, (void*)phrase ) )
00422       {
00423          throw FileCannotOpenException( __FILE__ , __LINE__ , fname );
00424       }
00425       fclose( fp );
00426       fp = 0;
00427       m_p = CODEX_ASN1::SecureBigNumber( BN_dup( key->p ) );
00428       m_q = CODEX_ASN1::SecureBigNumber( BN_dup( key->q ) );
00429       m_d = CODEX_ASN1::SecureBigNumber( BN_dup( key->d ) );
00430       m_n = CODEX_ASN1::SecureBigNumber( BN_dup( key->n ) );
00431 
00432       ctx = BN_CTX_new();
00433       if ( 0 == ctx )
00434       {
00435          throw BignumContextException( __FILE__ , __LINE__ );
00436       }
00437       phibn = BN_new();
00438       if ( 0 == phibn )
00439       {
00440          throw BignumNullException( __FILE__ , __LINE__ );
00441       }
00442       temp1 = BN_new();
00443       if ( 0 == temp1 )
00444       {
00445          throw BignumNullException( __FILE__ , __LINE__ );
00446       }
00447       temp2 = BN_new();
00448       if ( 0 == temp2 )
00449       {
00450          throw BignumNullException( __FILE__ , __LINE__ );
00451       }
00452       if ( ! BN_sub( temp1, key->p, BN_value_one() ) )
00453       {
00454             throw BignumSubException( __FILE__ , __LINE__ );
00455       }
00456       if ( ! BN_sub( temp2, key->q, BN_value_one() ) )
00457       {
00458          throw BignumSubException( __FILE__ , __LINE__ );
00459       }
00460       if ( ! BN_mul( phibn, temp1, temp2, ctx ) )
00461       {
00462          throw BignumMulException( __FILE__ , __LINE__ );
00463       }
00464       m_phi = CODEX_ASN1::SecureBigNumber( phibn );
00465 
00466       m_initialized = true;
00467 
00468       RSA_free( key ); key = 0;
00469       BN_CTX_free( ctx ); ctx = 0;
00470       BN_clear_free(temp1); temp1 = 0;
00471       BN_clear_free(temp2); temp2 = 0;
00472    }
00473    catch ( ... )
00474    {
00475       if ( 0 != fp ) fclose(fp);
00476       if ( 0 != key ) RSA_free( key );
00477       if ( 0 != ctx ) BN_CTX_free( ctx );
00478       if ( 0 != phibn ) BN_clear_free( phibn );
00479       if ( 0 != temp1 ) BN_clear_free( temp1 );
00480       if ( 0 != temp2 ) BN_clear_free( temp2 );
00481       throw;
00482    }
00483 }

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