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

Generated on Wed Jun 2 16:32:54 2004 for COrnell Data EXchange (CODEX) by doxygen1.2.18