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

randombit / botan / 28994301380

09 Jul 2026 12:46AM UTC coverage: 89.396% (+1.7%) from 87.739%
28994301380

push

github

web-flow
Merge pull request #5712 from randombit/jack/cdp-aia-extn

Improve CDP, AIA and IDP extension decoding and handling

113303 of 126743 relevant lines covered (89.4%)

10806632.55 hits per line

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

95.08
/src/tests/test_ecies.cpp
1
/*
2
* (C) 2016 Philipp Weber
3
* (C) 2016 Daniel Neus
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "tests.h"
9

10
#if defined(BOTAN_HAS_ECIES)
11
   #include <botan/ecdh.h>
12
   #include <botan/ecies.h>
13
   #include <botan/hex.h>
14
   #include <botan/rng.h>
15
#endif
16

17
namespace Botan_Tests {
18

19
namespace {
20

21
#if defined(BOTAN_HAS_ECIES) && defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_MODE_CBC)
22

23
using Flags = Botan::ECIES_Flags;
24

25
Botan::EC_Point_Format get_compression_type(const std::string& format) {
13✔
26
   if(format == "uncompressed") {
13✔
27
      return Botan::EC_Point_Format::Uncompressed;
28
   } else if(format == "compressed") {
6✔
29
      return Botan::EC_Point_Format::Compressed;
30
   } else if(format == "hybrid") {
×
31
      return Botan::EC_Point_Format::Hybrid;
32
   }
33
   throw Botan::Invalid_Argument("invalid compression format");
×
34
}
35

36
Flags ecies_flags(bool cofactor_mode, bool old_cofactor_mode, bool check_mode, bool single_hash_mode) {
107✔
37
   return (cofactor_mode ? Flags::CofactorMode : Flags::None) |
107✔
38
          (single_hash_mode ? Flags::SingleHashMode : Flags::None) |
39
          (old_cofactor_mode ? Flags::OldCofactorMode : Flags::None) | (check_mode ? Flags::CheckMode : Flags::None);
214✔
40
}
41

42
void check_encrypt_decrypt(Test::Result& result,
60✔
43
                           const Botan::ECDH_PrivateKey& private_key,
44
                           const Botan::ECDH_PrivateKey& other_private_key,
45
                           const Botan::ECIES_System_Params& ecies_params,
46
                           const Botan::InitializationVector& iv,
47
                           const std::string& label,
48
                           const std::vector<uint8_t>& plaintext,
49
                           const std::vector<uint8_t>& ciphertext,
50
                           Botan::RandomNumberGenerator& rng) {
51
   try {
60✔
52
      Botan::ECIES_Encryptor ecies_enc(private_key, ecies_params, rng);
60✔
53
      ecies_enc.set_other_key(
120✔
54
         Botan::EC_AffinePoint(other_private_key.domain(), other_private_key.raw_public_key_bits()));
120✔
55
      Botan::ECIES_Decryptor ecies_dec(other_private_key, ecies_params, rng);
60✔
56
      if(!iv.bits_of().empty()) {
118✔
57
         ecies_enc.set_initialization_vector(iv);
58✔
58
         ecies_dec.set_initialization_vector(iv);
58✔
59
      }
60
      if(!label.empty()) {
60✔
61
         ecies_enc.set_label(label);
10✔
62
         ecies_dec.set_label(label);
10✔
63
      }
64

65
      const auto ct_len_bound_enc = static_cast<Botan::PK_Encryptor&>(ecies_enc).ciphertext_length(plaintext.size());
60✔
66
      const auto ct_len_bound_dec = static_cast<Botan::PK_Decryptor&>(ecies_dec).ciphertext_length(plaintext.size());
60✔
67
      result.test_sz_eq("ciphertext length bounds match", ct_len_bound_enc, ct_len_bound_dec);
60✔
68

69
      const std::vector<uint8_t> encrypted = ecies_enc.encrypt(plaintext, rng);
60✔
70
      if(!ciphertext.empty()) {
60✔
71
         result.test_bin_eq("encrypted data", encrypted, ciphertext);
12✔
72
      }
73
      result.test_sz_lte("ciphertext length within bounds",
60✔
74
                         encrypted.size(),
75
                         static_cast<Botan::PK_Decryptor&>(ecies_dec).ciphertext_length(plaintext.size()));
60✔
76
      const Botan::secure_vector<uint8_t> decrypted = ecies_dec.decrypt(encrypted);
60✔
77
      result.test_bin_eq("decrypted data equals plaintext", decrypted, plaintext);
60✔
78

79
      const auto pt_len_bound_dec = static_cast<Botan::PK_Decryptor&>(ecies_dec).plaintext_length(encrypted.size());
60✔
80
      result.test_sz_lte("plaintext length bounds match", plaintext.size(), pt_len_bound_dec);
60✔
81

82
      std::vector<uint8_t> invalid_encrypted = encrypted;
60✔
83
      uint8_t& last_byte = invalid_encrypted[invalid_encrypted.size() - 1];
60✔
84
      last_byte = ~last_byte;
60✔
85
      result.test_throws("throw on invalid ciphertext",
60✔
86
                         [&ecies_dec, &invalid_encrypted] { ecies_dec.decrypt(invalid_encrypted); });
120✔
87
   } catch(Botan::Lookup_Error& e) {
180✔
88
      result.test_note("Not available", e.what());
×
89
   }
×
90
}
60✔
91

92
[[maybe_unused]] void check_encrypt_decrypt(Test::Result& result,
48✔
93
                                            const Botan::ECDH_PrivateKey& private_key,
94
                                            const Botan::ECDH_PrivateKey& other_private_key,
95
                                            const Botan::ECIES_System_Params& ecies_params,
96
                                            size_t iv_length,
97
                                            Botan::RandomNumberGenerator& rng) {
98
   const std::vector<uint8_t> plaintext{1, 2, 3};
48✔
99
   check_encrypt_decrypt(result,
96✔
100
                         private_key,
101
                         other_private_key,
102
                         ecies_params,
103
                         Botan::InitializationVector(std::vector<uint8_t>(iv_length, 0)),
144✔
104
                         "",
105
                         plaintext,
106
                         std::vector<uint8_t>(),
48✔
107
                         rng);
108
}
48✔
109

110
   #if defined(BOTAN_HAS_KDF1_18033) && defined(BOTAN_HAS_SHA1)
111

112
class ECIES_ISO_Tests final : public Text_Based_Test {
×
113
   public:
114
      ECIES_ISO_Tests() : Text_Based_Test("pubkey/ecies-18033.vec", "format,p,a,b,Order,Gx,Gy,Oid,hx,hy,x,r,C0,K") {}
2✔
115

116
      bool clear_between_callbacks() const override { return false; }
2✔
117

118
      bool skip_this_test(const std::string& /*header*/, const VarMap& /*vars*/) override {
2✔
119
         return !Botan::EC_Group::supports_application_specific_group();
2✔
120
      }
121

122
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
2✔
123
         Test::Result result("ECIES-ISO");
2✔
124

125
         // get test vectors defined by ISO 18033
126
         const Botan::EC_Point_Format compression_type = get_compression_type(vars.get_req_str("format"));
2✔
127
         const Botan::BigInt p = vars.get_req_bn("p");
2✔
128
         const Botan::BigInt a = vars.get_req_bn("a");
2✔
129
         const Botan::BigInt b = vars.get_req_bn("b");
2✔
130
         const Botan::BigInt order = vars.get_req_bn("Order");  // order
2✔
131
         const Botan::BigInt gx = vars.get_req_bn("Gx");        // base point x
2✔
132
         const Botan::BigInt gy = vars.get_req_bn("Gy");        // base point y
2✔
133
         const Botan::OID oid(vars.get_req_str("Oid"));
2✔
134
         const Botan::BigInt hx = vars.get_req_bn("hx");          // x of public point of bob
2✔
135
         const Botan::BigInt hy = vars.get_req_bn("hy");          // y of public point of bob
2✔
136
         const Botan::BigInt x = vars.get_req_bn("x");            // private key of bob
2✔
137
         const Botan::BigInt r = vars.get_req_bn("r");            // (ephemeral) private key of alice
2✔
138
         const std::vector<uint8_t> c0 = vars.get_req_bin("C0");  // expected encoded (ephemeral) public key
2✔
139
         const std::vector<uint8_t> k = vars.get_req_bin("K");    // expected derived secret
2✔
140

141
         const Botan::EC_Group domain(oid, p, a, b, gx, gy, order);
2✔
142

143
         // keys of bob
144
         const Botan::ECDH_PrivateKey other_private_key(this->rng(), domain, x);
2✔
145
         const auto other_public_key_point = Botan::EC_AffinePoint::from_bigint_xy(domain, hx, hy).value();
4✔
146
         const Botan::ECDH_PublicKey other_public_key(domain, other_public_key_point);
2✔
147

148
         // (ephemeral) keys of alice
149
         const Botan::ECDH_PrivateKey eph_private_key(this->rng(), domain, r);
2✔
150
         const auto eph_public_key_bin = eph_private_key.public_value(compression_type);
2✔
151
         result.test_bin_eq("encoded (ephemeral) public key", eph_public_key_bin, c0);
2✔
152

153
         // test secret derivation: ISO 18033 test vectors use KDF1 from ISO 18033
154
         // no cofactor-/oldcofactor-/singlehash-/check-mode and 128 byte secret length
155
         const Botan::ECIES_KA_Params ka_params(
2✔
156
            eph_private_key.domain(), "KDF1-18033(SHA-1)", 128, compression_type, Flags::None);
2✔
157
         const Botan::ECIES_KA_Operation ka(eph_private_key, ka_params, true, this->rng());
2✔
158
         const Botan::SymmetricKey secret_key = ka.derive_secret(eph_public_key_bin, other_public_key_point);
2✔
159
         result.test_bin_eq("derived secret key", secret_key.bits_of(), k);
2✔
160

161
         // test encryption / decryption
162

163
         // TODO(Botan4) clean this up after removing cofactor support
164

165
         for(auto comp_type : {Botan::EC_Point_Format::Uncompressed,
6✔
166
                               Botan::EC_Point_Format::Compressed,
167
                               Botan::EC_Point_Format::Hybrid}) {
8✔
168
            for(const bool cofactor_mode : {true, false}) {
18✔
169
               for(const bool single_hash_mode : {true, false}) {
36✔
170
                  for(const bool old_cofactor_mode : {true, false}) {
72✔
171
                     for(const bool check_mode : {true, false}) {
144✔
172
                        Flags flags = ecies_flags(cofactor_mode, old_cofactor_mode, check_mode, single_hash_mode);
96✔
173

174
                        if(size_t(cofactor_mode) + size_t(check_mode) + size_t(old_cofactor_mode) > 1) {
96✔
175
                           auto onThrow = [&]() {
96✔
176
                              Botan::ECIES_System_Params(eph_private_key.domain(),
48✔
177
                                                         "KDF2(SHA-1)",
178
                                                         "AES-256/CBC",
179
                                                         32,
180
                                                         "HMAC(SHA-1)",
181
                                                         20,
182
                                                         comp_type,
183
                                                         flags);
184
                           };
48✔
185
                           result.test_throws("throw on invalid ECIES_Flags", onThrow);
48✔
186
                           continue;
48✔
187
                        }
48✔
188

189
                        const Botan::ECIES_System_Params ecies_params(eph_private_key.domain(),
48✔
190
                                                                      "KDF2(SHA-1)",
191
                                                                      "AES-256/CBC",
192
                                                                      32,
193
                                                                      "HMAC(SHA-1)",
194
                                                                      20,
195
                                                                      comp_type,
196
                                                                      flags);
48✔
197
                        check_encrypt_decrypt(
48✔
198
                           result, eph_private_key, other_private_key, ecies_params, 16, this->rng());
199
                     }
48✔
200
                  }
201
               }
202
            }
203
         }
204

205
         return result;
4✔
206
      }
10✔
207
};
208

209
BOTAN_REGISTER_TEST("pubkey", "ecies_iso", ECIES_ISO_Tests);
210

211
   #endif
212

213
class ECIES_Tests final : public Text_Based_Test {
214
   public:
215
      ECIES_Tests() :
1✔
216
            Text_Based_Test("pubkey/ecies.vec",
217
                            "Curve,PrivateKey,OtherPrivateKey,Kdf,Dem,DemKeyLen,Mac,MacKeyLen,Format,"
218
                            "CofactorMode,OldCofactorMode,CheckMode,SingleHashMode,Label,Plaintext,Ciphertext",
219
                            "Iv") {
2✔
220
         // In order to test cofactor handling flags some of the tests use secp112r2 which has a cofactor of 4
221
         // TODO(Botan4) kill it with fire
222
         if(Botan::EC_Group::supports_application_specific_group_with_cofactor()) {
1✔
223
            auto p = Botan::BigInt::from_string("0xDB7C2ABF62E35E668076BEAD208B");
1✔
224
            auto a = Botan::BigInt::from_string("0x6127C24C05F38A0AAAF65C0EF02C");
1✔
225
            auto b = Botan::BigInt::from_string("0x51DEF1815DB5ED74FCC34C85D709");
1✔
226

227
            auto g_x = Botan::BigInt::from_string("0x4BA30AB5E892B4E1649DD0928643");
1✔
228
            auto g_y = Botan::BigInt::from_string("0xADCD46F5882E3747DEF36E956E97");
1✔
229
            auto order = Botan::BigInt::from_string("0x36DF0AAFD8B8D7597CA10520D04B");
1✔
230
            auto cofactor = Botan::BigInt::from_u64(4);
1✔
231
            m_secp112r2 = std::make_unique<Botan::EC_Group>(p, a, b, g_x, g_y, order, cofactor);
1✔
232
         }
1✔
233
      }
1✔
234

235
      bool skip_this_test(const std::string& /*header*/, const VarMap& vars) override {
12✔
236
         const auto curve = vars.get_req_str("Curve");
12✔
237

238
         // TODO(Botan4) remove this since cofactors no longer supported
239
         if(curve == "secp112r2") {
12✔
240
            return !Botan::EC_Group::supports_application_specific_group_with_cofactor();
4✔
241
         } else {
242
            return !Botan::EC_Group::supports_named_group(curve);
8✔
243
         }
244
      }
12✔
245

246
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
11✔
247
         Test::Result result("ECIES");
11✔
248

249
         const std::string curve = vars.get_req_str("Curve");
11✔
250
         const Botan::BigInt private_key_value = vars.get_req_bn("PrivateKey");
11✔
251
         const Botan::BigInt other_private_key_value = vars.get_req_bn("OtherPrivateKey");
11✔
252
         const std::string kdf = vars.get_req_str("Kdf");
11✔
253
         const std::string dem = vars.get_req_str("Dem");
11✔
254
         const size_t dem_key_len = vars.get_req_sz("DemKeyLen");
11✔
255
         const Botan::InitializationVector iv = Botan::InitializationVector(vars.get_opt_bin("Iv"));
11✔
256
         const std::string mac = vars.get_req_str("Mac");
11✔
257
         const size_t mac_key_len = vars.get_req_sz("MacKeyLen");
11✔
258
         const Botan::EC_Point_Format compression_type = get_compression_type(vars.get_req_str("Format"));
11✔
259
         const bool cofactor_mode = vars.get_req_sz("CofactorMode") != 0;
11✔
260
         const bool old_cofactor_mode = vars.get_req_sz("OldCofactorMode") != 0;
11✔
261
         const bool check_mode = vars.get_req_sz("CheckMode") != 0;
11✔
262
         const bool single_hash_mode = vars.get_req_sz("SingleHashMode") != 0;
11✔
263
         const std::string label = vars.get_req_str("Label");
11✔
264
         const std::vector<uint8_t> plaintext = vars.get_req_bin("Plaintext");
11✔
265
         const std::vector<uint8_t> ciphertext = vars.get_req_bin("Ciphertext");
11✔
266

267
         const Flags flags = ecies_flags(cofactor_mode, old_cofactor_mode, check_mode, single_hash_mode);
11✔
268

269
         const auto group = [&]() {
×
270
            if(curve == "secp112r2") {
11✔
271
               return *m_secp112r2;
4✔
272
            } else {
273
               return Botan::EC_Group::from_name(curve);
7✔
274
            }
275
         }();
11✔
276

277
         const Botan::ECDH_PrivateKey private_key(this->rng(), group, private_key_value);
11✔
278
         const Botan::ECDH_PrivateKey other_private_key(this->rng(), group, other_private_key_value);
11✔
279

280
         const Botan::ECIES_System_Params ecies_params(
11✔
281
            private_key.domain(), kdf, dem, dem_key_len, mac, mac_key_len, compression_type, flags);
11✔
282
         check_encrypt_decrypt(
11✔
283
            result, private_key, other_private_key, ecies_params, iv, label, plaintext, ciphertext, this->rng());
284

285
         return result;
22✔
286
      }
42✔
287

288
   private:
289
      std::unique_ptr<Botan::EC_Group> m_secp112r2;
290
};
291

292
BOTAN_REGISTER_TEST("pubkey", "ecies", ECIES_Tests);
293

294
   #if defined(BOTAN_HAS_KDF1_18033) && defined(BOTAN_HAS_HMAC) && defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_SHA2_64)
295

296
Test::Result test_other_key_not_set() {
1✔
297
   Test::Result result("ECIES other key not set");
1✔
298

299
   auto rng = Test::new_rng("ecies_other_key_not_set");
1✔
300

301
   const Flags flags = ecies_flags(false, false, false, true);
1✔
302
   const auto domain = Botan::EC_Group::from_name("secp521r1");
1✔
303

304
   const Botan::BigInt private_key_value(
1✔
305
      "405029866705438137604064977397053031159826489755682166267763407"
306
      "5002761777100287880684822948852132235484464537021197213998300006"
307
      "547176718172344447619746779823");
1✔
308

309
   const Botan::ECDH_PrivateKey private_key(*rng, domain, private_key_value);
1✔
310
   const Botan::ECIES_System_Params ecies_params(private_key.domain(),
1✔
311
                                                 "KDF1-18033(SHA-512)",
312
                                                 "AES-256/CBC",
313
                                                 32,
314
                                                 "HMAC(SHA-512)",
315
                                                 20,
316
                                                 Botan::EC_Point_Format::Compressed,
317
                                                 flags);
1✔
318

319
   Botan::ECIES_Encryptor ecies_enc(private_key, ecies_params, *rng);
1✔
320

321
   result.test_throws("encrypt not possible without setting other public key",
1✔
322
                      [&ecies_enc, &rng]() { ecies_enc.encrypt(std::vector<uint8_t>(8), *rng); });
2✔
323

324
   return result;
2✔
325
}
2✔
326

327
Test::Result test_kdf_not_found() {
1✔
328
   Test::Result result("ECIES kdf not found");
1✔
329

330
   auto rng = Test::new_rng("ecies_kdf_not_found");
1✔
331

332
   const Flags flags = ecies_flags(false, false, false, true);
1✔
333
   const auto domain = Botan::EC_Group::from_name("secp521r1");
1✔
334

335
   const Botan::BigInt private_key_value(
1✔
336
      "405029866705438137604064977397053031159826489755682166267763407"
337
      "5002761777100287880684822948852132235484464537021197213998300006"
338
      "547176718172344447619746779823");
1✔
339

340
   const Botan::ECDH_PrivateKey private_key(*rng, domain, private_key_value);
1✔
341
   const Botan::ECIES_System_Params ecies_params(private_key.domain(),
1✔
342
                                                 "KDF-XYZ(SHA-512)",
343
                                                 "AES-256/CBC",
344
                                                 32,
345
                                                 "HMAC(SHA-512)",
346
                                                 20,
347
                                                 Botan::EC_Point_Format::Compressed,
348
                                                 flags);
1✔
349

350
   result.test_throws("kdf not found", [&]() {
1✔
351
      const Botan::ECIES_Encryptor ecies_enc(private_key, ecies_params, *rng);
1✔
352
      ecies_enc.encrypt(std::vector<uint8_t>(8), *rng);
2✔
353
   });
1✔
354

355
   return result;
2✔
356
}
2✔
357

358
Test::Result test_mac_not_found() {
1✔
359
   Test::Result result("ECIES mac not found");
1✔
360

361
   auto rng = Test::new_rng("ecies_mac_not_found");
1✔
362

363
   const Flags flags = ecies_flags(false, false, false, true);
1✔
364
   const auto domain = Botan::EC_Group::from_name("secp521r1");
1✔
365

366
   const Botan::BigInt private_key_value(
1✔
367
      "405029866705438137604064977397053031159826489755682166267763407"
368
      "5002761777100287880684822948852132235484464537021197213998300006"
369
      "547176718172344447619746779823");
1✔
370

371
   const Botan::ECDH_PrivateKey private_key(*rng, domain, private_key_value);
1✔
372
   const Botan::ECIES_System_Params ecies_params(private_key.domain(),
1✔
373
                                                 "KDF1-18033(SHA-512)",
374
                                                 "AES-256/CBC",
375
                                                 32,
376
                                                 "XYZMAC(SHA-512)",
377
                                                 20,
378
                                                 Botan::EC_Point_Format::Compressed,
379
                                                 flags);
1✔
380

381
   result.test_throws("mac not found", [&]() {
1✔
382
      const Botan::ECIES_Encryptor ecies_enc(private_key, ecies_params, *rng);
1✔
383
      ecies_enc.encrypt(std::vector<uint8_t>(8), *rng);
×
384
   });
×
385

386
   return result;
2✔
387
}
2✔
388

389
Test::Result test_cipher_not_found() {
1✔
390
   Test::Result result("ECIES cipher not found");
1✔
391

392
   auto rng = Test::new_rng("ecies_cipher_not_found");
1✔
393

394
   const Flags flags = ecies_flags(false, false, false, true);
1✔
395
   const auto domain = Botan::EC_Group::from_name("secp521r1");
1✔
396

397
   const Botan::BigInt private_key_value(
1✔
398
      "405029866705438137604064977397053031159826489755682166267763407"
399
      "5002761777100287880684822948852132235484464537021197213998300006"
400
      "547176718172344447619746779823");
1✔
401

402
   const Botan::ECDH_PrivateKey private_key(*rng, domain, private_key_value);
1✔
403
   const Botan::ECIES_System_Params ecies_params(private_key.domain(),
1✔
404
                                                 "KDF1-18033(SHA-512)",
405
                                                 "AES-XYZ-256/CBC",
406
                                                 32,
407
                                                 "HMAC(SHA-512)",
408
                                                 20,
409
                                                 Botan::EC_Point_Format::Compressed,
410
                                                 flags);
1✔
411

412
   result.test_throws("cipher not found", [&]() {
1✔
413
      const Botan::ECIES_Encryptor ecies_enc(private_key, ecies_params, *rng);
1✔
414
      ecies_enc.encrypt(std::vector<uint8_t>(8), *rng);
×
415
   });
×
416

417
   return result;
2✔
418
}
2✔
419

420
Test::Result test_system_params_short_ctor() {
1✔
421
   Test::Result result("ECIES short system params ctor");
1✔
422

423
   auto rng = Test::new_rng("ecies_params_short_ctor");
1✔
424

425
   const auto domain = Botan::EC_Group::from_name("secp521r1");
1✔
426
   const Botan::BigInt private_key_value(
1✔
427
      "405029866705438137604064977397053031159826489755682166267763407"
428
      "5002761777100287880684822948852132235484464537021197213998300006"
429
      "547176718172344447619746779823");
1✔
430

431
   const Botan::BigInt other_private_key_value(
1✔
432
      "2294226772740614508941417891614236736606752960073669253551166842"
433
      "5866095315090327914760325168219669828915074071456176066304457448"
434
      "25404691681749451640151380153");
1✔
435

436
   const Botan::ECDH_PrivateKey private_key(*rng, domain, private_key_value);
1✔
437
   const Botan::ECDH_PrivateKey other_private_key(*rng, domain, other_private_key_value);
1✔
438

439
   const Botan::ECIES_System_Params ecies_params(
1✔
440
      private_key.domain(), "KDF1-18033(SHA-512)", "AES-256/CBC", 32, "HMAC(SHA-512)", 16);
1✔
441

442
   const Botan::InitializationVector iv("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
1✔
443
   const std::string label = "Test";
1✔
444

445
   const std::vector<uint8_t> plaintext = Botan::hex_decode("000102030405060708090A0B0C0D0E0F");
1✔
446

447
   // generated with botan
448
   const std::vector<uint8_t> ciphertext = Botan::hex_decode(
1✔
449
      "0401519EAA0489FF9D51E98E4C22349463E2001CD06F8CE47D81D4007A"
450
      "79ACF98E92C814686477CEA666EFC277DC84E15FC95E38AFF8E16D478A"
451
      "44CD5C5F1517F8B1F300000591317F261C3D04A7207F01EAE3EC70F2360"
452
      "0F82C53CC0B85BE7AC9F6CE79EF2AB416E5934D61BA9D346385D7545C57F"
453
      "77C7EA7C58E18C70CBFB0A24AE1B9943EC5A8D0657522CCDF30BA95674D81"
454
      "B397635D215178CD13BD9504AE957A9888F4128FFC0F0D3F1CEC646AEC8CE"
455
      "3F2463D233B22A7A12B679F4C06501F584D4DEFF6D26592A8D873398BD892"
456
      "B477B3468813C053DA43C4F3D49009F7A12D6EF7");
1✔
457

458
   check_encrypt_decrypt(result, private_key, other_private_key, ecies_params, iv, label, plaintext, ciphertext, *rng);
1✔
459

460
   return result;
1✔
461
}
4✔
462

463
Test::Result test_ciphertext_too_short() {
1✔
464
   Test::Result result("ECIES ciphertext too short");
1✔
465

466
   const auto domain = Botan::EC_Group::from_name("secp521r1");
1✔
467
   const Botan::BigInt private_key_value(
1✔
468
      "405029866705438137604064977397053031159826489755682166267763407"
469
      "5002761777100287880684822948852132235484464537021197213998300006"
470
      "547176718172344447619746779823");
1✔
471

472
   const Botan::BigInt other_private_key_value(
1✔
473
      "2294226772740614508941417891614236736606752960073669253551166842"
474
      "5866095315090327914760325168219669828915074071456176066304457448"
475
      "25404691681749451640151380153");
1✔
476

477
   auto rng = Test::new_rng("ecies_ciphertext_too_short");
1✔
478

479
   const Botan::ECDH_PrivateKey private_key(*rng, domain, private_key_value);
1✔
480
   const Botan::ECDH_PrivateKey other_private_key(*rng, domain, other_private_key_value);
1✔
481

482
   const Botan::ECIES_System_Params ecies_params(
1✔
483
      private_key.domain(), "KDF1-18033(SHA-512)", "AES-256/CBC", 32, "HMAC(SHA-512)", 16);
1✔
484

485
   Botan::ECIES_Decryptor ecies_dec(other_private_key, ecies_params, *rng);
1✔
486

487
   result.test_throws("ciphertext too short",
1✔
488
                      [&ecies_dec]() { ecies_dec.decrypt(Botan::hex_decode("0401519EAA0489FF9D51E98E4C22349A")); });
2✔
489

490
   return result;
1✔
491
}
2✔
492

493
class ECIES_Unit_Tests final : public Test {
1✔
494
   public:
495
      std::vector<Test::Result> run() override {
1✔
496
         std::vector<Test::Result> results;
1✔
497

498
         std::vector<std::function<Test::Result()>> fns = {test_other_key_not_set,
1✔
499
                                                           test_kdf_not_found,
500
                                                           test_mac_not_found,
501
                                                           test_cipher_not_found,
502
                                                           test_system_params_short_ctor,
503
                                                           test_ciphertext_too_short};
7✔
504

505
         for(size_t i = 0; i != fns.size(); ++i) {
7✔
506
            try {
6✔
507
               results.emplace_back(fns[i]());
12✔
508
            } catch(std::exception& e) {
×
509
               results.emplace_back(Test::Result::Failure("ECIES unit tests " + std::to_string(i), e.what()));
×
510
            }
×
511
         }
512

513
         return results;
1✔
514
      }
2✔
515
};
516

517
BOTAN_REGISTER_TEST("pubkey", "ecies_unit", ECIES_Unit_Tests);
518

519
   #endif
520

521
#endif
522

523
}  // namespace
524

525
}  // namespace Botan_Tests
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

© 2026 Coveralls, Inc