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

ElGamalPrivateKey.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: ElGamalPrivateKey.cc,v 1.3 2004/05/19 15:56:47 mmarsh Exp $
00008 //
00009 // $Log: ElGamalPrivateKey.cc,v $
00010 // Revision 1.3  2004/05/19 15:56:47  mmarsh
00011 // *** empty log message ***
00012 //
00013 // Revision 1.2  2003/11/04 22:31:47  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include <fstream>
00019 #include "ElGamal.h"
00020 #include "jacobi.h"
00021 #include "CODEX_Exceptions/BignumExceptions.h"
00022 #include "CODEX_Exceptions/FileExceptions.h"
00023 
00024 using namespace CODEX_Ciphers;
00025 using namespace CODEX_Exceptions;
00026 using CODEX_ASN1::BigNumber;
00027 using CODEX_ASN1::SecureBigNumber;
00028 
00029 ElGamalPrivateKey::ElGamalPrivateKey() :
00030    SecureBigNumber()
00031 {
00032 }
00033 
00034 ElGamalPrivateKey::ElGamalPrivateKey( BIGNUM * x ) :
00035    SecureBigNumber( x )
00036 {
00037 }
00038 
00039 ElGamalPrivateKey::ElGamalPrivateKey( const CODEX_ASN1::BigNumber& x ) :
00040    SecureBigNumber( x )
00041 {
00042 }
00043 
00044 ElGamalPrivateKey::~ElGamalPrivateKey()
00045 {
00046 }
00047 
00048 BIGNUM *
00049 ElGamalPrivateKey::decrypt( const ElGamalCipherText& cipherText,
00050                             const ElGamalPublicKey& publicKey ) const
00051 {
00052    BN_CTX * ctx    = 0;
00053    BIGNUM * retVal = 0;
00054 
00055    try
00056    {
00057       ctx = BN_CTX_new();
00058       if ( 0 == ctx )
00059       {
00060          throw BignumContextException( __FILE__ , __LINE__ );
00061       }
00062 
00063       // We're abusing retVal here, since allocating new BIGNUMs is
00064       // an expensive operation.
00065       retVal = BN_new();
00066       if ( 0 == retVal )
00067       {
00068          throw BignumNullException( __FILE__ , __LINE__ );
00069       }
00070       // retVal = c1^x mod p
00071       if ( ! BN_mod_exp( retVal,
00072                          cipherText.c1().value(),
00073                          m_value,
00074                          publicKey.p().value(),
00075                          ctx ) )
00076       {
00077          throw BignumModExpException( __FILE__ , __LINE__ );
00078       }
00079 
00080       // retVal = 1/retVal mod p = c1^(-x) mod p
00081       if ( ! BN_mod_inverse( retVal, retVal, publicKey.p().value(), ctx ) )
00082       {
00083          throw BignumModInverseException( __FILE__ , __LINE__ );
00084       }
00085 
00086       // retVal = c2*retVal mod p = c2 * c1^(-x) mod p
00087       if ( ! BN_mod_mul( retVal,
00088                          cipherText.c2().value(),
00089                          retVal,
00090                          publicKey.p().value(),
00091                          ctx ) )
00092       {
00093          throw BignumModMulException( __FILE__ , __LINE__ );
00094       }
00095 
00096       // map retVal back into [0,q)
00097       if ( BN_cmp( retVal, publicKey.q() ) >= 0 )
00098       {
00099          if ( ! BN_sub( retVal, publicKey.p().value(), retVal ) )
00100          {
00101             throw BignumSubException( __FILE__ , __LINE__ );
00102          }
00103       }
00104 
00105       BN_CTX_free(ctx);
00106       return retVal;
00107    }
00108    catch ( ... )
00109    {
00110       if ( 0 != ctx    ) BN_CTX_free(ctx);
00111       if ( 0 != retVal ) BN_clear_free(retVal);
00112       throw;
00113    }
00114 }
00115 
00119 ElGamalSignature*
00120 ElGamalPrivateKey::sign( const BIGNUM * message,
00121                          const ElGamalPublicKey& publicKey ) const
00122 {
00123    if ( 0 == message )
00124    {
00125       throw BignumNullException( __FILE__ , __LINE__ );
00126    }
00127 
00128    // We're going to abuse some of the BIGNUMs we create, since
00129    // allocating a new BIGNUM is an expensive operation.
00130    BN_CTX * ctx      = 0;
00131    BIGNUM * q        = 0;
00132    BIGNUM * k        = 0;
00133    BIGNUM * temp     = 0;
00134    BIGNUM * r        = 0;
00135    BIGNUM * s        = 0;
00136    BIGNUM * xr       = 0;
00137 
00138    try
00139    {
00140       ctx = BN_CTX_new();
00141       if ( 0 == ctx )
00142       {
00143          throw BignumContextException( __FILE__ , __LINE__ );
00144       }
00145 
00146       q = (BIGNUM*)publicKey.q();
00147 
00148       // k is random in (1,q)
00149       k = BN_new();
00150       if ( 0 == k )
00151       {
00152          throw BignumNullException( __FILE__ , __LINE__ );
00153       }
00154 
00155       temp = BN_new();
00156       if ( 0 == temp )
00157       {
00158          throw BignumNullException( __FILE__ , __LINE__ );
00159       }
00160 
00161       do
00162       {
00163          if ( ! BN_rand_range( k, q ) )
00164          {
00165             throw BignumRandRangeException( __FILE__ , __LINE__ );
00166          }
00167       } while ( 0 >= BN_cmp( k, BN_value_one() ) ); // k=0,1 are detectable
00168 
00169       // r = g^k mod p
00170       r = BN_new();
00171       if ( 0 == r )
00172       {
00173          throw BignumNullException( __FILE__ , __LINE__ );
00174       }
00175       if ( ! BN_mod_exp( r,
00176                          publicKey.g().value(),
00177                          k,
00178                          publicKey.p().value(),
00179                          ctx ) )
00180       {
00181          throw BignumModExpException( __FILE__ , __LINE__ );
00182       }
00183 
00184       // Abuse k : k = 1/k mod q
00185       if ( ! BN_mod_inverse( k, k, q, ctx ) )
00186       {
00187          throw BignumModInverseException( __FILE__ , __LINE__ );
00188       }
00189 
00190       // xr = x*r mod q
00191       xr = BN_new();
00192       if ( 0 == xr )
00193       {
00194          throw BignumNullException( __FILE__ , __LINE__ );
00195       }
00196       if ( ! BN_mod_mul( xr, m_value, r, q, ctx ) )
00197       {
00198          throw BignumModMulException( __FILE__ , __LINE__ );
00199       }
00200 
00201       // temp = m - xr
00202       if ( ! BN_sub( temp, message, xr ) )
00203       {
00204          throw BignumSubException( __FILE__ , __LINE__ );
00205       }
00206 
00207       // temp = temp + q (make non-negative)
00208       if ( ! BN_add( temp, temp, q ) )
00209       {
00210          throw BignumAddException( __FILE__ , __LINE__ );
00211       }
00212 
00213       // s = k*temp mod q = (m-x*r)/k mod q
00214       s = BN_new();
00215       if ( 0 == s )
00216       {
00217          throw BignumNullException( __FILE__ , __LINE__ );
00218       }
00219       if ( ! BN_mod_mul( s, k, temp, q, ctx ) )
00220       {
00221          throw BignumModMulException( __FILE__ , __LINE__ );
00222       }
00223 
00224       BN_clear_free( k );     k = 0;
00225       BN_clear_free( temp );  temp = 0;
00226       BN_clear_free( xr );    xr = 0;
00227       BN_CTX_free( ctx );     ctx = 0;
00228 
00229       return new ElGamalSignature( r, s );
00230    }
00231    catch ( ... )
00232    {
00233       if ( 0 != ctx      ) BN_CTX_free( ctx );
00234       if ( 0 != k        ) BN_clear_free( k );
00235       if ( 0 != temp     ) BN_clear_free( temp );
00236       if ( 0 != xr       ) BN_clear_free( xr );
00237       if ( 0 != r        ) BN_free( r );
00238       if ( 0 != s        ) BN_free( s );
00239       throw;
00240    }
00241 }
00242 
00243 void
00244 ElGamalPrivateKey::toFile(const char* fname) const
00245 {
00246    int length = marshal(0);
00247    if ( 0 == length ) return;
00248    unsigned char* buff = new unsigned char[length];
00249    unsigned char* p = buff;
00250    marshal(&p);
00251    ofstream os(fname);
00252    if ( ! os.is_open() )
00253    {
00254       delete [] buff;
00255       throw FileCannotCreateException( __FILE__ , __LINE__ , fname );
00256    }
00257    for ( int i = 0 ; i < length ; ++i )
00258    {
00259       os << buff[i];
00260    }
00261    os.close();
00262    delete [] buff;
00263 }
00264 
00265 void*
00266 ElGamalPrivateKey::fromFile(const char* fname)
00267 {
00268    ifstream is(fname);
00269    if ( ! is.is_open() )
00270    {
00271       throw FileCannotOpenException( __FILE__ , __LINE__ , fname );
00272    }
00273    string s;
00274    char ch;
00275    while ( is.get(ch) )
00276    {
00277       s.push_back(ch);
00278    }
00279    //basic_string<unsigned char> s;
00280    //is >> s;
00281    unsigned int length = s.length();
00282    unsigned char* p = new unsigned char[ length ];
00283    unsigned char* pOrig = p;
00284    for ( unsigned int i = 0 ; i < length ; ++i )
00285    {
00286       p[i] = s.data()[i];
00287    }
00288    //unsigned char* p = (unsigned char*)s.data();
00289    void* retVal = unmarshal(0,&p,length);
00290    delete [] pOrig;
00291    return retVal;
00292 }

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