Botan  2.1.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 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/ecgdsa.h>
9 #include <botan/keypair.h>
10 #include <botan/reducer.h>
11 #include <botan/internal/pk_ops_impl.h>
12 
13 namespace Botan {
14 
16  bool strong) const
17  {
18  if(!public_point().on_the_curve())
19  return false;
20 
21  if(!strong)
22  return true;
23 
24  return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
25  }
26 
27 namespace {
28 
29 /**
30 * ECGDSA signature operation
31 */
32 class ECGDSA_Signature_Operation : public PK_Ops::Signature_with_EMSA
33  {
34  public:
35 
36  ECGDSA_Signature_Operation(const ECGDSA_PrivateKey& ecgdsa,
37  const std::string& emsa) :
38  PK_Ops::Signature_with_EMSA(emsa),
39  m_order(ecgdsa.domain().get_order()),
40  m_base_point(ecgdsa.domain().get_base_point(), m_order),
41  m_x(ecgdsa.private_value()),
43  {
44  }
45 
46  secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
47  RandomNumberGenerator& rng) override;
48 
49  size_t max_input_bits() const override { return m_order.bits(); }
50 
51  private:
52  const BigInt& m_order;
53  Blinded_Point_Multiply m_base_point;
54  const BigInt& m_x;
55  Modular_Reducer m_mod_order;
56  };
57 
58 secure_vector<uint8_t>
59 ECGDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
60  RandomNumberGenerator& rng)
61  {
62  const BigInt m(msg, msg_len);
63 
64  BigInt k = BigInt::random_integer(rng, 1, m_order);
65 
66  const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng);
67  const BigInt r = m_mod_order.reduce(k_times_P.get_affine_x());
68  const BigInt s = m_mod_order.multiply(m_x, mul_sub(k, r, m));
69 
70  // With overwhelming probability, a bug rather than actual zero r/s
71  BOTAN_ASSERT(s != 0, "invalid s");
72  BOTAN_ASSERT(r != 0, "invalid r");
73 
75  }
76 
77 /**
78 * ECGDSA verification operation
79 */
80 class ECGDSA_Verification_Operation : public PK_Ops::Verification_with_EMSA
81  {
82  public:
83 
84  ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa,
85  const std::string& emsa) :
86  PK_Ops::Verification_with_EMSA(emsa),
87  m_base_point(ecgdsa.domain().get_base_point()),
88  m_public_point(ecgdsa.public_point()),
89  m_order(ecgdsa.domain().get_order()),
91  {
92  }
93 
94  size_t max_input_bits() const override { return m_order.bits(); }
95 
96  bool with_recovery() const override { return false; }
97 
98  bool verify(const uint8_t msg[], size_t msg_len,
99  const uint8_t sig[], size_t sig_len) override;
100  private:
101  const PointGFp& m_base_point;
102  const PointGFp& m_public_point;
103  const BigInt& m_order;
104  // FIXME: should be offered by curve
105  Modular_Reducer m_mod_order;
106  };
107 
108 bool ECGDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
109  const uint8_t sig[], size_t sig_len)
110  {
111  if(sig_len != m_order.bytes()*2)
112  return false;
113 
114  BigInt e(msg, msg_len);
115 
116  BigInt r(sig, sig_len / 2);
117  BigInt s(sig + sig_len / 2, sig_len / 2);
118 
119  if(r <= 0 || r >= m_order || s <= 0 || s >= m_order)
120  return false;
121 
122  BigInt w = inverse_mod(r, m_order);
123 
124  const BigInt u1 = m_mod_order.reduce(e * w);
125  const BigInt u2 = m_mod_order.reduce(s * w);
126  const PointGFp R = multi_exponentiate(m_base_point, u1, m_public_point, u2);
127 
128  if(R.is_zero())
129  return false;
130 
131  const BigInt v = m_mod_order.reduce(R.get_affine_x());
132  return (v == r);
133  }
134 
135 }
136 
137 std::unique_ptr<PK_Ops::Verification>
139  const std::string& provider) const
140  {
141  if(provider == "base" || provider.empty())
142  return std::unique_ptr<PK_Ops::Verification>(new ECGDSA_Verification_Operation(*this, params));
143  throw Provider_Not_Found(algo_name(), provider);
144  }
145 
146 std::unique_ptr<PK_Ops::Signature>
148  const std::string& params,
149  const std::string& provider) const
150  {
151  if(provider == "base" || provider.empty())
152  return std::unique_ptr<PK_Ops::Signature>(new ECGDSA_Signature_Operation(*this, params));
153  throw Provider_Not_Found(algo_name(), provider);
154  }
155 
156 }
std::string algo_name() const override
Definition: ecgdsa.h:44
Modular_Reducer m_mod_order
Definition: ecgdsa.cpp:55
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: ecgdsa.cpp:147
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition: big_rand.cpp:45
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
Definition: ecgdsa.cpp:138
const PointGFp & public_point() const
Definition: ecc_key.h:58
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
Blinded_Point_Multiply m_base_point
Definition: ecgdsa.cpp:53
const BigInt & m_x
Definition: ecgdsa.cpp:54
const BigInt & m_order
Definition: ecgdsa.cpp:52
BigInt multiply(const BigInt &x, const BigInt &y) const
Definition: reducer.h:31
PointGFp blinded_multiply(const BigInt &scalar, RandomNumberGenerator &rng)
Definition: point_gfp.cpp:335
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, const std::string &padding)
Definition: keypair.cpp:48
Definition: alg_id.cpp:13
BigInt reduce(const BigInt &x) const
Definition: reducer.cpp:32
const PointGFp & m_public_point
Definition: ecgdsa.cpp:102
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition: numthry.cpp:276
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: ecgdsa.cpp:15
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:103
PointGFp multi_exponentiate(const PointGFp &p1, const BigInt &z1, const PointGFp &p2, const BigInt &z2)
Definition: point_gfp.cpp:248
BigInt mul_sub(const BigInt &a, const BigInt &b, const BigInt &c)
Definition: mp_numth.cpp:71
size_t bytes() const
Definition: bigint.cpp:176