Botan
1.11.15
|
00001 /* 00002 * ElGamal 00003 * (C) 1999-2007 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/pk_utils.h> 00009 #include <botan/elgamal.h> 00010 #include <botan/keypair.h> 00011 #include <botan/reducer.h> 00012 #include <botan/blinding.h> 00013 #include <botan/workfactor.h> 00014 00015 namespace Botan { 00016 00017 /* 00018 * ElGamal_PublicKey Constructor 00019 */ 00020 ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& grp, const BigInt& y1) 00021 { 00022 group = grp; 00023 y = y1; 00024 } 00025 00026 /* 00027 * ElGamal_PrivateKey Constructor 00028 */ 00029 ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, 00030 const DL_Group& grp, 00031 const BigInt& x_arg) 00032 { 00033 group = grp; 00034 x = x_arg; 00035 00036 if(x == 0) 00037 x.randomize(rng, 2 * dl_work_factor(group_p().bits())); 00038 00039 y = power_mod(group_g(), x, group_p()); 00040 00041 if(x_arg == 0) 00042 gen_check(rng); 00043 else 00044 load_check(rng); 00045 } 00046 00047 ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, 00048 const secure_vector<byte>& key_bits, 00049 RandomNumberGenerator& rng) : 00050 DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42) 00051 { 00052 y = power_mod(group_g(), x, group_p()); 00053 load_check(rng); 00054 } 00055 00056 /* 00057 * Check Private ElGamal Parameters 00058 */ 00059 bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng, 00060 bool strong) const 00061 { 00062 if(!DL_Scheme_PrivateKey::check_key(rng, strong)) 00063 return false; 00064 00065 if(!strong) 00066 return true; 00067 00068 return KeyPair::encryption_consistency_check(rng, *this, "EME1(SHA-1)"); 00069 } 00070 00071 namespace { 00072 00073 /** 00074 * ElGamal encryption operation 00075 */ 00076 class ElGamal_Encryption_Operation : public PK_Ops::Encryption 00077 { 00078 public: 00079 typedef ElGamal_PublicKey Key_Type; 00080 00081 size_t max_input_bits() const { return mod_p.get_modulus().bits() - 1; } 00082 00083 ElGamal_Encryption_Operation(const ElGamal_PublicKey& key, const std::string&); 00084 00085 secure_vector<byte> encrypt(const byte msg[], size_t msg_len, 00086 RandomNumberGenerator& rng); 00087 00088 private: 00089 Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; 00090 Modular_Reducer mod_p; 00091 }; 00092 00093 ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key, 00094 const std::string&) 00095 { 00096 const BigInt& p = key.group_p(); 00097 00098 powermod_g_p = Fixed_Base_Power_Mod(key.group_g(), p); 00099 powermod_y_p = Fixed_Base_Power_Mod(key.get_y(), p); 00100 mod_p = Modular_Reducer(p); 00101 } 00102 00103 secure_vector<byte> 00104 ElGamal_Encryption_Operation::encrypt(const byte msg[], size_t msg_len, 00105 RandomNumberGenerator& rng) 00106 { 00107 const BigInt& p = mod_p.get_modulus(); 00108 00109 BigInt m(msg, msg_len); 00110 00111 if(m >= p) 00112 throw Invalid_Argument("ElGamal encryption: Input is too large"); 00113 00114 BigInt k(rng, 2 * dl_work_factor(p.bits())); 00115 00116 BigInt a = powermod_g_p(k); 00117 BigInt b = mod_p.multiply(m, powermod_y_p(k)); 00118 00119 secure_vector<byte> output(2*p.bytes()); 00120 a.binary_encode(&output[p.bytes() - a.bytes()]); 00121 b.binary_encode(&output[output.size() / 2 + (p.bytes() - b.bytes())]); 00122 return output; 00123 } 00124 00125 /** 00126 * ElGamal decryption operation 00127 */ 00128 class ElGamal_Decryption_Operation : public PK_Ops::Decryption 00129 { 00130 public: 00131 typedef ElGamal_PrivateKey Key_Type; 00132 00133 size_t max_input_bits() const { return mod_p.get_modulus().bits() - 1; } 00134 00135 ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key, const std::string& emsa); 00136 00137 secure_vector<byte> decrypt(const byte msg[], size_t msg_len); 00138 private: 00139 Fixed_Exponent_Power_Mod powermod_x_p; 00140 Modular_Reducer mod_p; 00141 Blinder blinder; 00142 }; 00143 00144 ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key, 00145 const std::string&) 00146 { 00147 const BigInt& p = key.group_p(); 00148 00149 powermod_x_p = Fixed_Exponent_Power_Mod(key.get_x(), p); 00150 mod_p = Modular_Reducer(p); 00151 00152 blinder = Blinder(p, 00153 [](const BigInt& k) { return k; }, 00154 [this](const BigInt& k) { return powermod_x_p(k); }); 00155 } 00156 00157 secure_vector<byte> 00158 ElGamal_Decryption_Operation::decrypt(const byte msg[], size_t msg_len) 00159 { 00160 const BigInt& p = mod_p.get_modulus(); 00161 00162 const size_t p_bytes = p.bytes(); 00163 00164 if(msg_len != 2 * p_bytes) 00165 throw Invalid_Argument("ElGamal decryption: Invalid message"); 00166 00167 BigInt a(msg, p_bytes); 00168 BigInt b(msg + p_bytes, p_bytes); 00169 00170 if(a >= p || b >= p) 00171 throw Invalid_Argument("ElGamal decryption: Invalid message"); 00172 00173 a = blinder.blind(a); 00174 00175 BigInt r = mod_p.multiply(b, inverse_mod(powermod_x_p(a), p)); 00176 00177 return BigInt::encode_locked(blinder.unblind(r)); 00178 } 00179 00180 BOTAN_REGISTER_PK_ENCRYPTION_OP("ElGamal", ElGamal_Encryption_Operation); 00181 BOTAN_REGISTER_PK_DECRYPTION_OP("ElGamal", ElGamal_Decryption_Operation); 00182 00183 } 00184 00185 }