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

randombit / botan / 12991133942

27 Jan 2025 02:24PM UTC coverage: 91.246% (-0.008%) from 91.254%
12991133942

push

github

web-flow
Merge pull request #4592 from randombit/jack/split-key-prework

Some initial refactoring for splitting public and private keys

93966 of 102981 relevant lines covered (91.25%)

11558329.57 hits per line

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

79.87
/src/cli/perf_pk_sig.cpp
1
/*
2
* (C) 2024 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "perf.h"
8

9
#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
10
   #include <botan/pk_algs.h>
11
   #include <botan/pubkey.h>
12
#endif
13

14
namespace Botan_CLI {
15

16
#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
17

18
class PerfTest_PKSig : public PerfTest {
12✔
19
   public:
20
      virtual std::string algo() const = 0;
21

22
      virtual std::string hash() const { return "SHA-256"; }
4✔
23

24
      virtual std::vector<std::string> keygen_params(const PerfConfig& config) const {
2✔
25
         BOTAN_UNUSED(config);
2✔
26
         return {""};
2✔
27
      }
28

29
      void go(const PerfConfig& config) override {
12✔
30
         const std::string alg = this->algo();
12✔
31
         const std::string padding = this->hash();
12✔
32

33
         const auto params = this->keygen_params(config);
12✔
34

35
         for(const auto& param : params) {
63✔
36
            const std::string nm = this->format_name(alg, param);
51✔
37
            bench_pk_sig(config, nm, alg, param, padding);
102✔
38
         }
51✔
39
      }
12✔
40

41
      void bench_pk_sig(const PerfConfig& config,
51✔
42
                        const std::string& nm,
43
                        const std::string& alg,
44
                        const std::string& param,
45
                        const std::string& padding,
46
                        const std::string& provider = "") {
47
         auto& rng = config.rng();
51✔
48
         const auto msec = config.runtime();
51✔
49

50
         auto keygen_timer = config.make_timer(nm, 1, "keygen");
102✔
51

52
         auto sk = keygen_timer->run([&] { return Botan::create_private_key(alg, rng, param); });
102✔
53
         while(keygen_timer->under(msec)) {
87✔
54
            sk = keygen_timer->run([&] { return Botan::create_private_key(alg, rng, param); });
108✔
55
         }
56

57
         if(sk != nullptr) {
51✔
58
            config.record_result(*keygen_timer);
51✔
59

60
            auto pk = sk->public_key();
51✔
61

62
            std::vector<uint8_t> message, signature, bad_signature;
51✔
63

64
            Botan::PK_Signer sig(*sk, rng, padding, Botan::Signature_Format::Standard, provider);
51✔
65
            Botan::PK_Verifier ver(*pk, padding, Botan::Signature_Format::Standard, provider);
51✔
66

67
            auto sig_timer = config.make_timer(nm, 1, "sign");
102✔
68
            auto ver_timer = config.make_timer(nm, 1, "verify");
102✔
69

70
            size_t invalid_sigs = 0;
51✔
71

72
            while(ver_timer->under(msec) || sig_timer->under(msec)) {
267✔
73
               if(signature.empty() || sig_timer->under(msec)) {
165✔
74
                  /*
75
                  Length here is kind of arbitrary, but 48 bytes fits into a single
76
                  hash block so minimizes hashing overhead versus the PK op itself.
77
                  */
78
                  rng.random_vec(message, 48);
116✔
79

80
                  signature = sig_timer->run([&]() { return sig.sign_message(message, rng); });
232✔
81

82
                  bad_signature = signature;
116✔
83
                  bad_signature[rng.next_byte() % bad_signature.size()] ^= rng.next_nonzero_byte();
116✔
84
               }
85

86
               if(ver_timer->under(msec)) {
165✔
87
                  const bool verified = ver_timer->run([&] { return ver.verify_message(message, signature); });
232✔
88

89
                  if(!verified) {
116✔
90
                     invalid_sigs += 1;
×
91
                  }
92

93
                  const bool verified_bad = ver_timer->run([&] { return ver.verify_message(message, bad_signature); });
232✔
94

95
                  if(verified_bad) {
116✔
96
                     config.error_output() << "Bad signature accepted in " << nm << " signature bench\n";
×
97
                  }
98
               }
99
            }
100

101
            if(invalid_sigs > 0) {
51✔
102
               config.error_output() << invalid_sigs << " generated signatures rejected in " << nm
×
103
                                     << " signature bench\n";
×
104
            }
105
            config.record_result(*sig_timer);
51✔
106
            config.record_result(*ver_timer);
102✔
107
         }
102✔
108
      }
51✔
109
};
110

111
#endif
112

113
#if defined(BOTAN_HAS_DSA)
114

115
class PerfTest_DSA final : public PerfTest_PKSig {
1✔
116
   public:
117
      std::string algo() const override { return "DSA"; }
1✔
118

119
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
120
         BOTAN_UNUSED(config);
1✔
121
         return {"dsa/jce/1024", "dsa/botan/2048", "dsa/botan/3072"};
1✔
122
      }
123

124
      std::string format_name(const std::string& alg, const std::string& param) const override {
3✔
125
         return Botan::fmt("{}-{}", alg, param.substr(param.find_last_of('/') + 1));
6✔
126
      }
127
};
128

129
BOTAN_REGISTER_PERF_TEST("DSA", PerfTest_DSA);
1✔
130

131
#endif
132

133
#if defined(BOTAN_HAS_RSA)
134

135
class PerfTest_RSA final : public PerfTest_PKSig {
1✔
136
   public:
137
      std::string algo() const override { return "RSA"; }
1✔
138

139
      std::string hash() const override { return "PKCS1v15(SHA-256)"; }
1✔
140

141
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
142
         BOTAN_UNUSED(config);
1✔
143
         return {"1024", "2048", "3072", "4096"};
1✔
144
      }
145
};
146

147
BOTAN_REGISTER_PERF_TEST("RSA", PerfTest_RSA);
1✔
148

149
#endif
150

151
#if defined(BOTAN_HAS_ECDSA)
152

153
class PerfTest_ECDSA final : public PerfTest_PKSig {
1✔
154
   public:
155
      std::string algo() const override { return "ECDSA"; }
1✔
156

157
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
158
};
159

160
BOTAN_REGISTER_PERF_TEST("ECDSA", PerfTest_ECDSA);
1✔
161

162
#endif
163

164
#if defined(BOTAN_HAS_ECKCDSA)
165

166
class PerfTest_ECKCDSA final : public PerfTest_PKSig {
1✔
167
   public:
168
      std::string algo() const override { return "ECKCDSA"; }
1✔
169

170
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
171
};
172

173
BOTAN_REGISTER_PERF_TEST("ECKCDSA", PerfTest_ECKCDSA);
1✔
174

175
#endif
176

177
#if defined(BOTAN_HAS_ECGDSA)
178

179
class PerfTest_ECGDSA final : public PerfTest_PKSig {
1✔
180
   public:
181
      std::string algo() const override { return "ECGDSA"; }
1✔
182

183
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
184
};
185

186
BOTAN_REGISTER_PERF_TEST("ECGDSA", PerfTest_ECGDSA);
1✔
187

188
#endif
189

190
#if defined(BOTAN_HAS_GOST_34_10_2001) && defined(BOTAN_HAS_GOST_34_11)
191

192
class PerfTest_Gost3410 final : public PerfTest_PKSig {
1✔
193
   public:
194
      std::string algo() const override { return "GOST-34.10"; }
1✔
195

196
      std::string hash() const override { return "GOST-34.11"; }
1✔
197

198
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
199
         BOTAN_UNUSED(config);
1✔
200
         return {"gost_256A"};
1✔
201
      }
202
};
203

204
BOTAN_REGISTER_PERF_TEST("GOST-34.10", PerfTest_Gost3410);
1✔
205

206
#endif
207

208
#if defined(BOTAN_HAS_SM2) && defined(BOTAN_HAS_SM3)
209

210
class PerfTest_SM2 final : public PerfTest_PKSig {
1✔
211
   public:
212
      std::string algo() const override { return "SM2"; }
1✔
213

214
      std::string hash() const override { return "SM3"; }
1✔
215

216
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
217
         BOTAN_UNUSED(config);
1✔
218
         return {"sm2p256v1"};
1✔
219
      }
220
};
221

222
BOTAN_REGISTER_PERF_TEST("SM2", PerfTest_SM2);
1✔
223

224
#endif
225

226
#if defined(BOTAN_HAS_ED25519)
227

228
class PerfTest_Ed25519 final : public PerfTest_PKSig {
1✔
229
   public:
230
      std::string algo() const override { return "Ed25519"; }
1✔
231

232
      std::string hash() const override { return "Pure"; }
1✔
233
};
234

235
BOTAN_REGISTER_PERF_TEST("Ed25519", PerfTest_Ed25519);
1✔
236

237
#endif
238

239
#if defined(BOTAN_HAS_ED448)
240

241
class PerfTest_Ed448 final : public PerfTest_PKSig {
1✔
242
   public:
243
      std::string algo() const override { return "Ed448"; }
1✔
244

245
      std::string hash() const override { return "Pure"; }
1✔
246
};
247

248
BOTAN_REGISTER_PERF_TEST("Ed448", PerfTest_Ed448);
1✔
249

250
#endif
251

252
#if defined(BOTAN_HAS_XMSS_RFC8391)
253

254
class PerfTest_XMSS final : public PerfTest_PKSig {
1✔
255
   public:
256
      std::string algo() const override { return "XMSS"; }
1✔
257

258
      std::string hash() const override { return ""; }
1✔
259

260
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
261
         BOTAN_UNUSED(config);
1✔
262

263
         /*
264
         We only test H10 signatures here since already they are quite slow (a
265
         few seconds per signature). On a fast machine, H16 signatures take 1-2
266
         minutes to generate and H20 signatures take 5-10 minutes to generate
267
         */
268
         return {
1✔
269
            "XMSS-SHA2_10_256",
270
            "XMSS-SHAKE_10_256",
271
            "XMSS-SHA2_10_512",
272
            "XMSS-SHAKE_10_512",
273
         };
1✔
274
      }
275
};
276

277
BOTAN_REGISTER_PERF_TEST("XMSS", PerfTest_XMSS);
1✔
278

279
#endif
280

281
#if defined(BOTAN_HAS_HSS_LMS)
282

283
class PerfTest_HSS_LMS final : public PerfTest_PKSig {
×
284
   public:
285
      std::string algo() const override { return "HSS-LMS"; }
×
286

287
      std::string hash() const override { return ""; }
×
288

289
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
×
290
         BOTAN_UNUSED(config);
×
291

292
         // At first we compare instances with multiple hash functions. LMS trees with
293
         // height 10 are suitable, since they can be used for enough signatures and are
294
         // fast enough for speed testing.
295
         // Afterward, setups with multiple HSS layers are tested
296
         return {"SHA-256,HW(10,1)",
×
297
                 "SHAKE-256(256),HW(10,1)",
298
                 "SHAKE-256(192),HW(10,1)",
299
                 "Truncated(SHA-256,192),HW(10,1)",
300
                 "SHA-256,HW(10,1),HW(10,1)",
301
                 "SHA-256,HW(10,1),HW(10,1),HW(10,1)"};
×
302
      }
303
};
304

305
BOTAN_REGISTER_PERF_TEST("HSS-LMS", PerfTest_HSS_LMS);
×
306

307
#endif
308

309
#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
310

311
class PerfTest_SPHINCSp final : public PerfTest_PKSig {
×
312
   public:
313
      std::string algo() const override { return "SPHINCS+"; }
×
314

315
      std::string hash() const override { return ""; }
×
316

317
      std::string format_name(const std::string& alg, const std::string& param) const override {
×
318
         return alg + param.substr(11);
×
319
      }
320

321
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
×
322
         BOTAN_UNUSED(config);
×
323

324
         return {"SphincsPlus-sha2-128s-r3.1",
×
325
                 "SphincsPlus-sha2-128f-r3.1",
326
                 "SphincsPlus-sha2-192s-r3.1",
327
                 "SphincsPlus-sha2-192f-r3.1",
328
                 "SphincsPlus-sha2-256s-r3.1",
329
                 "SphincsPlus-sha2-256f-r3.1",
330
                 "SphincsPlus-shake-128s-r3.1",
331
                 "SphincsPlus-shake-128f-r3.1",
332
                 "SphincsPlus-shake-192s-r3.1",
333
                 "SphincsPlus-shake-192f-r3.1",
334
                 "SphincsPlus-shake-256s-r3.1",
335
                 "SphincsPlus-shake-256f-r3.1"};
×
336
      }
337
};
338

339
BOTAN_REGISTER_PERF_TEST("SPHINCS+", PerfTest_SPHINCSp);
×
340

341
#endif
342

343
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
344

345
class PerfTest_SLH_DSA final : public PerfTest_PKSig {
1✔
346
   public:
347
      std::string algo() const override { return "SLH-DSA"; }
1✔
348

349
      std::string hash() const override { return ""; }
1✔
350

351
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
352
         BOTAN_UNUSED(config);
1✔
353

354
         return {"SLH-DSA-SHA2-128s",
1✔
355
                 "SLH-DSA-SHA2-128f",
356
                 "SLH-DSA-SHA2-192s",
357
                 "SLH-DSA-SHA2-192f",
358
                 "SLH-DSA-SHA2-256s",
359
                 "SLH-DSA-SHA2-256f",
360
                 "SLH-DSA-SHAKE-128s",
361
                 "SLH-DSA-SHAKE-128f",
362
                 "SLH-DSA-SHAKE-192s",
363
                 "SLH-DSA-SHAKE-192f",
364
                 "SLH-DSA-SHAKE-256s",
365
                 "SLH-DSA-SHAKE-256f"};
1✔
366
      }
367
};
368

369
BOTAN_REGISTER_PERF_TEST("SLH-DSA", PerfTest_SLH_DSA);
1✔
370

371
#endif
372

373
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
374

375
class PerfTest_Dilithium final : public PerfTest_PKSig {
1✔
376
   public:
377
      std::string algo() const override { return "Dilithium"; }
1✔
378

379
      std::string hash() const override { return ""; }
1✔
380

381
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
382
         BOTAN_UNUSED(config);
1✔
383

384
         return {
1✔
385
            "Dilithium-4x4-r3",
386
            "Dilithium-4x4-AES-r3",
387
            "Dilithium-6x5-r3",
388
            "Dilithium-6x5-AES-r3",
389
            "Dilithium-8x7-r3",
390
            "Dilithium-8x7-AES-r3",
391
         };
1✔
392
      }
393
};
394

395
BOTAN_REGISTER_PERF_TEST("Dilithium", PerfTest_Dilithium);
1✔
396

397
#endif
398

399
#if defined(BOTAN_HAS_ML_DSA)
400

401
class PerfTest_ML_DSA final : public PerfTest_PKSig {
×
402
   public:
403
      std::string algo() const override { return "ML-DSA"; }
×
404

405
      std::string hash() const override { return ""; }
×
406

407
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
×
408
         BOTAN_UNUSED(config);
×
409

410
         return {
×
411
            "ML-DSA-4x4",
412
            "ML-DSA-6x5",
413
            "ML-DSA-8x7",
414
         };
×
415
      }
416
};
417

418
BOTAN_REGISTER_PERF_TEST("ML-DSA", PerfTest_ML_DSA);
×
419

420
#endif
421

422
}  // namespace Botan_CLI
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