Botan 3.11.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,2024 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/ec_group.h>
12#include <botan/internal/keypair.h>
13#include <botan/internal/pk_ops_impl.h>
14
15namespace Botan {
16
17std::unique_ptr<Public_Key> ECGDSA_PrivateKey::public_key() const {
18 return std::make_unique<ECGDSA_PublicKey>(domain(), _public_ec_point());
19}
20
22 if(!EC_PrivateKey::check_key(rng, strong)) {
23 return false;
24 }
25
26 if(!strong) {
27 return true;
28 }
29
30 return KeyPair::signature_consistency_check(rng, *this, "SHA-256");
31}
32
33namespace {
34
35/**
36* ECGDSA signature operation
37*/
38class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_Hash {
39 public:
40 ECGDSA_Signature_Operation(const ECGDSA_PrivateKey& ecgdsa, std::string_view hash_fn) :
41 PK_Ops::Signature_with_Hash(hash_fn), m_group(ecgdsa.domain()), m_x(ecgdsa._private_key()) {}
42
43 std::vector<uint8_t> raw_sign(std::span<const uint8_t> msg, RandomNumberGenerator& rng) override;
44
45 size_t signature_length() const override { return 2 * m_group.get_order_bytes(); }
46
47 AlgorithmIdentifier algorithm_identifier() const override;
48
49 private:
50 const EC_Group m_group;
51 const EC_Scalar m_x;
52};
53
54AlgorithmIdentifier ECGDSA_Signature_Operation::algorithm_identifier() const {
55 const std::string full_name = "ECGDSA/" + hash_function();
56 const OID oid = OID::from_string(full_name);
57 return AlgorithmIdentifier(oid, AlgorithmIdentifier::USE_EMPTY_PARAM);
58}
59
60std::vector<uint8_t> ECGDSA_Signature_Operation::raw_sign(std::span<const uint8_t> msg, RandomNumberGenerator& rng) {
61 const auto m = EC_Scalar::from_bytes_with_trunc(m_group, msg);
62
63 const auto k = EC_Scalar::random(m_group, rng);
64
65 const auto r = EC_Scalar::gk_x_mod_order(k, rng);
66
67 const auto s = m_x * ((k * r) - m);
68
69 // With overwhelming probability, a bug rather than actual zero r/s
70 if(r.is_zero() || s.is_zero()) {
71 throw Internal_Error("During ECGDSA signature generated zero r/s");
72 }
73
74 return EC_Scalar::serialize_pair(r, s);
75}
76
77/**
78* ECGDSA verification operation
79*/
80class ECGDSA_Verification_Operation final : public PK_Ops::Verification_with_Hash {
81 public:
82 ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa, std::string_view padding) :
83 PK_Ops::Verification_with_Hash(padding), m_group(ecgdsa.domain()), m_gy_mul(ecgdsa._public_ec_point()) {}
84
85 ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa, const AlgorithmIdentifier& alg_id) :
86 PK_Ops::Verification_with_Hash(alg_id, "ECGDSA"),
87 m_group(ecgdsa.domain()),
88 m_gy_mul(ecgdsa._public_ec_point()) {}
89
90 bool verify(std::span<const uint8_t> msg, std::span<const uint8_t> sig) override;
91
92 private:
93 const EC_Group m_group;
94 const EC_Group::Mul2Table m_gy_mul;
95};
96
97bool ECGDSA_Verification_Operation::verify(std::span<const uint8_t> msg, std::span<const uint8_t> sig) {
98 if(auto rs = EC_Scalar::deserialize_pair(m_group, sig)) {
99 const auto& [r, s] = rs.value();
100
101 if(r.is_nonzero() && s.is_nonzero()) {
102 const auto m = EC_Scalar::from_bytes_with_trunc(m_group, msg);
103
104 const auto w = r.invert_vartime();
105
106 // Check if r == x_coord(g*w*m + y*w*s) % n
107 return m_gy_mul.mul2_vartime_x_mod_order_eq(r, w, m, s);
108 }
109 }
110
111 return false;
112}
113
114} // namespace
115
117 return domain().get_order_bytes();
118}
119
120std::unique_ptr<Private_Key> ECGDSA_PublicKey::generate_another(RandomNumberGenerator& rng) const {
121 return std::make_unique<ECGDSA_PrivateKey>(rng, domain());
122}
123
124std::unique_ptr<PK_Ops::Verification> ECGDSA_PublicKey::create_verification_op(std::string_view params,
125 std::string_view provider) const {
126 if(provider == "base" || provider.empty()) {
127 return std::make_unique<ECGDSA_Verification_Operation>(*this, params);
128 }
129 throw Provider_Not_Found(algo_name(), provider);
130}
131
132std::unique_ptr<PK_Ops::Verification> ECGDSA_PublicKey::create_x509_verification_op(
133 const AlgorithmIdentifier& signature_algorithm, std::string_view provider) const {
134 if(provider == "base" || provider.empty()) {
135 return std::make_unique<ECGDSA_Verification_Operation>(*this, signature_algorithm);
136 }
137
138 throw Provider_Not_Found(algo_name(), provider);
139}
140
141std::unique_ptr<PK_Ops::Signature> ECGDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
142 std::string_view params,
143 std::string_view provider) const {
144 if(provider == "base" || provider.empty()) {
145 return std::make_unique<ECGDSA_Signature_Operation>(*this, params);
146 }
147 throw Provider_Not_Found(algo_name(), provider);
148}
149
150} // namespace Botan
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ecgdsa.cpp:21
std::unique_ptr< Public_Key > public_key() const override
Definition ecgdsa.cpp:17
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
Definition ecgdsa.cpp:141
std::string algo_name() const override
Definition ecgdsa.h:48
std::optional< size_t > _signature_element_size_for_DER_encoding() const override
Definition ecgdsa.cpp:116
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
Definition ecgdsa.cpp:124
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
Definition ecgdsa.cpp:132
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
Definition ecgdsa.cpp:120
bool mul2_vartime_x_mod_order_eq(const EC_Scalar &v, const EC_Scalar &x, const EC_Scalar &y) const
Definition ec_group.cpp:843
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ecc_key.cpp:201
const EC_Group & domain() const
Definition ecc_key.cpp:64
const EC_AffinePoint & _public_ec_point() const
Definition ecc_key.cpp:76
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, std::string_view padding)
Definition keypair.cpp:49