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

randombit / botan / 5134090420

31 May 2023 03:12PM UTC coverage: 91.721% (-0.3%) from 91.995%
5134090420

push

github

randombit
Merge GH #3565 Disable noisy/pointless pylint warnings

76048 of 82912 relevant lines covered (91.72%)

11755290.1 hits per line

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

89.47
/src/tests/unit_ecdsa.cpp
1
/*
2
* ECDSA Tests
3
*
4
* (C) 2007 Falko Strenzke
5
*     2007 Manuel Hartl
6
*     2008,2015 Jack Lloyd
7
*
8
* Botan is released under the Simplified BSD License (see license.txt)
9
*/
10

11
#include "tests.h"
12
#include <botan/hex.h>
13
#include <numeric>
14

15
#if defined(BOTAN_HAS_ECDSA)
16
   #include <botan/data_src.h>
17
   #include <botan/ec_group.h>
18
   #include <botan/ecdsa.h>
19
   #include <botan/hash.h>
20
   #include <botan/pkcs8.h>
21
   #include <botan/pubkey.h>
22
#endif
23

24
#if defined(BOTAN_HAS_X509_CERTIFICATES)
25
   #include <botan/x509cert.h>
26
#endif
27

28
namespace Botan_Tests {
29

30
namespace {
31

32
#if defined(BOTAN_HAS_ECDSA)
33

34
/**
35
* Tests whether the signing routine will work correctly in case
36
* the integer e that is constructed from the message (thus the hash
37
* value) is larger than n, the order of the base point.  Tests the
38
* signing function of the pk signer object
39
*/
40
Test::Result test_hash_larger_than_n() {
1✔
41
   Test::Result result("ECDSA Unit");
1✔
42

43
   Botan::EC_Group dom_pars("secp160r1");
1✔
44

45
   // n = 0x0100000000000000000001f4c8f927aed3ca752257 (21 bytes)
46

47
   Botan::ECDSA_PrivateKey priv_key(Test::rng(), dom_pars);
1✔
48

49
   std::vector<uint8_t> message(20);
1✔
50
   std::iota(message.begin(), message.end(), static_cast<uint8_t>(0));
1✔
51

52
   auto sha1 = Botan::HashFunction::create("SHA-1");
1✔
53
   auto sha224 = Botan::HashFunction::create("SHA-224");
1✔
54

55
   if(!sha1 || !sha224) {
1✔
56
      result.test_note("Skipping due to missing SHA-1 or SHA-224");
×
57
      return result;
×
58
   }
59

60
   Botan::PK_Signer pk_signer_160(priv_key, Test::rng(), "SHA-1");
1✔
61
   Botan::PK_Verifier pk_verifier_160(priv_key, "SHA-1");
1✔
62

63
   // Verify we can sign and verify with SHA-1
64
   std::vector<uint8_t> signature_160 = pk_signer_160.sign_message(message, Test::rng());
1✔
65
   result.test_eq("message verifies", pk_verifier_160.verify_message(message, signature_160), true);
1✔
66

67
   // Verify we can sign and verify with SHA-224
68
   Botan::PK_Signer pk_signer(priv_key, Test::rng(), "SHA-224");
1✔
69
   std::vector<uint8_t> signature = pk_signer.sign_message(message, Test::rng());
1✔
70
   Botan::PK_Verifier pk_verifier(priv_key, "SHA-224");
1✔
71
   result.test_eq("message verifies", pk_verifier.verify_message(message, signature), true);
1✔
72

73
   return result;
1✔
74
}
6✔
75

76
   #if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
77
Test::Result test_decode_ecdsa_X509() {
1✔
78
   Test::Result result("ECDSA Unit");
1✔
79
   Botan::X509_Certificate cert(Test::data_file("x509/ecc/CSCA.CSCA.csca-germany.1.crt"));
2✔
80

81
   result.test_eq("correct signature oid", cert.signature_algorithm().oid().to_formatted_string(), "ECDSA/SHA-224");
2✔
82

83
   result.test_eq("serial number", cert.serial_number(), Botan::hex_decode("01"));
2✔
84
   result.test_eq("authority key id", cert.authority_key_id(), cert.subject_key_id());
1✔
85
   result.test_eq("key fingerprint",
3✔
86
                  cert.fingerprint("SHA-256"),
2✔
87
                  "3B:6C:99:1C:D6:5A:51:FC:EB:17:E3:AA:F6:3C:1A:DA:14:1F:82:41:30:6F:64:EE:FF:63:F3:1F:D6:07:14:9F");
88

89
   auto pubkey = cert.subject_public_key();
1✔
90
   result.test_eq("verify self-signed signature", cert.check_signature(*pubkey), true);
1✔
91

92
   return result;
2✔
93
}
1✔
94

95
Test::Result test_decode_ver_link_SHA256() {
1✔
96
   Test::Result result("ECDSA Unit");
1✔
97
   Botan::X509_Certificate root_cert(Test::data_file("x509/ecc/root2_SHA256.cer"));
2✔
98
   Botan::X509_Certificate link_cert(Test::data_file("x509/ecc/link_SHA256.cer"));
2✔
99

100
   auto pubkey = root_cert.subject_public_key();
1✔
101
   result.confirm("verified self-signed signature", link_cert.check_signature(*pubkey));
2✔
102
   return result;
2✔
103
}
1✔
104

105
Test::Result test_decode_ver_link_SHA1() {
1✔
106
   Botan::X509_Certificate root_cert(Test::data_file("x509/ecc/root_SHA1.163.crt"));
2✔
107
   Botan::X509_Certificate link_cert(Test::data_file("x509/ecc/link_SHA1.166.crt"));
2✔
108

109
   Test::Result result("ECDSA Unit");
1✔
110
   auto pubkey = root_cert.subject_public_key();
1✔
111

112
   auto sha1 = Botan::HashFunction::create("SHA-1");
1✔
113

114
   if(!sha1) {
1✔
115
      result.confirm("verification of self-signed signature failed due to missing SHA-1",
×
116
                     !link_cert.check_signature(*pubkey));
×
117
      return result;
×
118
   }
119
   result.confirm("verified self-signed signature", link_cert.check_signature(*pubkey));
2✔
120
   return result;
1✔
121
}
2✔
122
   #endif
123

124
Test::Result test_sign_then_ver() {
1✔
125
   Test::Result result("ECDSA Unit");
1✔
126

127
   Botan::EC_Group dom_pars("secp160r1");
1✔
128
   Botan::ECDSA_PrivateKey ecdsa(Test::rng(), dom_pars);
1✔
129

130
   Botan::PK_Signer signer(ecdsa, Test::rng(), "SHA-256");
1✔
131

132
   auto msg = Botan::hex_decode("12345678901234567890abcdef12");
1✔
133
   std::vector<uint8_t> sig = signer.sign_message(msg, Test::rng());
1✔
134

135
   Botan::PK_Verifier verifier(ecdsa, "SHA-256");
1✔
136

137
   result.confirm("signature verifies", verifier.verify_message(msg, sig));
2✔
138

139
   result.confirm("invalid signature rejected", !verifier.verify_message(msg, Test::mutate_vec(sig)));
3✔
140

141
   return result;
1✔
142
}
3✔
143

144
Test::Result test_ec_sign() {
1✔
145
   Test::Result result("ECDSA Unit");
1✔
146

147
   try {
1✔
148
      Botan::EC_Group dom_pars("secp160r1");
1✔
149
      Botan::ECDSA_PrivateKey priv_key(Test::rng(), dom_pars);
1✔
150
      Botan::PK_Signer signer(priv_key, Test::rng(), "SHA-224");
1✔
151
      Botan::PK_Verifier verifier(priv_key, "SHA-224");
1✔
152

153
      for(size_t i = 0; i != 256; ++i) {
257✔
154
         signer.update(static_cast<uint8_t>(i));
256✔
155
      }
156
      std::vector<uint8_t> sig = signer.signature(Test::rng());
1✔
157

158
      for(size_t i = 0; i != 256; ++i) {
257✔
159
         verifier.update(static_cast<uint8_t>(i));
256✔
160
      }
161

162
      result.test_eq("ECDSA signature valid", verifier.check_signature(sig), true);
1✔
163

164
      // now check valid signature, different input
165
      for(size_t i = 1; i != 256; ++i)  //starting from 1
256✔
166
      {
167
         verifier.update(static_cast<uint8_t>(i));
255✔
168
      }
169

170
      result.test_eq("invalid ECDSA signature invalid", verifier.check_signature(sig), false);
1✔
171

172
      // now check with original input, modified signature
173

174
      sig[sig.size() / 2]++;
1✔
175
      for(size_t i = 0; i != 256; ++i) {
257✔
176
         verifier.update(static_cast<uint8_t>(i));
256✔
177
      }
178

179
      result.test_eq("invalid ECDSA signature invalid", verifier.check_signature(sig), false);
2✔
180
   } catch(std::exception& e) {
1✔
181
      result.test_failure("test_ec_sign", e.what());
×
182
   }
×
183

184
   return result;
1✔
185
}
×
186

187
Test::Result test_ecdsa_create_save_load() {
1✔
188
   Test::Result result("ECDSA Unit");
1✔
189

190
   std::string ecc_private_key_pem;
1✔
191
   const std::vector<uint8_t> msg = Botan::hex_decode("12345678901234567890abcdef12");
1✔
192
   std::vector<uint8_t> msg_signature;
1✔
193

194
   try {
1✔
195
      Botan::EC_Group dom_pars("secp160r1");
1✔
196
      Botan::ECDSA_PrivateKey key(Test::rng(), dom_pars);
1✔
197

198
      Botan::PK_Signer signer(key, Test::rng(), "SHA-256");
1✔
199
      msg_signature = signer.sign_message(msg, Test::rng());
2✔
200

201
      ecc_private_key_pem = Botan::PKCS8::PEM_encode(key);
1✔
202
   } catch(std::exception& e) {
1✔
203
      result.test_failure("create_pkcs8", e.what());
×
204
   }
×
205

206
   Botan::DataSource_Memory pem_src(ecc_private_key_pem);
1✔
207
   auto loaded_key = Botan::PKCS8::load_key(pem_src);
1✔
208
   Botan::ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<Botan::ECDSA_PrivateKey*>(loaded_key.get());
1✔
209
   result.confirm("the loaded key could be converted into an ECDSA_PrivateKey", loaded_ec_key != nullptr);
2✔
210

211
   if(loaded_ec_key) {
1✔
212
      result.confirm("the loaded key produces equal encoding",
2✔
213
                     (ecc_private_key_pem == Botan::PKCS8::PEM_encode(*loaded_ec_key)));
1✔
214
      Botan::PK_Verifier verifier(*loaded_ec_key, "SHA-256");
1✔
215
      result.confirm("generated signature valid", verifier.verify_message(msg, msg_signature));
2✔
216
   }
1✔
217

218
   return result;
1✔
219
}
5✔
220

221
Test::Result test_unusual_curve() {
1✔
222
   Test::Result result("ECDSA Unit");
1✔
223

224
   //calc a curve which is not in the registry
225
   const Botan::BigInt p(
1✔
226
      "2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809");
1✔
227
   const Botan::BigInt a(
1✔
228
      "0x0a377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe");
1✔
229
   const Botan::BigInt b(
1✔
230
      "0x0a9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7");
1✔
231
   const Botan::BigInt order_g("0x0e1a16196e6000000000bc7f1618d867b15bb86474418f");
1✔
232
   const Botan::BigInt cofactor = Botan::BigInt::one();
1✔
233

234
   const BigInt Gx(
1✔
235
      "1503931002566715881584977704503341991763310127581173321974500299341775226206001860606586625324214456299149080935147329869147994265934715820");
1✔
236
   const BigInt Gy(
1✔
237
      "1774988776970033741491814582357926984496972046739476148938345272681378523636129776486407268230155403536112014267092770854858769258781598199");
1✔
238

239
   Botan::EC_Group dom_params(p, a, b, Gx, Gy, order_g, cofactor);
1✔
240

241
   Botan::EC_Point p_G = dom_params.point(Gx, Gy);
1✔
242

243
   if(!result.confirm("G is on curve", p_G.on_the_curve())) {
2✔
244
      return result;
245
   }
246

247
   Botan::ECDSA_PrivateKey key_odd_curve(Test::rng(), dom_params);
1✔
248
   std::string key_odd_curve_str = Botan::PKCS8::PEM_encode(key_odd_curve);
1✔
249

250
   Botan::DataSource_Memory key_data_src(key_odd_curve_str);
1✔
251
   auto loaded_key = Botan::PKCS8::load_key(key_data_src);
1✔
252

253
   result.confirm("reloaded key", loaded_key != nullptr);
2✔
254

255
   return result;
1✔
256
}
10✔
257

258
Test::Result test_encoding_options() {
1✔
259
   Test::Result result("ECDSA Unit");
1✔
260

261
   Botan::EC_Group group("secp256r1");
1✔
262
   Botan::ECDSA_PrivateKey key(Test::rng(), group);
1✔
263

264
   result.confirm("Default encoding is uncompressed", key.point_encoding() == Botan::EC_Point_Format::Uncompressed);
2✔
265

266
   const std::vector<uint8_t> enc_uncompressed = key.public_key_bits();
1✔
267

268
   key.set_point_encoding(Botan::EC_Point_Format::Compressed);
1✔
269

270
   result.confirm("set_point_encoding works", key.point_encoding() == Botan::EC_Point_Format::Compressed);
2✔
271

272
   const std::vector<uint8_t> enc_compressed = key.public_key_bits();
1✔
273

274
   result.test_lt("Comprssed points are smaller", enc_compressed.size(), enc_uncompressed.size());
1✔
275

276
   size_t size_diff = enc_uncompressed.size() - enc_compressed.size();
1✔
277

278
   result.test_gte("Compressed points smaller by group size", size_diff, 32);
1✔
279

280
   key.set_point_encoding(Botan::EC_Point_Format::Hybrid);
1✔
281

282
   result.confirm("set_point_encoding works", key.point_encoding() == Botan::EC_Point_Format::Hybrid);
2✔
283

284
   const std::vector<uint8_t> enc_hybrid = key.public_key_bits();
1✔
285

286
   result.test_eq("Hybrid point same size as uncompressed", enc_uncompressed.size(), enc_hybrid.size());
1✔
287

288
   #if !defined(BOTAN_HAS_SANITIZER_UNDEFINED)
289
   auto invalid_format = static_cast<Botan::EC_Point_Format>(99);
1✔
290

291
   result.test_throws("Invalid point format throws", "Invalid point encoding for EC_PublicKey", [&] {
3✔
292
      key.set_point_encoding(invalid_format);
1✔
293
   });
294
   #endif
295

296
   return result;
2✔
297
}
3✔
298

299
   #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
300

301
Test::Result test_read_pkcs8() {
1✔
302
   Test::Result result("ECDSA Unit");
1✔
303

304
   const std::vector<uint8_t> msg = Botan::hex_decode("12345678901234567890abcdef12");
1✔
305

306
   try {
1✔
307
      Botan::DataSource_Stream key_stream(Test::data_file("x509/ecc/nodompar_private.pkcs8.pem"));
2✔
308
      auto loaded_key_nodp = Botan::PKCS8::load_key(key_stream);
1✔
309
      // anew in each test with unregistered domain-parameters
310
      Botan::ECDSA_PrivateKey* ecdsa_nodp = dynamic_cast<Botan::ECDSA_PrivateKey*>(loaded_key_nodp.get());
1✔
311
      if(!ecdsa_nodp) {
1✔
312
         throw Test_Error("Unable to load valid PKCS8 ECDSA key");
×
313
      }
314

315
      Botan::PK_Signer signer(*ecdsa_nodp, Test::rng(), "SHA-256");
1✔
316
      Botan::PK_Verifier verifier(*ecdsa_nodp, "SHA-256");
1✔
317

318
      std::vector<uint8_t> signature_nodp = signer.sign_message(msg, Test::rng());
1✔
319

320
      result.confirm("signature valid", verifier.verify_message(msg, signature_nodp));
2✔
321

322
      try {
1✔
323
         Botan::DataSource_Stream key_stream2(Test::data_file("x509/ecc/withdompar_private.pkcs8.pem"));
2✔
324
         auto should_fail = Botan::PKCS8::load_key(key_stream2);
1✔
325
         result.test_failure("loaded key with unknown OID");
×
326
      } catch(std::exception&) {
2✔
327
         result.test_note("rejected key with unknown OID");
1✔
328
      }
1✔
329
   } catch(std::exception& e) {
2✔
330
      result.test_failure("read_pkcs8", e.what());
×
331
   }
×
332

333
   return result;
1✔
334
}
1✔
335

336
Test::Result test_ecc_key_with_rfc5915_extensions() {
1✔
337
   Test::Result result("ECDSA Unit");
1✔
338

339
   try {
1✔
340
      Botan::DataSource_Stream key_stream(Test::data_file("x509/ecc/ecc_private_with_rfc5915_ext.pem"));
2✔
341
      auto pkcs8 = Botan::PKCS8::load_key(key_stream);
1✔
342

343
      result.confirm("loaded RFC 5915 key", pkcs8 != nullptr);
2✔
344
      result.test_eq("key is ECDSA", pkcs8->algo_name(), "ECDSA");
2✔
345
      result.confirm("key type is ECDSA", dynamic_cast<Botan::ECDSA_PrivateKey*>(pkcs8.get()) != nullptr);
3✔
346
   } catch(std::exception& e) {
1✔
347
      result.test_failure("load_rfc5915_ext", e.what());
×
348
   }
×
349

350
   return result;
1✔
351
}
×
352

353
Test::Result test_ecc_key_with_rfc5915_parameters() {
1✔
354
   Test::Result result("ECDSA Unit");
1✔
355

356
   try {
1✔
357
      Botan::DataSource_Stream key_stream(Test::data_file("x509/ecc/ecc_private_with_rfc5915_parameters.pem"));
2✔
358
      auto pkcs8 = Botan::PKCS8::load_key(key_stream);
1✔
359

360
      result.confirm("loaded RFC 5915 key", pkcs8 != nullptr);
2✔
361
      result.test_eq("key is ECDSA", pkcs8->algo_name(), "ECDSA");
2✔
362
      result.confirm("key type is ECDSA", dynamic_cast<Botan::ECDSA_PrivateKey*>(pkcs8.get()) != nullptr);
3✔
363
   } catch(std::exception& e) {
×
364
      result.test_failure("load_rfc5915_params", e.what());
×
365
   }
×
366

367
   return result;
1✔
368
}
×
369

370
   #endif
371

372
Test::Result test_curve_registry() {
1✔
373
   Test::Result result("ECDSA Unit");
1✔
374

375
   for(const std::string& group_name : Botan::EC_Group::known_named_groups()) {
28✔
376
      try {
27✔
377
         Botan::EC_Group group(group_name);
27✔
378
         Botan::ECDSA_PrivateKey ecdsa(Test::rng(), group);
27✔
379

380
         Botan::PK_Signer signer(ecdsa, Test::rng(), "SHA-256");
27✔
381
         Botan::PK_Verifier verifier(ecdsa, "SHA-256");
27✔
382

383
         const std::vector<uint8_t> msg = Botan::hex_decode("12345678901234567890abcdef12");
27✔
384
         const std::vector<uint8_t> sig = signer.sign_message(msg, Test::rng());
27✔
385

386
         result.confirm("verified signature", verifier.verify_message(msg, sig));
81✔
387
      } catch(Botan::Invalid_Argument& e) {
54✔
388
         result.test_failure("testing " + group_name + ": " + e.what());
×
389
      }
×
390
   }
391

392
   return result;
1✔
393
}
×
394

395
class ECDSA_Unit_Tests final : public Test {
×
396
   public:
397
      std::vector<Test::Result> run() override {
1✔
398
         std::vector<Test::Result> results;
1✔
399

400
   #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
401
         results.push_back(test_read_pkcs8());
2✔
402
         results.push_back(test_ecc_key_with_rfc5915_extensions());
2✔
403
         results.push_back(test_ecc_key_with_rfc5915_parameters());
2✔
404

405
      #if defined(BOTAN_HAS_X509_CERTIFICATES)
406
         results.push_back(test_decode_ecdsa_X509());
2✔
407
         results.push_back(test_decode_ver_link_SHA256());
2✔
408
         results.push_back(test_decode_ver_link_SHA1());
2✔
409
      #endif
410

411
   #endif
412

413
         results.push_back(test_hash_larger_than_n());
2✔
414
         results.push_back(test_sign_then_ver());
2✔
415
         results.push_back(test_ec_sign());
2✔
416
         results.push_back(test_ecdsa_create_save_load());
2✔
417
         results.push_back(test_unusual_curve());
2✔
418
         results.push_back(test_curve_registry());
2✔
419
         results.push_back(test_encoding_options());
2✔
420
         return results;
1✔
421
      }
×
422
};
423

424
BOTAN_REGISTER_TEST("pubkey", "ecdsa_unit", ECDSA_Unit_Tests);
425
#endif
426

427
}  // namespace
428

429
}  // 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

© 2025 Coveralls, Inc