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

RSAPlaintextPK.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: RSAPlaintextPK.cc,v 1.4 2004/05/19 15:56:47 mmarsh Exp $
00008 //
00009 // $Log: RSAPlaintextPK.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:47  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include "RSAPlaintextPK.h"
00019 #include "CODEX_Exceptions/BignumExceptions.h"
00020 
00021 #include "timing.h"
00022 
00023 using namespace CODEX_Ciphers;
00024 
00025 RSAPlaintextPK::RSAPlaintextPK() :
00026    CODEX_ASN1::Base( false )
00027 {
00028 }
00029 
00030 RSAPlaintextPK::RSAPlaintextPK( const CODEX_ASN1::SecureBigNumber& plaintext,
00031                                 const RSAPublicKey& publicKey,
00032                                 const CODEX_ASN1::Base& id,
00033                                 const HashFunction& hashFunc ) :
00034    CODEX_ASN1::Base( true )
00035 {
00036    if ( ! ( plaintext.initialized() &&
00037             publicKey.initialized() &&
00038             id.initialized() ) )
00039    {
00040       throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00041    }
00042    int Ln = BN_num_bytes( publicKey.n().value() );
00043    int ln = BN_num_bits( publicKey.n().value() );
00044    int Le = BN_num_bytes( publicKey.e().value() );
00045    int sublen = Le - 1;
00046    int k = Ln / sublen;
00047 
00048    typedef vector< BIGNUM* > VBNType;
00049    VBNType vr;
00050 
00051    //const BIGNUM * e         = publicKey.e().value();
00052    const BIGNUM * n         = publicKey.n().value();
00053    const BIGNUM * s         = plaintext.value();
00054    CODEX_ASN1::ustring* str = 0;
00055    unsigned char* buff      = 0;
00056    BIGNUM * r               = 0;
00057    RSACipherText* p1        = 0;
00058    RSACipherText* es        = 0;
00059    BIGNUM * c               = 0;
00060    BIGNUM * p2              = 0;
00061    BN_CTX * ctx             = 0;
00062    try
00063    {
00064       ctx = BN_CTX_new();
00065       if ( NULL == ctx )
00066       {
00067          throw CODEX_Exceptions::BignumContextException( __FILE__ , __LINE__ );
00068       }
00069 
00070       for ( int i = 0 ; i < k ; ++i )
00071       {
00072          // Choose a random number
00073          r = BN_new();
00074          if ( 0 == r )
00075          {
00076             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00077          }
00078          do
00079          {
00080             if ( ! BN_rand_range( r, (BIGNUM*)n ) )
00081             {
00082                throw CODEX_Exceptions::BignumRandRangeException( __FILE__ ,
00083                                                                  __LINE__ );
00084             }
00085          }
00086          while ( 0 >= BN_cmp( r, BN_value_one() ) ); // r=0,1 are detectable
00087 
00088          p1 = publicKey.encrypt( r );
00089          vr.push_back( r );
00090          r = 0;
00091          m_a.append( p1 );
00092          p1 = 0;
00093       }
00094       if ( vr.size() != k )
00095       {
00096          throw CODEX_Exceptions::IllegalIndexException( __FILE__ , __LINE__ );
00097       }
00098       if ( m_a.size() != k )
00099       {
00100          throw CODEX_Exceptions::IllegalIndexException( __FILE__ , __LINE__ );
00101       }
00102 
00103       es = publicKey.encrypt( s );
00104 
00105       unsigned int length = m_a.marshal(0);
00106       length += es->marshal(0);
00107       length += id.marshal(0);
00108 
00109       buff = new unsigned char[length];
00110       unsigned char* pBuff = buff;
00111       m_a.marshal(&pBuff);
00112       es->marshal(&pBuff);
00113       id.marshal(&pBuff);
00114       str = hashFunc( CODEX_ASN1::ustring(buff,length), ln );
00115       delete [] buff;
00116       buff = 0;
00117       delete es;
00118       es = 0;
00119       for ( int i = 0 ; i < k ; ++i )
00120       {
00121          c = BN_new();
00122          if ( 0 == c )
00123          {
00124             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00125          }
00126          if ( 0 == BN_bin2bn( str->data()+i*sublen, sublen, c ) )
00127          {
00128             throw CODEX_Exceptions::BignumBin2BNException( __FILE__ ,
00129                                                            __LINE__ );
00130          }
00131 
00132          p2 = BN_new();
00133          if ( 0 == p2 )
00134          {
00135             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00136          }
00137          if ( ! BN_mod_exp( p2, s, c, n, ctx ) )
00138          {
00139             throw CODEX_Exceptions::BignumModExpException( __FILE__ ,
00140                                                            __LINE__ );
00141          }
00142          if ( ! BN_mod_mul( p2, p2, vr[i], n, ctx ) )
00143          {
00144             throw CODEX_Exceptions::BignumModMulException( __FILE__ ,
00145                                                            __LINE__ );
00146          }
00147          m_b.append( new CODEX_ASN1::BigNumber( p2 ) );
00148          p2 = 0;
00149          BN_free(c);
00150          c = 0;
00151          BN_clear_free(vr[i]);
00152          vr[i] = 0;
00153       }
00154       delete str;
00155       str = 0;
00156 
00157       BN_CTX_free(ctx);
00158    }
00159    catch ( ... )
00160    {
00161       if ( 0 != ctx ) BN_CTX_free( ctx );
00162       if ( 0 != r ) BN_clear_free( r );
00163       if ( 0 != p1 ) delete p1;
00164       if ( 0 != es ) delete es;
00165       if ( 0 != c ) BN_free( c );
00166       if ( 0 != str ) delete str;
00167       if ( 0 != buff ) delete [] buff;
00168       for ( VBNType::iterator itr = vr.begin() ; itr != vr.end() ; ++itr )
00169       {
00170          BN_clear_free( *itr );
00171       }
00172       throw;
00173    }
00174 }
00175 
00176 RSAPlaintextPK::RSAPlaintextPK( const RSAPlaintextPK& aPPK ) :
00177    CODEX_ASN1::Base( aPPK.m_initialized ),
00178    m_a( aPPK.m_a ),
00179    m_b( aPPK.m_b )
00180 {
00181 }
00182 
00183 RSAPlaintextPK::~RSAPlaintextPK()
00184 {
00185 }
00186 
00187 void
00188 RSAPlaintextPK::operator=( const RSAPlaintextPK& aPPK )
00189 {
00190    m_initialized = aPPK.m_initialized;
00191    m_a           = aPPK.m_a;
00192    m_b           = aPPK.m_b;
00193 }
00194 
00195 bool
00196 RSAPlaintextPK::verify( const RSACipherText& ciphertext,
00197                         const RSAPublicKey& publicKey,
00198                         const CODEX_ASN1::Base& id,
00199                         const HashFunction& hashFunc ) const
00200 {
00201    if ( ! ( ciphertext.initialized() &&
00202             publicKey.initialized() &&
00203             id.initialized() ) )
00204    {
00205       throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00206    }
00207 
00208    int Ln = BN_num_bytes( publicKey.n().value() );
00209    int ln = BN_num_bits( publicKey.n().value() );
00210    int Le = BN_num_bytes( publicKey.e().value() );
00211    int sublen = Le - 1;
00212    int k = Ln / sublen;
00213 
00214    if ( m_a.size() != k )
00215    {
00216       return false;
00217    }
00218    if ( m_b.size() != k )
00219    {
00220       return false;
00221    }
00222 
00223    for ( int i = 0 ; i < k ; ++i )
00224    {
00225       if ( BN_is_zero( m_a.element(i)->value() ) )
00226       {
00227          return false;
00228       }
00229    }
00230 
00231 #ifdef TIMING
00232    RSAPPKTimer.start();
00233 #endif
00234    const BIGNUM * e         = publicKey.e().value();
00235    const BIGNUM * n         = publicKey.n().value();
00236    const BIGNUM * ct        = ciphertext.value();
00237    CODEX_ASN1::ustring* str = 0;
00238    unsigned char* buff      = 0;
00239    BIGNUM * c               = 0;
00240    BIGNUM * ep2             = 0;
00241    BIGNUM * ecp1            = 0;
00242    BN_CTX * ctx             = 0;
00243    try
00244    {
00245       ctx = BN_CTX_new();
00246       if ( 0 == ctx )
00247       {
00248          throw CODEX_Exceptions::BignumContextException( __FILE__ , __LINE__ );
00249       }
00250 
00251       unsigned int length = m_a.marshal(0);
00252       length += ciphertext.marshal(0);
00253       length += id.marshal(0);
00254       buff = new unsigned char[length];
00255       unsigned char* pBuff = buff;
00256       m_a.marshal(&pBuff);
00257       ciphertext.marshal(&pBuff);
00258       id.marshal(&pBuff);
00259       str = hashFunc( CODEX_ASN1::ustring(buff,length), ln );
00260       delete [] buff;
00261       buff = 0;
00262 
00263       bool retVal = true;
00264       for ( int i = 0 ;
00265             retVal && ( i < k ) ;
00266             ++i )
00267       {
00268          c = BN_new();
00269          if ( 0 == c )
00270          {
00271             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00272          }
00273          if ( 0 == BN_bin2bn( str->data()+i*sublen, sublen, c ) )
00274          {
00275             throw CODEX_Exceptions::BignumBin2BNException( __FILE__ ,
00276                                                            __LINE__ );
00277          }
00278 
00279          ep2 = BN_new();
00280          if ( 0 == ep2 )
00281          {
00282             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00283          }
00284          if ( ! BN_mod_exp( ep2, m_b.element(i)->value(), e, n, ctx ) )
00285          {
00286             throw CODEX_Exceptions::BignumModExpException( __FILE__ ,
00287                                                            __LINE__ );
00288          }
00289 
00290          ecp1 = BN_new();
00291          if ( 0 == ecp1 )
00292          {
00293             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00294          }
00295          if ( ! BN_mod_exp( ecp1, ct, c, n, ctx ) )
00296          {
00297             throw CODEX_Exceptions::BignumModExpException( __FILE__ ,
00298                                                            __LINE__ );
00299          }
00300          if ( ! BN_mod_mul( ecp1, ecp1, m_a.element(i)->value(), n, ctx ) )
00301          {
00302             throw CODEX_Exceptions::BignumModMulException( __FILE__ ,
00303                                                            __LINE__ );
00304          }
00305          BN_free( c );
00306          c = 0;
00307 
00308          if ( 0 != BN_cmp( ep2, ecp1 ) )
00309          {
00310             retVal = false;
00311          }
00312          BN_free( ep2 ); ep2 = 0;
00313          BN_free( ecp1 ); ecp1 = 0;
00314       }
00315 
00316       delete str;
00317       str = 0;
00318       BN_CTX_free( ctx );
00319 #ifdef TIMING
00320       RSAPPKTimer.stop();
00321 #endif
00322       return retVal;
00323    }
00324    catch ( ... )
00325    {
00326       if ( 0 != ctx  ) BN_CTX_free( ctx );
00327       if ( 0 != str  ) delete str;
00328       if ( 0 != buff ) delete [] buff;
00329       if ( 0 != c    ) BN_free( c );
00330       if ( 0 != ep2  ) BN_free( ep2 );
00331       if ( 0 != ecp1 ) BN_free( ecp1 );
00332 #ifdef TIMING
00333       RSAPPKTimer.stop();
00334 #endif
00335       throw;
00336    }
00337 }
00338 
00339 int
00340 RSAPlaintextPK::marshal( unsigned char ** pp ) const
00341 {
00342    int r=0;
00343    int ret=0;
00344    unsigned char * p;
00345 
00346    ret += m_a.marshal(0);
00347    ret += m_b.marshal(0);
00348    M_ASN1_I2D_seq_total();
00349    m_a.marshal(&p);
00350    m_b.marshal(&p);
00351    M_ASN1_I2D_finish();
00352 }
00353 
00354 void*
00355 RSAPlaintextPK::unmarshal( void* bogus, unsigned char ** pp, long length )
00356 {
00357    if ( m_initialized )
00358    {
00359       return NULL;
00360    }
00361    if ( (NULL == pp) || (NULL == *pp) )
00362    {
00363       return NULL;
00364    }
00365 
00366    ASN1_CTX c;
00367    c.pp = pp;
00368    c.q = *pp;
00369    c.error = ERR_R_NESTED_ASN1_ERROR;
00370    int i;
00371 
00372    M_ASN1_D2I_Init();
00373    M_ASN1_D2I_start_sequence();
00374    M_ASN1_D2I_get(i, m_a.unmarshal);
00375    M_ASN1_D2I_get(i, m_b.unmarshal);
00376    if ( !asn1_Finish(&c) )
00377    {
00378       return NULL;
00379    }
00380    *pp=c.p;
00381    m_initialized = true;
00382    return this;
00383   err: // needed by ASN.1 macros
00384    return NULL;
00385 }

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