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

ElGamalKeyPairGenerator.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: ElGamalKeyPairGenerator.cc,v 1.3 2004/05/19 15:56:47 mmarsh Exp $
00008 //
00009 // $Log: ElGamalKeyPairGenerator.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 "ElGamal.h"
00019 #include "CODEX_Exceptions/BignumExceptions.h"
00020 
00021 using namespace CODEX_Ciphers;
00022 using namespace CODEX_Exceptions;
00023 using CODEX_ASN1::BigNumber;
00024 using CODEX_ASN1::SecureBigNumber;
00025 
00026 void
00027 ElGamalKeyPairGenerator::operator()( ElGamalPublicKey*& pubKey,
00028                                      ElGamalPrivateKey*& privKey,
00029                                      BIGNUM * p,
00030                                      BIGNUM * g )
00031 {
00032    bool ownP = false;
00033    bool ownG = false;
00034 
00035    BIGNUM * p1   = 0;
00036    BN_CTX * ctx  = 0;
00037    BIGNUM * q    = 0;
00038    BIGNUM * temp = 0;
00039    BIGNUM * x    = 0;
00040    BIGNUM * y    = 0;
00041 
00042    try
00043    {
00044       if ( 0 == p )
00045       {
00046          // generate a new modulus -- a safe prime (p=2q+1 where q is prime)
00047          ownP = true;
00048          p = BN_new();
00049          if ( 0 == p )
00050          {
00051             throw BignumNullException( __FILE__ , __LINE__ );
00052          }
00053          if ( 0 == BN_generate_prime( p, m_numBits, 1, 0, 0, 0, 0 ) )
00054          {
00055             throw BignumGeneratePrimeException( __FILE__ , __LINE__ );
00056          }
00057       }
00058       else
00059       {
00060          p = BN_dup(p);
00061          ownP = true;
00062       }
00063 
00064       p1 = BN_new();
00065       if ( 0 == p1 )
00066       {
00067          throw BignumNullException( __FILE__ , __LINE__ );
00068       }
00069       if ( ! BN_sub(p1,p,BN_value_one()) )
00070       {
00071          throw BignumSubException( __FILE__ , __LINE__ );
00072       }
00073 
00074       q = BN_new();
00075       if ( 0 == q )
00076       {
00077          throw BignumNullException( __FILE__ , __LINE__ );
00078       }
00079       if ( ! BN_rshift1(q,p1) ) // q = (p-1)/2
00080       {
00081          throw BignumRshiftException( __FILE__ , __LINE__ );
00082       }
00083 
00084       ctx = BN_CTX_new();
00085       if ( 0 == ctx )
00086       {
00087          throw BignumContextException( __FILE__ , __LINE__ );
00088       }
00089 
00090       if ( 0 == g )
00091       {
00092          // generate a new generator
00093          g = BN_new();
00094          if ( 0 == g )
00095          {
00096             throw BignumNullException( __FILE__ , __LINE__ );
00097          }
00098          ownG = true;
00099          bool flag;
00100          temp = BN_new();
00101          if ( 0 == temp )
00102          {
00103             throw BignumNullException( __FILE__ , __LINE__ );
00104          }
00105          do
00106          {
00107             flag = false;
00108             if ( ! BN_rand_range(g,p) )
00109             {
00110                throw BignumRandRangeException( __FILE__ , __LINE__ );
00111             }
00112             if ( 0 >= BN_cmp( g, BN_value_one() ) )
00113             {
00114                flag = true;
00115             }
00116             else
00117             {
00118                // g is a generator if g^2 and g^q are both different from 1
00119                if ( ! BN_mod_mul(temp, g, g, p, ctx) )
00120                {
00121                   throw BignumModMulException( __FILE__ , __LINE__ );
00122                }
00123                if ( 0 == BN_cmp( temp, BN_value_one() ) )
00124                {
00125                   flag = true;
00126                }
00127                else
00128                {
00129                   if ( ! BN_mod_exp(temp, g, q, p, ctx) )
00130                   {
00131                      throw BignumModExpException( __FILE__ , __LINE__ );
00132                   }
00133                   if ( 0 == BN_cmp( temp, BN_value_one() ) )
00134                   {
00135                      flag = true;
00136                   }
00137                }
00138             }
00139          } while ( flag );
00140          BN_free( temp );
00141          temp = 0;
00142 
00143          // The generator we really want is for the subgroup of order q.
00144          // To get this generator, we simply square the generator we
00145          // currently have.
00146          if ( ! BN_mod_sqr( g, g, p, ctx ) )
00147          {
00148             throw BignumModMulException( __FILE__ , __LINE__ );
00149          }
00150       }
00151       else
00152       {
00153          g = BN_dup(g);
00154          ownG = true;
00155       }
00156 
00157       // now choose a private key x
00158       x = BN_new();
00159       if ( 0 == x )
00160       {
00161          throw BignumNullException( __FILE__ , __LINE__ );
00162       }
00163       do
00164       {
00165          // we choose from the range (1,q) because we're working in a subgroup
00166          if ( ! BN_rand_range(x,q) )
00167          {
00168             throw BignumRandRangeException( __FILE__ , __LINE__ );
00169          }
00170       } while ( 0 >= BN_cmp( g, BN_value_one() ) );
00171 
00172       // now compute the corresponding public key y=g^x mod p
00173       y = BN_new();
00174       if ( 0 == y )
00175       {
00176          throw BignumNullException( __FILE__ , __LINE__ );
00177       }
00178       if ( ! BN_mod_exp(y, g, x, p, ctx) )
00179       {
00180          throw BignumModExpException( __FILE__ , __LINE__ );
00181       }
00182 
00183       pubKey = new ElGamalPublicKey( p, g, y );
00184       privKey = new ElGamalPrivateKey( x );
00185 
00186       BN_CTX_free(ctx);
00187       BN_free(p1);
00188       BN_free( q );
00189    }
00190    catch ( ... )
00191    {
00192       if ( ownP && ( 0 != p ) ) BN_free(p);
00193       if ( ownG && ( 0 != g ) ) BN_free(g);
00194 
00195       if ( 0 != p1   ) BN_free(p1);
00196       if ( 0 != q    ) BN_free(q);
00197       if ( 0 != temp ) BN_free(temp);
00198       if ( 0 != x    ) BN_clear_free(x);
00199       if ( 0 != y    ) BN_free(y);
00200       if ( 0 != ctx  ) BN_CTX_free(ctx);
00201       throw;
00202    }
00203 }

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