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

cryptosystem_comparison.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: cryptosystem_comparison.cc,v 1.5 2005/01/15 03:41:37 mmarsh Exp $
00008 //
00009 // $Log: cryptosystem_comparison.cc,v $
00010 // Revision 1.5  2005/01/15 03:41:37  mmarsh
00011 // Updated to work with more recent versions of g++.
00012 //
00013 // Revision 1.4  2004/05/19 15:56:46  mmarsh
00014 // *** empty log message ***
00015 //
00016 // Revision 1.3  2003/11/04 22:07:35  mmarsh
00017 // General code cleanup and reorganization.
00018 //
00019 //
00020 
00021 #include <fstream>
00022 #include <sstream>
00023 #include <openssl/ssl.h>
00024 #include <openssl/conf.h>
00025 #include <unistd.h>
00026 
00027 #include "CODEX_Ciphers/RSA.h"
00028 #include "CODEX_Ciphers/RSAPlaintextPK.h"
00029 #include "CODEX_Ciphers/VarRSA.h"
00030 #include "CODEX_Ciphers/ElGamal.h"
00031 #include "CODEX_Ciphers/SHA1HashFunction.h"
00032 #include "CODEX_Server/ConfigurationExceptions.h"
00033 #include "CODEX_Server/ServerState.h"
00034 #include "CODEX_ThresholdCrypto/CombinatoricThresholdRSA.h"
00035 
00036 #include "timing.h"
00037 
00038 using namespace CODEX_Server;
00039 using namespace std;
00040 
00041 int main( int argc, char** argv )
00042 {
00043 #ifndef TIMING
00044    cerr << "Timing must be configured" << endl;
00045    return 1;
00046 #else
00047 
00048    SSLeay_add_ssl_algorithms();
00049 
00050    int arg = 0;
00051    string fname;
00052    string config_section;
00053    string usage_string(
00054       "Usage: cryptosystem_comparison -c <config_file> [-s <section>]");
00055    while ( -1 != arg )
00056    {
00057       arg = getopt(argc,argv,"c:s:");
00058       switch(arg)
00059       {
00060          case 'c' :
00061             fname = optarg;
00062             break;
00063          case 's' :
00064             config_section = optarg;
00065             break;
00066          case ':' :
00067          case '?' :
00068             cerr << usage_string << endl;
00069             ::exit(1);
00070       }
00071    }
00072    if ( 0 == fname.size() )
00073    {
00074       cerr << usage_string << endl;
00075       ::exit(1);
00076    }
00077 
00078    unsigned int nerror = 0;
00079    try
00080    {
00081       CONF* conf = NCONF_new(NCONF_default());
00082       if ( 0 == NCONF_load(conf,fname.c_str(),0) )
00083       {
00084          throw CODEX_Exceptions::FileCannotOpenException( __FILE__ ,
00085                                                           __LINE__ ,
00086                                                           fname );
00087       }
00088       char* section = (char*) config_section.c_str();
00089 
00090       const unsigned int N = ServerState::nServers;
00091       const unsigned int T = 1 + ServerState::nFaults;
00092 
00093       long dummy;
00094       if ( ! NCONF_get_number_e(conf,section,"nhosts",&dummy) )
00095       {
00096          throw BCParameterNotDefinedException( __FILE__ , __LINE__ ,
00097                                                fname, "nhosts" );
00098       }
00099       if ( N != dummy )
00100       {
00101          throw BCBadValueException( __FILE__ , __LINE__ , fname, "nhosts" );
00102       }
00103       if ( ! NCONF_get_number_e(conf,section,"nfaults",&dummy) )
00104       {
00105          throw BCParameterNotDefinedException( __FILE__ , __LINE__ ,
00106                                                fname, "nfaults" );
00107       }
00108       if ( (T-1) != dummy )
00109       {
00110          throw BCBadValueException( __FILE__ , __LINE__ , fname, "nfaults" );
00111       }
00112 
00113       const char* pubKeyFile =
00114          NCONF_get_string(conf,section,"service_cert_file");
00115       if ( 0 == pubKeyFile )
00116       {
00117          throw BCBadValueException( __FILE__ , __LINE__ ,
00118                                     fname, "service_cert_file" );
00119       }
00120       CODEX_ASN1::Certificate cert;
00121       cert.fromPEMFile( pubKeyFile );
00122       CODEX_Ciphers::RSAPublicKey pubKey( cert.value() );
00123 
00124       const char* privKeyFile =
00125          NCONF_get_string(conf,section,"private_key_file");
00126       if ( 0 == privKeyFile )
00127       {
00128          throw BCBadValueException( __FILE__ , __LINE__ ,
00129                                     fname, "private_key_file" );
00130       }
00131       const char* privKeyPasswd =
00132          NCONF_get_string(conf,section,"private_key_passwd");
00133       CODEX_Ciphers::RSAPrivateKey privKey;
00134       privKey.fromPEMFile( privKeyFile, privKeyPasswd );
00135 
00136       const char* pubEGKeyFile =
00137          NCONF_get_string(conf,section,"public_eg_key_file");
00138       if ( 0 == pubEGKeyFile )
00139       {
00140          throw BCParameterNotDefinedException( __FILE__ , __LINE__ ,
00141                                                fname, "public_eg_key_file" );
00142       }
00143       const char* privEGKeyFile =
00144          NCONF_get_string(conf,section,"private_eg_key_file");
00145       if ( 0 == privEGKeyFile )
00146       {
00147          throw BCParameterNotDefinedException( __FILE__ , __LINE__ ,
00148                                                fname, "private_eg_key_file" );
00149       }
00150 
00151       CODEX_Server::SignedAugmentedEGPublicKey signedPubEGKey;
00152       ifstream is(pubEGKeyFile);
00153       if ( ! is.is_open() )
00154       {
00155          throw CODEX_Exceptions::FileCannotOpenException( __FILE__ ,
00156                                                           __LINE__ ,
00157                                                           pubEGKeyFile );
00158       }
00159       string s;
00160       char ch;
00161       while ( is.get(ch) )
00162       {
00163          s.push_back(ch);
00164       }
00165       //basic_string<unsigned char> s;
00166       //is >> s;
00167       unsigned int length = s.length();
00168       //unsigned char* p = (unsigned char*)s.data();
00169       unsigned char* p = new unsigned char[length];
00170       unsigned char* pOrig = p;
00171       for ( unsigned int i = 0 ; i < length ; ++i )
00172       {
00173          p[i] = s.data()[i];
00174       }
00175       if ( 0 == signedPubEGKey.unmarshal(0,&p,length) )
00176       {
00177          delete [] pOrig;
00178          throw PublicKeyNotFoundException( __FILE__ , __LINE__ );
00179       }
00180       delete [] pOrig;
00181       const CODEX_Ciphers::ElGamalPublicKey& pubEGKey =
00182          signedPubEGKey.key().key();
00183       CODEX_Ciphers::ElGamalPrivateKey privEGKey;
00184       privEGKey.fromFile( privEGKeyFile );
00185 
00186       typedef CODEX_VSS::ModExpFunctional                     OneWay;
00187       typedef CODEX_VSS::Combinatoric< N , T >                ShareType;
00188       typedef CODEX_VSS::LabeledShare< ShareType , OneWay >   LSType;
00189       typedef CODEX_VSS::SecretWitness< ShareType , OneWay >  WitnessType;
00190 
00191       const char* output_dir =
00192          NCONF_get_string(conf,section,"output_directory");
00193       if ( 0 == output_dir )
00194       {
00195          throw BCParameterNotDefinedException( __FILE__ , __LINE__ ,
00196                                                fname, "output_directory" );
00197       }
00198 
00199       WitnessType rsaWitness;
00200       ostringstream rwstr;
00201       rwstr << output_dir << "/rsa.witness\0";
00202       rsaWitness.fromFile( rwstr.str().c_str() );
00203 
00204       WitnessType egWitness;
00205       ostringstream ewstr;
00206       ewstr << output_dir << "/elgamal.witness\0";
00207       egWitness.fromFile( ewstr.str().c_str() );
00208 
00209       LSType rsaSharings[N];
00210       LSType elgamalSharings[N];
00211       for ( unsigned int i = 0 ; i < N ; ++i )
00212       {
00213          ostringstream rstr;
00214          rstr << output_dir << "/rsa." << i << ".shares" << '\0';
00215          rsaSharings[i].fromFile( rstr.str().c_str() );
00216          ostringstream estr;
00217          estr << output_dir << "/elgamal." << i << ".shares" << '\0';
00218          elgamalSharings[i].fromFile( estr.str().c_str() );
00219       }
00220 
00221       // Clean up CONF object.
00222       NCONF_free( conf );
00223 
00224       // Now that we have everything read in it's time to perform our tests.
00225       // We assume that the partial decryption for RSA uses a different
00226       // timer than the partial decryption for ElGamal.  This will only
00227       // be true during the testing, since it makes more sense for them
00228       // both to use the same timer, since only one will generally be
00229       // in use at one time.
00230 
00231       // For our earlier timing studies, the client used its private RSA
00232       // exponent.  Here we'll use the service's private RSA exponent.
00233       // There are two tests to do:
00234       //
00235       //  1) partial (blind) decryption in RSA vs ElGamal
00236       //  2) verifying Schnorr-signed ElGamal ciphertexts vs the Ohta-Okamoto
00237       //     RSA plaintext-knowledge proof
00238 
00239       // First we set up the plaintext, ciphertexts, proofs, etc.
00240       // The RSA public key will be used as the credentials.
00241       const CODEX_ASN1::SecureBigNumber& plaintext = privKey.d();
00242       const CODEX_Ciphers::HashFunction& hashFunc =
00243          ServerState::instance()->hashFunc();
00244 
00245       const BIGNUM * bmax = ( pubKey.n() > pubEGKey.p() ) ?
00246          pubEGKey.p().value() :
00247          pubKey.n().value();
00248 
00249       BIGNUM * r = 0;
00250       BIGNUM * b = 0;
00251 
00252       CODEX_Ciphers::VarRSAPublicKey         varRSAEncKey( pubKey );
00253       CODEX_Ciphers::VarRSACipherText*       rsaEncryption      = 0;
00254       CODEX_Ciphers::RSAPlaintextPK*         rsaProof           = 0;
00255       CODEX_Ciphers::RSACipherText*          rsaBlindingCipher  = 0;
00256       CODEX_Ciphers::VarRSABlindCipherText*  rsaBlindEncryption = 0;
00257 
00258       CODEX_Ciphers::ElGamalSchnorrCipherText*  egEncryption      = 0;
00259       CODEX_Ciphers::ElGamalSchnorrCipherText*  egBlindingCipher  = 0;
00260       CODEX_Ciphers::ElGamalCipherText*         egBlindEncryption = 0;
00261 
00262       try
00263       {
00264          r = BN_new();
00265          if ( 0 == r )
00266          {
00267             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00268          }
00269          rsaEncryption =
00270             varRSAEncKey.encrypt( plaintext.value(), hashFunc, r );
00271          rsaProof =
00272             new CODEX_Ciphers::RSAPlaintextPK( r, pubKey, pubKey, hashFunc );
00273          r = 0;
00274 
00275          egEncryption =
00276             pubEGKey.encryptS( plaintext.value(), pubKey, hashFunc );
00277       }
00278       catch ( ... )
00279       {
00280          if ( 0 != r ) BN_clear_free(r);
00281          if ( 0 != rsaEncryption ) delete rsaEncryption;
00282          if ( 0 != rsaProof ) delete rsaProof;
00283          if ( 0 != egEncryption ) delete egEncryption;
00284          throw;
00285       }
00286 
00287       CODEX_ThresholdCrypto::ThresholdVarRSACrypto< ShareType >
00288          tRSA( pubKey.n() );
00289       CODEX_ThresholdCrypto::ThresholdElGamalCrypto< ShareType >
00290          tEG( pubEGKey.p() );
00291 
00292       ShareType rsaDecShares;
00293       ShareType egDecShares;
00294 
00295       // Now we loop...
00296       for ( unsigned int i = 0 ; i < 100000 ; ++i )
00297       {
00298          if ( 0 == i%1000 )
00299          {
00300             PartialDecTimer.print(cout);
00301             PartialRSADecTimer.print(cout);
00302             SchnorrTimer.print(cout);
00303             RSAPPKTimer.print(cout);
00304 
00305             PartialDecTimer.clear();
00306             PartialRSADecTimer.clear();
00307             SchnorrTimer.clear();
00308             RSAPPKTimer.clear();
00309          }
00310          try
00311          {
00312             // Verify the proofs
00313             if ( ! egEncryption->verify( pubEGKey.g(),
00314                                          pubEGKey.p(),
00315                                          pubKey,
00316                                          hashFunc ) )
00317             {
00318                cerr << "Failed to verify Schnorr proof!" << endl;
00319                return 1;
00320             }
00321             if ( ! rsaProof->verify( rsaEncryption->c1(),
00322                                      pubKey,
00323                                      pubKey,
00324                                      hashFunc ) )
00325             {
00326                cerr << "Failed to verify RSA proof!" << endl;
00327                return 1;
00328             }
00329 
00330             // Set up blinding
00331             b = BN_new();
00332             if ( 0 == b )
00333             {
00334                throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00335                                                             __LINE__ );
00336             }
00337             if ( ! BN_rand_range( b, (BIGNUM*)bmax ) )
00338             {
00339                throw CODEX_Exceptions::BignumRandRangeException( __FILE__ ,
00340                                                                  __LINE__ );
00341             }
00342             rsaBlindingCipher = pubKey.encrypt( b );
00343             egBlindingCipher = pubEGKey.encryptS( b, pubKey, hashFunc );
00344             BN_clear_free( b );
00345             b = 0;
00346 
00347             // Blind ciphertexts
00348             rsaBlindEncryption =
00349                rsaEncryption->blind( *rsaBlindingCipher, pubKey.n() );
00350             egBlindEncryption =
00351                egEncryption->blind( *egBlindingCipher, pubEGKey.p() );
00352 
00353             // Perform partial decryptions
00354             tRSA.decrypt( rsaSharings[0].share(),
00355                           *rsaBlindEncryption,
00356                           rsaDecShares );
00357             tEG.decrypt( elgamalSharings[0].share(),
00358                          *egBlindEncryption,
00359                          egDecShares );
00360 
00361             delete rsaBlindingCipher;
00362             delete egBlindingCipher;
00363             delete rsaBlindEncryption;
00364             delete egBlindEncryption;
00365          }
00366          catch ( ... )
00367          {
00368             if ( 0 != b ) BN_clear_free(b);
00369             if ( 0 != rsaBlindingCipher ) delete rsaBlindingCipher;
00370             if ( 0 != egBlindingCipher ) delete egBlindingCipher;
00371             if ( 0 != rsaBlindEncryption ) delete rsaBlindEncryption;
00372             if ( 0 != egBlindEncryption ) delete egBlindEncryption;
00373             throw;
00374          }
00375       }
00376 
00377       delete rsaEncryption;
00378       delete rsaProof;
00379       delete egEncryption;
00380 
00381    }
00382    catch ( CODEX_Exceptions::ExceptionBase& e )
00383    {
00384       e.report();
00385       return 1;
00386    }
00387 
00388    PartialDecTimer.print(cout);
00389    PartialRSADecTimer.print(cout);
00390    SchnorrTimer.print(cout);
00391    RSAPPKTimer.print(cout);
00392 
00393    return 0;
00394 #endif
00395 }

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