• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 13579810322

28 Feb 2025 02:06AM UTC coverage: 91.693% (-0.005%) from 91.698%
13579810322

Pull #4724

github

web-flow
Merge 068727df0 into 0e7c06384
Pull Request #4724: Cleanups and deprecations for key agreement

95849 of 104533 relevant lines covered (91.69%)

11440327.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.72
/src/lib/pubkey/elgamal/elgamal.cpp
1
/*
2
* ElGamal
3
* (C) 1999-2007,2018,2019,2023 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/elgamal.h>
9

10
#include <botan/internal/blinding.h>
11
#include <botan/internal/dl_scheme.h>
12
#include <botan/internal/keypair.h>
13
#include <botan/internal/monty_exp.h>
14
#include <botan/internal/pk_ops_impl.h>
15

16
namespace Botan {
17

18
ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& group, const BigInt& y) {
3✔
19
   m_public_key = std::make_shared<DL_PublicKey>(group, y);
3✔
20
}
3✔
21

22
ElGamal_PublicKey::ElGamal_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
4✔
23
   m_public_key = std::make_shared<DL_PublicKey>(alg_id, key_bits, DL_Group_Format::ANSI_X9_42);
4✔
24
}
4✔
25

26
size_t ElGamal_PublicKey::estimated_strength() const {
8✔
27
   return m_public_key->estimated_strength();
8✔
28
}
29

30
size_t ElGamal_PublicKey::key_length() const {
×
31
   return m_public_key->p_bits();
×
32
}
33

34
AlgorithmIdentifier ElGamal_PublicKey::algorithm_identifier() const {
44✔
35
   return AlgorithmIdentifier(object_identifier(), m_public_key->group().DER_encode(DL_Group_Format::ANSI_X9_42));
88✔
36
}
37

38
std::vector<uint8_t> ElGamal_PublicKey::raw_public_key_bits() const {
1✔
39
   return m_public_key->public_key_as_bytes();
1✔
40
}
41

42
std::vector<uint8_t> ElGamal_PublicKey::public_key_bits() const {
19✔
43
   return m_public_key->DER_encode();
19✔
44
}
45

46
const BigInt& ElGamal_PublicKey::get_int_field(std::string_view field) const {
6✔
47
   return m_public_key->get_int_field(algo_name(), field);
6✔
48
}
49

50
std::unique_ptr<Private_Key> ElGamal_PublicKey::generate_another(RandomNumberGenerator& rng) const {
1✔
51
   return std::make_unique<ElGamal_PrivateKey>(rng, m_public_key->group());
2✔
52
}
53

54
bool ElGamal_PublicKey::check_key(RandomNumberGenerator& rng, bool strong) const {
5✔
55
   return m_public_key->check_key(rng, strong);
5✔
56
}
57

58
ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group) {
12✔
59
   m_private_key = std::make_shared<DL_PrivateKey>(group, rng);
12✔
60
   m_public_key = m_private_key->public_key();
12✔
61
}
12✔
62

63
ElGamal_PrivateKey::ElGamal_PrivateKey(const DL_Group& group, const BigInt& x) {
25✔
64
   m_private_key = std::make_shared<DL_PrivateKey>(group, x);
25✔
65
   m_public_key = m_private_key->public_key();
25✔
66
}
25✔
67

68
ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
14✔
69
   m_private_key = std::make_shared<DL_PrivateKey>(alg_id, key_bits, DL_Group_Format::ANSI_X9_42);
14✔
70
   m_public_key = m_private_key->public_key();
14✔
71
}
14✔
72

73
std::unique_ptr<Public_Key> ElGamal_PrivateKey::public_key() const {
17✔
74
   return std::unique_ptr<Public_Key>(new ElGamal_PublicKey(m_public_key));
17✔
75
}
76

77
const BigInt& ElGamal_PrivateKey::get_int_field(std::string_view field) const {
2✔
78
   return m_private_key->get_int_field(algo_name(), field);
2✔
79
}
80

81
secure_vector<uint8_t> ElGamal_PrivateKey::private_key_bits() const {
33✔
82
   return m_private_key->DER_encode();
33✔
83
}
84

85
secure_vector<uint8_t> ElGamal_PrivateKey::raw_private_key_bits() const {
×
86
   return m_private_key->raw_private_key_bits();
×
87
}
88

89
bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const {
3✔
90
   if(!m_private_key->check_key(rng, strong)) {
3✔
91
      return false;
92
   }
93

94
#if defined(BOTAN_HAS_OAEP) && defined(BOTAN_HAS_SHA_256)
95
   const std::string padding = "OAEP(SHA-256)";
3✔
96
#else
97
   const std::string padding = "Raw";
98
#endif
99

100
   return KeyPair::encryption_consistency_check(rng, *this, padding);
3✔
101
}
3✔
102

103
namespace {
104

105
/**
106
* ElGamal encryption operation
107
*/
108
class ElGamal_Encryption_Operation final : public PK_Ops::Encryption_with_EME {
×
109
   public:
110
      ElGamal_Encryption_Operation(const std::shared_ptr<const DL_PublicKey>& key, std::string_view eme) :
15✔
111
            PK_Ops::Encryption_with_EME(eme), m_key(key) {
15✔
112
         const size_t powm_window = 4;
15✔
113
         m_monty_y_p = monty_precompute(m_key->group().monty_params_p(), m_key->public_key(), powm_window);
15✔
114
      }
15✔
115

116
      size_t ciphertext_length(size_t /*ptext_len*/) const override { return 2 * m_key->group().p_bytes(); }
8✔
117

118
      size_t max_ptext_input_bits() const override { return m_key->group().p_bits() - 1; }
31✔
119

120
      std::vector<uint8_t> raw_encrypt(std::span<const uint8_t> ptext, RandomNumberGenerator& rng) override;
121

122
   private:
123
      std::shared_ptr<const DL_PublicKey> m_key;
124
      std::shared_ptr<const Montgomery_Exponentation_State> m_monty_y_p;
125
};
126

127
std::vector<uint8_t> ElGamal_Encryption_Operation::raw_encrypt(std::span<const uint8_t> ptext,
15✔
128
                                                               RandomNumberGenerator& rng) {
129
   BigInt m(ptext);
15✔
130

131
   const auto& group = m_key->group();
15✔
132

133
   if(m >= group.get_p()) {
15✔
134
      throw Invalid_Argument("ElGamal encryption: Input is too large");
×
135
   }
136

137
   /*
138
   Some weird PGP implementations generate keys using bad parameters
139
   which result in easily breakable encryption if short exponents are
140
   used during encryption. To avoid this problem, always use full size
141
   exponents.
142

143
   See https://eprint.iacr.org/2021/923
144
   */
145
   const size_t k_bits = group.p_bits() - 1;
15✔
146
   const BigInt k(rng, k_bits, false);
15✔
147

148
   const BigInt a = group.power_g_p(k, k_bits);
15✔
149
   const BigInt b = group.multiply_mod_p(m, monty_execute(*m_monty_y_p, k, k_bits).value());
15✔
150

151
   return unlock(BigInt::encode_fixed_length_int_pair(a, b, group.p_bytes()));
45✔
152
}
15✔
153

154
/**
155
* ElGamal decryption operation
156
*/
157
class ElGamal_Decryption_Operation final : public PK_Ops::Decryption_with_EME {
×
158
   public:
159
      ElGamal_Decryption_Operation(const std::shared_ptr<const DL_PrivateKey>& key,
32✔
160
                                   std::string_view eme,
161
                                   RandomNumberGenerator& rng) :
32✔
162
            PK_Ops::Decryption_with_EME(eme),
163
            m_key(key),
64✔
164
            m_blinder(
64✔
165
               m_key->group()._reducer_mod_p(),
32✔
166
               rng,
167
               [](const BigInt& k) { return k; },
32✔
168
               [this](const BigInt& k) { return powermod_x_p(k); }) {}
64✔
169

170
      size_t plaintext_length(size_t /*ctext_len*/) const override { return m_key->group().p_bytes(); }
8✔
171

172
      secure_vector<uint8_t> raw_decrypt(std::span<const uint8_t> ctext) override;
173

174
   private:
175
      BigInt powermod_x_p(const BigInt& v) const { return m_key->group().power_b_p(v, m_key->private_key()); }
32✔
176

177
      std::shared_ptr<const DL_PrivateKey> m_key;
178
      Blinder m_blinder;
179
};
180

181
secure_vector<uint8_t> ElGamal_Decryption_Operation::raw_decrypt(std::span<const uint8_t> ctext) {
492✔
182
   const auto& group = m_key->group();
492✔
183

184
   const size_t p_bytes = group.p_bytes();
492✔
185

186
   if(ctext.size() != 2 * p_bytes) {
492✔
187
      throw Invalid_Argument("ElGamal decryption: Invalid message");
×
188
   }
189

190
   BigInt a(ctext.first(p_bytes));
492✔
191
   const BigInt b(ctext.last(p_bytes));
492✔
192

193
   if(a >= group.get_p() || b >= group.get_p()) {
492✔
194
      throw Invalid_Argument("ElGamal decryption: Invalid message");
×
195
   }
196

197
   a = m_blinder.blind(a);
492✔
198

199
   const BigInt r = group.multiply_mod_p(group.inverse_mod_p(powermod_x_p(a)), b);
492✔
200

201
   return m_blinder.unblind(r).serialize<secure_vector<uint8_t>>(p_bytes);
984✔
202
}
492✔
203

204
}  // namespace
205

206
std::unique_ptr<PK_Ops::Encryption> ElGamal_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/,
33✔
207
                                                                            std::string_view params,
208
                                                                            std::string_view provider) const {
209
   if(provider == "base" || provider.empty()) {
39✔
210
      return std::make_unique<ElGamal_Encryption_Operation>(this->m_public_key, params);
15✔
211
   }
212
   throw Provider_Not_Found(algo_name(), provider);
36✔
213
}
214

215
std::unique_ptr<PK_Ops::Decryption> ElGamal_PrivateKey::create_decryption_op(RandomNumberGenerator& rng,
101✔
216
                                                                             std::string_view params,
217
                                                                             std::string_view provider) const {
218
   if(provider == "base" || provider.empty()) {
124✔
219
      return std::make_unique<ElGamal_Decryption_Operation>(this->m_private_key, params, rng);
32✔
220
   }
221
   throw Provider_Not_Found(algo_name(), provider);
138✔
222
}
223

224
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc