00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00064
00065 retVal = BN_new();
00066 if ( 0 == retVal )
00067 {
00068 throw BignumNullException( __FILE__ , __LINE__ );
00069 }
00070
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
00081 if ( ! BN_mod_inverse( retVal, retVal, publicKey.p().value(), ctx ) )
00082 {
00083 throw BignumModInverseException( __FILE__ , __LINE__ );
00084 }
00085
00086
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
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
00129
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
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() ) );
00168
00169
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
00185 if ( ! BN_mod_inverse( k, k, q, ctx ) )
00186 {
00187 throw BignumModInverseException( __FILE__ , __LINE__ );
00188 }
00189
00190
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
00202 if ( ! BN_sub( temp, message, xr ) )
00203 {
00204 throw BignumSubException( __FILE__ , __LINE__ );
00205 }
00206
00207
00208 if ( ! BN_add( temp, temp, q ) )
00209 {
00210 throw BignumAddException( __FILE__ , __LINE__ );
00211 }
00212
00213
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
00280
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
00289 void* retVal = unmarshal(0,&p,length);
00290 delete [] pOrig;
00291 return retVal;
00292 }