Botan  2.4.0
Crypto and TLS for C++11
elgamal.cpp
Go to the documentation of this file.
1 /*
2 * ElGamal
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/elgamal.h>
9 #include <botan/internal/pk_ops_impl.h>
10 #include <botan/keypair.h>
11 #include <botan/reducer.h>
12 #include <botan/blinding.h>
13 #include <botan/workfactor.h>
14 #include <botan/pow_mod.h>
15 
16 namespace Botan {
17 
18 /*
19 * ElGamal_PublicKey Constructor
20 */
22  {
23  m_group = grp;
24  m_y = y1;
25  }
26 
27 /*
28 * ElGamal_PrivateKey Constructor
29 */
31  const DL_Group& grp,
32  const BigInt& x_arg)
33  {
34  m_group = grp;
35  m_x = x_arg;
36 
37  if(m_x == 0)
38  m_x.randomize(rng, dl_exponent_size(group_p().bits()));
39 
40  m_y = power_mod(group_g(), m_x, group_p());
41  }
42 
44  const secure_vector<uint8_t>& key_bits) :
45  DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
46  {
47  m_y = power_mod(group_g(), m_x, group_p());
48  }
49 
50 /*
51 * Check Private ElGamal Parameters
52 */
54  bool strong) const
55  {
56  if(!DL_Scheme_PrivateKey::check_key(rng, strong))
57  return false;
58 
59  if(!strong)
60  return true;
61 
62  return KeyPair::encryption_consistency_check(rng, *this, "EME1(SHA-256)");
63  }
64 
65 namespace {
66 
67 /**
68 * ElGamal encryption operation
69 */
70 class ElGamal_Encryption_Operation final : public PK_Ops::Encryption_with_EME
71  {
72  public:
73 
74  size_t max_raw_input_bits() const override { return m_mod_p.get_modulus().bits() - 1; }
75 
76  ElGamal_Encryption_Operation(const ElGamal_PublicKey& key, const std::string& eme);
77 
78  secure_vector<uint8_t> raw_encrypt(const uint8_t msg[], size_t msg_len,
79  RandomNumberGenerator& rng) override;
80 
81  private:
82  Fixed_Base_Power_Mod m_powermod_g_p, m_powermod_y_p;
84  };
85 
86 ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key,
87  const std::string& eme) :
89  {
90  const BigInt& p = key.group_p();
91 
92  m_powermod_g_p = Fixed_Base_Power_Mod(key.group_g(), p);
93  m_powermod_y_p = Fixed_Base_Power_Mod(key.get_y(), p);
95  }
96 
98 ElGamal_Encryption_Operation::raw_encrypt(const uint8_t msg[], size_t msg_len,
100  {
101  const BigInt& p = m_mod_p.get_modulus();
102 
103  BigInt m(msg, msg_len);
104 
105  if(m >= p)
106  throw Invalid_Argument("ElGamal encryption: Input is too large");
107 
108  BigInt k(rng, dl_exponent_size(p.bits()));
109 
110  BigInt a = m_powermod_g_p(k);
111  BigInt b = m_mod_p.multiply(m, m_powermod_y_p(k));
112 
113  secure_vector<uint8_t> output(2*p.bytes());
114  a.binary_encode(&output[p.bytes() - a.bytes()]);
115  b.binary_encode(&output[output.size() / 2 + (p.bytes() - b.bytes())]);
116  return output;
117  }
118 
119 /**
120 * ElGamal decryption operation
121 */
122 class ElGamal_Decryption_Operation final : public PK_Ops::Decryption_with_EME
123  {
124  public:
125 
126  size_t max_raw_input_bits() const override
127  { return m_mod_p.get_modulus().bits() - 1; }
128 
129  ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key,
130  const std::string& eme,
131  RandomNumberGenerator& rng);
132 
133  secure_vector<uint8_t> raw_decrypt(const uint8_t msg[], size_t msg_len) override;
134  private:
135  Fixed_Exponent_Power_Mod m_powermod_x_p;
138  };
139 
140 ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key,
141  const std::string& eme,
142  RandomNumberGenerator& rng) :
144  m_powermod_x_p(Fixed_Exponent_Power_Mod(key.get_x(), key.group_p())),
146  m_blinder(key.group_p(),
147  rng,
148  [](const BigInt& k) { return k; },
149  [this](const BigInt& k) { return m_powermod_x_p(k); })
150  {
151  }
152 
154 ElGamal_Decryption_Operation::raw_decrypt(const uint8_t msg[], size_t msg_len)
155  {
156  const BigInt& p = m_mod_p.get_modulus();
157 
158  const size_t p_bytes = p.bytes();
159 
160  if(msg_len != 2 * p_bytes)
161  throw Invalid_Argument("ElGamal decryption: Invalid message");
162 
163  BigInt a(msg, p_bytes);
164  BigInt b(msg + p_bytes, p_bytes);
165 
166  if(a >= p || b >= p)
167  throw Invalid_Argument("ElGamal decryption: Invalid message");
168 
169  a = m_blinder.blind(a);
170 
171  BigInt r = m_mod_p.multiply(b, inverse_mod(m_powermod_x_p(a), p));
172 
173  return BigInt::encode_1363(m_blinder.unblind(r), p_bytes);
174  }
175 
176 }
177 
178 std::unique_ptr<PK_Ops::Encryption>
180  const std::string& params,
181  const std::string& provider) const
182  {
183  if(provider == "base" || provider.empty())
184  return std::unique_ptr<PK_Ops::Encryption>(new ElGamal_Encryption_Operation(*this, params));
185  throw Provider_Not_Found(algo_name(), provider);
186  }
187 
188 std::unique_ptr<PK_Ops::Decryption>
190  const std::string& params,
191  const std::string& provider) const
192  {
193  if(provider == "base" || provider.empty())
194  return std::unique_ptr<PK_Ops::Decryption>(new ElGamal_Decryption_Operation(*this, params, rng));
195  throw Provider_Not_Found(algo_name(), provider);
196  }
197 
198 }
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition: numthry.cpp:374
size_t bits() const
Definition: bigint.cpp:183
ElGamal_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: elgamal.cpp:43
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: elgamal.cpp:53
const BigInt & get_y() const
Definition: dl_algo.h:37
void binary_encode(uint8_t buf[]) const
Definition: bigint.cpp:269
bool encryption_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, const std::string &padding)
Definition: keypair.cpp:19
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition: numthry.cpp:277
std::unique_ptr< PK_Ops::Encryption > create_encryption_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: elgamal.cpp:179
std::unique_ptr< PK_Ops::Decryption > create_decryption_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: elgamal.cpp:189
Definition: alg_id.cpp:13
size_t bytes() const
Definition: bigint.cpp:175
const BigInt & group_p() const
Definition: dl_algo.h:43
Blinder m_blinder
Definition: rsa.cpp:239
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: dl_algo.cpp:90
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:82
size_t dl_exponent_size(size_t bits)
Definition: workfactor.cpp:40
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
const BigInt & get_x() const
Definition: dl_algo.h:105
const BigInt & group_g() const
Definition: dl_algo.h:55
std::string algo_name() const override
Definition: elgamal.h:21
Modular_Reducer m_mod_p
Definition: rsa.cpp:238