Botan 3.4.0
Crypto and TLS for C&
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
11#include <botan/reducer.h>
12#include <botan/internal/keypair.h>
13#include <botan/internal/pk_ops_impl.h>
14#include <botan/internal/point_mul.h>
15
16namespace Botan {
17
18std::unique_ptr<Public_Key> ECGDSA_PrivateKey::public_key() const {
19 return std::make_unique<ECGDSA_PublicKey>(domain(), public_point());
20}
21
23 if(!EC_PrivateKey::check_key(rng, strong)) {
24 return false;
25 }
26
27 if(!strong) {
28 return true;
29 }
30
31 return KeyPair::signature_consistency_check(rng, *this, "SHA-256");
32}
33
34namespace {
35
36/**
37* ECGDSA signature operation
38*/
39class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_Hash {
40 public:
41 ECGDSA_Signature_Operation(const ECGDSA_PrivateKey& ecgdsa, std::string_view emsa) :
42 PK_Ops::Signature_with_Hash(emsa), m_group(ecgdsa.domain()), m_x(ecgdsa.private_value()) {}
43
44 secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len, RandomNumberGenerator& rng) override;
45
46 size_t signature_length() const override { return 2 * m_group.get_order_bytes(); }
47
48 AlgorithmIdentifier algorithm_identifier() const override;
49
50 private:
51 const EC_Group m_group;
52 const BigInt m_x;
53 std::vector<BigInt> m_ws;
54};
55
56AlgorithmIdentifier ECGDSA_Signature_Operation::algorithm_identifier() const {
57 const std::string full_name = "ECGDSA/" + hash_function();
58 const OID oid = OID::from_string(full_name);
59 return AlgorithmIdentifier(oid, AlgorithmIdentifier::USE_EMPTY_PARAM);
60}
61
62secure_vector<uint8_t> ECGDSA_Signature_Operation::raw_sign(const uint8_t msg[],
63 size_t msg_len,
64 RandomNumberGenerator& rng) {
65 const BigInt m = BigInt::from_bytes_with_max_bits(msg, msg_len, m_group.get_order_bits());
66
67 const BigInt k = m_group.random_scalar(rng);
68
69 const BigInt r = m_group.mod_order(m_group.blinded_base_point_multiply_x(k, rng, m_ws));
70
71 const BigInt kr = m_group.multiply_mod_order(k, r);
72
73 const BigInt s = m_group.multiply_mod_order(m_x, kr - m);
74
75 // With overwhelming probability, a bug rather than actual zero r/s
76 if(r.is_zero() || s.is_zero()) {
77 throw Internal_Error("During ECGDSA signature generated zero r/s");
78 }
79
80 return BigInt::encode_fixed_length_int_pair(r, s, m_group.get_order_bytes());
81}
82
83/**
84* ECGDSA verification operation
85*/
86class ECGDSA_Verification_Operation final : public PK_Ops::Verification_with_Hash {
87 public:
88 ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa, std::string_view padding) :
89 PK_Ops::Verification_with_Hash(padding),
90 m_group(ecgdsa.domain()),
91 m_gy_mul(m_group.get_base_point(), ecgdsa.public_point()) {}
92
93 ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa, const AlgorithmIdentifier& alg_id) :
94 PK_Ops::Verification_with_Hash(alg_id, "ECGDSA"),
95 m_group(ecgdsa.domain()),
96 m_gy_mul(m_group.get_base_point(), ecgdsa.public_point()) {}
97
98 bool verify(const uint8_t msg[], size_t msg_len, const uint8_t sig[], size_t sig_len) override;
99
100 private:
101 const EC_Group m_group;
102 const EC_Point_Multi_Point_Precompute m_gy_mul;
103};
104
105bool ECGDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len, const uint8_t sig[], size_t sig_len) {
106 if(sig_len != m_group.get_order_bytes() * 2) {
107 return false;
108 }
109
110 const BigInt e = BigInt::from_bytes_with_max_bits(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
119 const BigInt w = m_group.inverse_mod_order(r);
120
121 const BigInt u1 = m_group.multiply_mod_order(e, w);
122 const BigInt u2 = m_group.multiply_mod_order(s, w);
123 const EC_Point R = m_gy_mul.multi_exp(u1, u2);
124
125 if(R.is_zero()) {
126 return false;
127 }
128
129 const BigInt v = m_group.mod_order(R.get_affine_x());
130 return (v == r);
131}
132
133} // namespace
134
135std::unique_ptr<Private_Key> ECGDSA_PublicKey::generate_another(RandomNumberGenerator& rng) const {
136 return std::make_unique<ECGDSA_PrivateKey>(rng, domain());
137}
138
139std::unique_ptr<PK_Ops::Verification> ECGDSA_PublicKey::create_verification_op(std::string_view params,
140 std::string_view provider) const {
141 if(provider == "base" || provider.empty()) {
142 return std::make_unique<ECGDSA_Verification_Operation>(*this, params);
143 }
144 throw Provider_Not_Found(algo_name(), provider);
145}
146
147std::unique_ptr<PK_Ops::Verification> ECGDSA_PublicKey::create_x509_verification_op(
148 const AlgorithmIdentifier& signature_algorithm, std::string_view provider) const {
149 if(provider == "base" || provider.empty()) {
150 return std::make_unique<ECGDSA_Verification_Operation>(*this, signature_algorithm);
151 }
152
153 throw Provider_Not_Found(algo_name(), provider);
154}
155
156std::unique_ptr<PK_Ops::Signature> ECGDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
157 std::string_view params,
158 std::string_view provider) const {
159 if(provider == "base" || provider.empty()) {
160 return std::make_unique<ECGDSA_Signature_Operation>(*this, params);
161 }
162 throw Provider_Not_Found(algo_name(), provider);
163}
164
165} // namespace Botan
std::unique_ptr< Public_Key > public_key() const override
Definition ecgdsa.cpp:18
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition ecgdsa.cpp:22
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
Definition ecgdsa.cpp:156
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
Definition ecgdsa.cpp:139
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
Definition ecgdsa.cpp:147
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
Definition ecgdsa.cpp:135
BigInt blinded_base_point_multiply_x(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition ec_group.cpp:581
BigInt mod_order(const BigInt &x) const
Definition ec_group.cpp:524
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
Definition ec_group.cpp:532
const BigInt & get_order() const
Definition ec_group.cpp:508
BigInt inverse_mod_order(const BigInt &x) const
Definition ec_group.cpp:540
BigInt random_scalar(RandomNumberGenerator &rng) const
Definition ec_group.cpp:592
size_t get_order_bits() const
Definition ec_group.cpp:484
size_t get_order_bytes() const
Definition ec_group.cpp:488
EC_Point multi_exp(const BigInt &k1, const BigInt &k2) const
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ecc_key.cpp:161
const EC_Group & domain() const
Definition ecc_key.h:54
const EC_Point & public_point() const
Definition ecc_key.h:40
int(* final)(unsigned char *, CTX *)
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, std::string_view padding)
Definition keypair.cpp:49