Botan 3.9.0
Crypto and TLS for C&
rfc6979.cpp
Go to the documentation of this file.
1/*
2* RFC 6979 Deterministic Nonce Generator
3* (C) 2014,2015,2024 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/rfc6979.h>
9
10#include <botan/assert.h>
11#include <botan/hmac_drbg.h>
12#include <botan/mac.h>
13#include <botan/internal/fmt.h>
14
15namespace Botan {
16
19
21
22RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const BigInt& x) :
23 m_qlen(order_bits), m_rlen((m_qlen + 7) / 8), m_rng_in(m_rlen * 2), m_rng_out(m_rlen) {
24 m_hmac_drbg = std::make_unique<HMAC_DRBG>(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hash)));
25
26 x.serialize_to(std::span{m_rng_in}.first(m_rlen));
27}
28
30 BOTAN_DEBUG_ASSERT(order.bits() == m_qlen);
31
32 m.serialize_to(std::span{m_rng_in}.last(m_rlen));
33
34 m_hmac_drbg->initialize_with(m_rng_in);
35
36 const size_t shift = 8 * m_rlen - m_qlen;
37 BOTAN_ASSERT_NOMSG(shift < 8);
38
39 BigInt k;
40
41 for(;;) {
42 m_hmac_drbg->randomize(m_rng_out);
43 k._assign_from_bytes(m_rng_out);
44
45 if(shift > 0) {
46 k >>= shift;
47 }
48
49 if(k > 0 && k < order) {
50 break;
51 }
52 }
53
54 return k;
55}
56
57#if defined(BOTAN_HAS_ECC_GROUP)
58RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const EC_Scalar& scalar) :
59 m_qlen(order_bits), m_rlen((m_qlen + 7) / 8), m_rng_in(m_rlen * 2), m_rng_out(m_rlen) {
60 m_hmac_drbg = std::make_unique<HMAC_DRBG>(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hash)));
61
62 scalar.serialize_to(std::span{m_rng_in}.first(m_rlen));
63}
64
66 m.serialize_to(std::span{m_rng_in}.last(m_rlen));
67
68 m_hmac_drbg->initialize_with(m_rng_in);
69
70 const size_t shift = 8 * m_rlen - m_qlen;
71 BOTAN_ASSERT_NOMSG(shift < 8);
72
73 for(;;) {
74 m_hmac_drbg->randomize(m_rng_out);
75
76 if(shift > 0) {
77 uint8_t carry = 0;
78 for(uint8_t& b : m_rng_out) {
79 const uint8_t w = b;
80 b = (w >> shift) | carry;
81 carry = w << (8 - shift);
82 }
83 }
84
85 if(auto k = EC_Scalar::deserialize(group, m_rng_out)) {
86 return *k;
87 }
88 }
89}
90#endif
91
92} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
void serialize_to(std::span< uint8_t > out) const
Definition bigint.cpp:399
size_t bits() const
Definition bigint.cpp:311
void _assign_from_bytes(std::span< const uint8_t > bytes)
Definition bigint.h:947
static std::optional< EC_Scalar > deserialize(const EC_Group &group, std::span< const uint8_t > bytes)
void serialize_to(std::span< uint8_t > bytes) const
Definition ec_scalar.cpp:88
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition mac.cpp:148
RFC6979_Nonce_Generator & operator=(const RFC6979_Nonce_Generator &other)=delete
RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const BigInt &x)
Definition rfc6979.cpp:22
BigInt nonce_for(const BigInt &group_order, const BigInt &m)
Definition rfc6979.cpp:29
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
void carry(int64_t &h0, int64_t &h1)