-
Notifications
You must be signed in to change notification settings - Fork 8
Closed
Description
When benchmarking ML-DSA sign function, we random sample all input arguments, making the algorithm non-deterministic - resulting in variable timing. This doesn't give correct performance profile during benchmarking.
ml-dsa/benchmarks/bench_ml_dsa_44.cpp
Lines 29 to 68 in 5e24387
| // Benchmark performance of ML-DSA-44 signing algorithm. | |
| void | |
| ml_dsa_44_sign(benchmark::State& state) | |
| { | |
| const size_t mlen = state.range(0); | |
| std::vector<uint8_t> msg(mlen, 0); | |
| auto msg_span = std::span(msg); | |
| std::array<uint8_t, ml_dsa_44::KeygenSeedByteLen> seed{}; | |
| std::array<uint8_t, ml_dsa_44::PubKeyByteLen> pubkey{}; | |
| std::array<uint8_t, ml_dsa_44::SecKeyByteLen> seckey{}; | |
| std::array<uint8_t, ml_dsa_44::SigningSeedByteLen> rnd{}; | |
| std::array<uint8_t, ml_dsa_44::SigByteLen> sig{}; | |
| randomshake::randomshake_t<128> csprng; | |
| csprng.generate(seed); | |
| csprng.generate(rnd); | |
| csprng.generate(msg_span); | |
| ml_dsa_44::keygen(seed, pubkey, seckey); | |
| bool has_signed = true; | |
| for (auto _ : state) { | |
| benchmark::DoNotOptimize(has_signed); | |
| benchmark::DoNotOptimize(rnd); | |
| benchmark::DoNotOptimize(seckey); | |
| benchmark::DoNotOptimize(msg_span); | |
| benchmark::DoNotOptimize(sig); | |
| has_signed &= ml_dsa_44::sign(rnd, seckey, msg_span, {}, sig); | |
| benchmark::ClobberMemory(); | |
| } | |
| assert(has_signed); | |
| assert(ml_dsa_44::verify(pubkey, msg_span, {}, sig)); | |
| state.SetItemsProcessed(state.iterations()); | |
| } |
To avoid this, we can seed the RandomShake CSRPNG (cryptographically secure pseudo-random number generator) with a fixed seed. Address it and update benchmark results. This will also make it easy to spot any performance degradation or optimization.
Metadata
Metadata
Assignees
Labels
No labels