Botan  2.6.0
Crypto and TLS for C++11
ecgdsa.cpp
Go to the documentation of this file.
1 /*
2 * ECGDSA (BSI-TR-03111, version 2.0)
3 * (C) 2016 RenĂ© Korthaus
4 * (C) 2018 Jack Lloyd
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/ecgdsa.h>
10 #include <botan/keypair.h>
11 #include <botan/reducer.h>
12 #include <botan/internal/pk_ops_impl.h>
13 
14 namespace Botan {
15 
17  bool strong) const
18  {
19  if(!public_point().on_the_curve())
20  return false;
21 
22  if(!strong)
23  return true;
24 
25  return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
26  }
27 
28 namespace {
29 
30 /**
31 * ECGDSA signature operation
32 */
33 class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
34  {
35  public:
36 
37  ECGDSA_Signature_Operation(const ECGDSA_PrivateKey& ecgdsa,
38  const std::string& emsa) :
39  PK_Ops::Signature_with_EMSA(emsa),
40  m_group(ecgdsa.domain()),
41  m_x(ecgdsa.private_value())
42  {
43  }
44 
45  secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
46  RandomNumberGenerator& rng) override;
47 
48  size_t max_input_bits() const override { return m_group.get_order_bits(); }
49 
50  private:
51  const EC_Group m_group;
52  const BigInt& m_x;
53  std::vector<BigInt> m_ws;
54  };
55 
56 secure_vector<uint8_t>
57 ECGDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
58  RandomNumberGenerator& rng)
59  {
60  const BigInt m(msg, msg_len, m_group.get_order_bits());
61 
62  const BigInt k = m_group.random_scalar(rng);
63 
64  const BigInt r = m_group.mod_order(
65  m_group.blinded_base_point_multiply_x(k, rng, m_ws));
66 
67  const BigInt kr = m_group.multiply_mod_order(k, r);
68 
69  const BigInt s = m_group.multiply_mod_order(m_x, kr - m);
70 
71  // With overwhelming probability, a bug rather than actual zero r/s
72  if(r.is_zero() || s.is_zero())
73  throw Internal_Error("During ECGDSA signature generated zero r/s");
74 
75  return BigInt::encode_fixed_length_int_pair(r, s, m_group.get_order_bytes());
76  }
77 
78 /**
79 * ECGDSA verification operation
80 */
81 class ECGDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
82  {
83  public:
84 
85  ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa,
86  const std::string& emsa) :
87  PK_Ops::Verification_with_EMSA(emsa),
88  m_group(ecgdsa.domain()),
89  m_public_point(ecgdsa.public_point())
90  {
91  }
92 
93  size_t max_input_bits() const override { return m_group.get_order_bits(); }
94 
95  bool with_recovery() const override { return false; }
96 
97  bool verify(const uint8_t msg[], size_t msg_len,
98  const uint8_t sig[], size_t sig_len) override;
99  private:
100  const EC_Group m_group;
101  const PointGFp& m_public_point;
102  };
103 
104 bool ECGDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
105  const uint8_t sig[], size_t sig_len)
106  {
107  if(sig_len != m_group.get_order_bytes() * 2)
108  return false;
109 
110  const BigInt e(msg, msg_len, m_group.get_order_bits());
111 
112  const BigInt r(sig, sig_len / 2);
113  const BigInt s(sig + sig_len / 2, sig_len / 2);
114 
115  if(r <= 0 || r >= m_group.get_order() || s <= 0 || s >= m_group.get_order())
116  return false;
117 
118  const BigInt w = inverse_mod(r, m_group.get_order());
119 
120  const BigInt u1 = m_group.multiply_mod_order(e, w);
121  const BigInt u2 = m_group.multiply_mod_order(s, w);
122  const PointGFp R = m_group.point_multiply(u1, m_public_point, u2);
123 
124  if(R.is_zero())
125  return false;
126 
127  const BigInt v = m_group.mod_order(R.get_affine_x());
128  return (v == r);
129  }
130 
131 }
132 
133 std::unique_ptr<PK_Ops::Verification>
135  const std::string& provider) const
136  {
137  if(provider == "base" || provider.empty())
138  return std::unique_ptr<PK_Ops::Verification>(new ECGDSA_Verification_Operation(*this, params));
139  throw Provider_Not_Found(algo_name(), provider);
140  }
141 
142 std::unique_ptr<PK_Ops::Signature>
144  const std::string& params,
145  const std::string& provider) const
146  {
147  if(provider == "base" || provider.empty())
148  return std::unique_ptr<PK_Ops::Signature>(new ECGDSA_Signature_Operation(*this, params));
149  throw Provider_Not_Found(algo_name(), provider);
150  }
151 
152 }
std::string algo_name() const override
Definition: ecgdsa.h:44
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: ecgdsa.cpp:143
const PointGFp & public_point() const
Definition: ecc_key.h:57
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
Definition: ecgdsa.cpp:134
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, const std::string &padding)
Definition: keypair.cpp:49
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition: numthry.cpp:279
Definition: alg_id.cpp:13
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: ecgdsa.cpp:16
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:103