9#include <botan/ecgdsa.h>
11#include <botan/internal/keypair.h>
12#include <botan/internal/pk_ops_impl.h>
39 ECGDSA_Signature_Operation(
const ECGDSA_PrivateKey& ecgdsa, std::string_view hash_fn) :
40 PK_Ops::Signature_with_Hash(hash_fn), m_group(ecgdsa.domain()), m_x(ecgdsa._private_key()) {}
42 std::vector<uint8_t> raw_sign(std::span<const uint8_t> msg, RandomNumberGenerator& rng)
override;
44 size_t signature_length()
const override {
return 2 * m_group.get_order_bytes(); }
46 AlgorithmIdentifier algorithm_identifier()
const override;
49 const EC_Group m_group;
54 const std::string full_name =
"ECGDSA/" + hash_function();
55 const OID oid = OID::from_string(full_name);
56 return AlgorithmIdentifier(oid, AlgorithmIdentifier::USE_EMPTY_PARAM);
59std::vector<uint8_t> ECGDSA_Signature_Operation::raw_sign(std::span<const uint8_t> msg, RandomNumberGenerator& rng) {
60 const auto m = EC_Scalar::from_bytes_with_trunc(m_group, msg);
62 const auto k = EC_Scalar::random(m_group, rng);
64 const auto r = EC_Scalar::gk_x_mod_order(k, rng);
66 const auto s = m_x * ((k * r) - m);
69 if(r.is_zero() || s.is_zero()) {
70 throw Internal_Error(
"During ECGDSA signature generated zero r/s");
73 return EC_Scalar::serialize_pair(r, s);
79class ECGDSA_Verification_Operation final :
public PK_Ops::Verification_with_Hash {
81 ECGDSA_Verification_Operation(
const ECGDSA_PublicKey& ecgdsa, std::string_view padding) :
82 PK_Ops::Verification_with_Hash(padding), m_group(ecgdsa.domain()), m_gy_mul(ecgdsa._public_ec_point()) {}
84 ECGDSA_Verification_Operation(
const ECGDSA_PublicKey& ecgdsa,
const AlgorithmIdentifier& alg_id) :
85 PK_Ops::Verification_with_Hash(alg_id,
"ECGDSA"),
86 m_group(ecgdsa.domain()),
87 m_gy_mul(ecgdsa._public_ec_point()) {}
89 bool verify(std::span<const uint8_t> msg, std::span<const uint8_t> sig)
override;
92 const EC_Group m_group;
93 const EC_Group::Mul2Table m_gy_mul;
96bool ECGDSA_Verification_Operation::verify(std::span<const uint8_t> msg, std::span<const uint8_t> sig) {
97 if(
auto rs = EC_Scalar::deserialize_pair(m_group, sig)) {
98 const auto& [r, s] = rs.value();
100 if(r.is_nonzero() && s.is_nonzero()) {
101 const auto m = EC_Scalar::from_bytes_with_trunc(m_group, msg);
103 const auto w = r.invert_vartime();
116 return std::make_unique<ECGDSA_PrivateKey>(rng,
domain());
120 std::string_view provider)
const {
121 if(provider ==
"base" || provider.empty()) {
122 return std::make_unique<ECGDSA_Verification_Operation>(*
this, params);
129 if(provider ==
"base" || provider.empty()) {
130 return std::make_unique<ECGDSA_Verification_Operation>(*
this, signature_algorithm);
137 std::string_view params,
138 std::string_view provider)
const {
139 if(provider ==
"base" || provider.empty()) {
140 return std::make_unique<ECGDSA_Signature_Operation>(*
this, params);
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::unique_ptr< Public_Key > public_key() const override
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
std::string algo_name() const override
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
bool mul2_vartime_x_mod_order_eq(const EC_Scalar &v, const EC_Scalar &x, const EC_Scalar &y) const
bool check_key(RandomNumberGenerator &rng, bool strong) const override
const EC_Group & domain() const
const EC_AffinePoint & _public_ec_point() const
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, std::string_view padding)