Botan  2.8.0
Crypto and TLS for C++11
elgamal.cpp
Go to the documentation of this file.
1 /*
2 * ElGamal
3 * (C) 1999-2007,2018 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/pow_mod.h>
14 
15 namespace Botan {
16 
17 /*
18 * ElGamal_PublicKey Constructor
19 */
21  DL_Scheme_PublicKey(group, y)
22  {
23  }
24 
25 /*
26 * ElGamal_PrivateKey Constructor
27 */
29  const DL_Group& group,
30  const BigInt& x)
31  {
32  m_x = x;
33  m_group = group;
34 
35  if(m_x.is_zero())
36  {
37  const size_t exp_bits = m_group.exponent_bits();
38  m_x.randomize(rng, exp_bits);
39  m_y = m_group.power_g_p(m_x, exp_bits);
40  }
41  else
42  {
44  }
45  }
46 
48  const secure_vector<uint8_t>& key_bits) :
49  DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
50  {
52  }
53 
54 /*
55 * Check Private ElGamal Parameters
56 */
58  bool strong) const
59  {
60  if(!DL_Scheme_PrivateKey::check_key(rng, strong))
61  return false;
62 
63  if(!strong)
64  return true;
65 
66  return KeyPair::encryption_consistency_check(rng, *this, "EME1(SHA-256)");
67  }
68 
69 namespace {
70 
71 /**
72 * ElGamal encryption operation
73 */
74 class ElGamal_Encryption_Operation final : public PK_Ops::Encryption_with_EME
75  {
76  public:
77 
78  size_t ciphertext_length(size_t) const override { return 2*m_group.p_bytes(); }
79 
80  size_t max_raw_input_bits() const override { return m_group.p_bits() - 1; }
81 
82  ElGamal_Encryption_Operation(const ElGamal_PublicKey& key, const std::string& eme);
83 
84  secure_vector<uint8_t> raw_encrypt(const uint8_t msg[], size_t msg_len,
85  RandomNumberGenerator& rng) override;
86 
87  private:
88  const DL_Group m_group;
89  Fixed_Base_Power_Mod m_powermod_y_p;
90  };
91 
92 ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key,
93  const std::string& eme) :
94  PK_Ops::Encryption_with_EME(eme),
95  m_group(key.get_group()),
96  m_powermod_y_p(key.get_y(), m_group.get_p())
97  {
98  }
99 
100 secure_vector<uint8_t>
101 ElGamal_Encryption_Operation::raw_encrypt(const uint8_t msg[], size_t msg_len,
102  RandomNumberGenerator& rng)
103  {
104  BigInt m(msg, msg_len);
105 
106  if(m >= m_group.get_p())
107  throw Invalid_Argument("ElGamal encryption: Input is too large");
108 
109  const size_t k_bits = m_group.exponent_bits();
110  const BigInt k(rng, k_bits);
111 
112  const BigInt a = m_group.power_g_p(k, k_bits);
113  const BigInt b = m_group.multiply_mod_p(m, m_powermod_y_p(k));
114 
115  return BigInt::encode_fixed_length_int_pair(a, b, m_group.p_bytes());
116  }
117 
118 /**
119 * ElGamal decryption operation
120 */
121 class ElGamal_Decryption_Operation final : public PK_Ops::Decryption_with_EME
122  {
123  public:
124 
125  ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key,
126  const std::string& eme,
127  RandomNumberGenerator& rng);
128 
129  size_t plaintext_length(size_t) const override { return m_group.p_bytes(); }
130 
131  secure_vector<uint8_t> raw_decrypt(const uint8_t msg[], size_t msg_len) override;
132  private:
133  const DL_Group m_group;
134  Fixed_Exponent_Power_Mod m_powermod_x_p;
135  Blinder m_blinder;
136  };
137 
138 ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key,
139  const std::string& eme,
140  RandomNumberGenerator& rng) :
141  PK_Ops::Decryption_with_EME(eme),
142  m_group(key.get_group()),
143  m_powermod_x_p(key.get_x(), m_group.get_p()),
144  m_blinder(m_group.get_p(),
145  rng,
146  [](const BigInt& k) { return k; },
147  [this](const BigInt& k) { return m_powermod_x_p(k); })
148  {
149  }
150 
151 secure_vector<uint8_t>
152 ElGamal_Decryption_Operation::raw_decrypt(const uint8_t msg[], size_t msg_len)
153  {
154  const size_t p_bytes = m_group.p_bytes();
155 
156  if(msg_len != 2 * p_bytes)
157  throw Invalid_Argument("ElGamal decryption: Invalid message");
158 
159  BigInt a(msg, p_bytes);
160  const BigInt b(msg + p_bytes, p_bytes);
161 
162  if(a >= m_group.get_p() || b >= m_group.get_p())
163  throw Invalid_Argument("ElGamal decryption: Invalid message");
164 
165  a = m_blinder.blind(a);
166 
167  const BigInt r = m_group.multiply_mod_p(m_group.inverse_mod_p(m_powermod_x_p(a)), b);
168 
169  return BigInt::encode_1363(m_blinder.unblind(r), p_bytes);
170  }
171 
172 }
173 
174 std::unique_ptr<PK_Ops::Encryption>
176  const std::string& params,
177  const std::string& provider) const
178  {
179  if(provider == "base" || provider.empty())
180  return std::unique_ptr<PK_Ops::Encryption>(new ElGamal_Encryption_Operation(*this, params));
181  throw Provider_Not_Found(algo_name(), provider);
182  }
183 
184 std::unique_ptr<PK_Ops::Decryption>
186  const std::string& params,
187  const std::string& provider) const
188  {
189  if(provider == "base" || provider.empty())
190  return std::unique_ptr<PK_Ops::Decryption>(new ElGamal_Decryption_Operation(*this, params, rng));
191  throw Provider_Not_Found(algo_name(), provider);
192  }
193 
194 }
size_t p_bytes() const
Definition: dl_group.cpp:441
BigInt multiply_mod_p(const BigInt &x, const BigInt &y) const
Definition: dl_group.cpp:479
ElGamal_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: elgamal.cpp:47
void randomize(RandomNumberGenerator &rng, size_t bitsize, bool set_high_bit=true)
Definition: big_rand.cpp:17
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: elgamal.cpp:57
BigInt power_g_p(const BigInt &x) const
Definition: dl_group.cpp:520
int(* final)(unsigned char *, CTX *)
bool is_zero() const
Definition: bigint.h:362
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 unblind(const BigInt &x) const
Definition: blinding.cpp:58
const BigInt & get_p() const
Definition: dl_group.cpp:410
size_t exponent_bits() const
Definition: dl_group.cpp:463
std::unique_ptr< PK_Ops::Encryption > create_encryption_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: elgamal.cpp:175
std::unique_ptr< PK_Ops::Decryption > create_decryption_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: elgamal.cpp:185
Definition: alg_id.cpp:13
size_t p_bits() const
Definition: dl_group.cpp:436
BigInt blind(const BigInt &x) const
Definition: blinding.cpp:35
Blinder m_blinder
Definition: rsa.cpp:286
BigInt inverse_mod_p(const BigInt &x) const
Definition: dl_group.cpp:468
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: dl_algo.cpp:78
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:124
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:145
std::string algo_name() const override
Definition: elgamal.h:21