11#include "../hmac/hmac.hpp"
18template <
typename Hash,
typename Fq,
typename Fr,
typename G1>
24 Fr z = ecdsa_hash_message<Hash, Fr>(message);
27 std::vector<uint8_t> pkey_buffer;
29 Fr k = crypto::deterministic_nonce_rfc6979<Hash, Fr>(message, pkey_buffer);
33 typename G1::affine_element R(G1::one * k);
42 s = is_s_low ? s : -s;
57 bool recovery_id = is_s_low ? y_parity : !y_parity;
59 int value = is_r_finite ? ECDSA_RECOVERY_ID_OFFSET + recovery_id
60 : ECDSA_RECOVERY_ID_OFFSET + recovery_id + ECDSA_R_FINITENESS_OFFSET;
62 sig.
v =
static_cast<uint8_t
>(
value);
67template <
typename Hash,
typename Fq,
typename Fr,
typename G1>
71 using AffineElement = G1::affine_element;
79 const auto* r_buf = &sig.
r[0];
80 const auto* s_buf = &sig.
s[0];
81 const auto* v_buf = &sig.
v;
89 BB_ASSERT_LT(r_uint, mod,
"r value exceeds the modulus");
90 BB_ASSERT_LT(s_uint, mod,
"s value exceeds the modulus");
91 BB_ASSERT_LT(s_uint, (mod + 1) / 2,
"s value is not less than curve order by 2");
92 BB_ASSERT(r_uint != 0,
"r value is zero");
93 BB_ASSERT(s_uint != 0,
"s value is zero");
96 BB_ASSERT_GTE(v_uint, ECDSA_RECOVERY_ID_OFFSET,
"v value is too small");
97 BB_ASSERT_LTE(v_uint, ECDSA_RECOVERY_ID_OFFSET + 3,
"v value is too large");
98 bool is_r_finite = v_uint < ECDSA_RECOVERY_ID_OFFSET + 2;
99 v_uint -= ECDSA_RECOVERY_ID_OFFSET;
105 auto uncompressed_points = AffineElement::from_compressed_unsafe(r_uint);
106 AffineElement point_R = uncompressed_points[is_r_finite ? 0 : 1];
110 bool v_parity = v_uint & 1;
112 if ((v_parity && !y_parity_R) || (!v_parity && y_parity_R)) {
113 point_R.y = -point_R.y;
117 Fr z = ecdsa_hash_message<Hash, Fr>(message);
121 Fr u1 = -(z * r_inv);
124 AffineElement recovered_public_key(point_R * u2 + G1::one * u1);
125 return recovered_public_key;
128template <
typename Hash,
typename Fq,
typename Fr,
typename G1>
130 const typename G1::affine_element& public_key,
135 using AffineElement = G1::affine_element;
138 if ((!public_key.on_curve()) || (public_key.is_point_at_infinity())) {
147 const auto* r_buf = &sig.
r[0];
148 const auto* s_buf = &sig.
s[0];
154 vinfo(
"The r component of the signature exceeds the modulus of the scalar field of the curve.");
157 if (s_uint >= (mod + 1) / 2) {
158 vinfo(
"The s component of the signature exceeds (modulus + 1) / 2.");
162 vinfo(
"The r component of the signature is zero.");
166 vinfo(
"The s component of the signature is zero.");
171 Fr z = ecdsa_hash_message<Hash, Fr>(message);
182 AffineElement R = (G1::one * u1) + (
Element(public_key) * u2);
183 if (R.is_point_at_infinity()) {
184 vinfo(
"Result of the scalar multiplication is the point at infinity.");
198 static_assert(Hash::OUTPUT_SIZE <= 32,
"Hash output size is too large for our implementation of ECDSA.");
202 std::vector<uint8_t> message_buffer;
204 auto ev = Hash::hash(message_buffer);
206 if (Hash::OUTPUT_SIZE * 8 > MODULUS_BIT_LENGTH) {
207 const uint8_t* ptr = ev.data();
212 ev_uint = ev_uint >> (Hash::OUTPUT_SIZE * 8 - MODULUS_BIT_LENGTH);
215 uint8_t* ptr_write = ev.
data();
216 write(ptr_write, ev_uint);
#define BB_ASSERT(expression,...)
#define BB_ASSERT_GTE(left, right,...)
#define BB_ASSERT_LTE(left, right,...)
#define BB_ASSERT_LT(left, right,...)
constexpr bool get_bit(uint64_t bit_index) const
constexpr uint64_t get_msb() const
bb::curve::BN254::Element Element
G1::affine_element ecdsa_recover_public_key(const std::string &message, const ecdsa_signature &sig)
void read(B &it, SchnorrProofOfPossession< G1, Hash > &proof_of_possession)
void secure_erase(std::array< T, N > &buffer)
Fr ecdsa_hash_message(const std::string &message)
ecdsa_signature ecdsa_construct_signature(const std::string &message, const ecdsa_key_pair< Fr, G1 > &account)
Generate the ECDSA for the message using the provided account key pair and hash function.
void write(B &buf, SchnorrProofOfPossession< G1, Hash > const &proof_of_possession)
bool ecdsa_verify_signature(const std::string &message, const typename G1::affine_element &public_key, const ecdsa_signature &sig)
void secure_erase_bytes(void *ptr, size_t size)
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by MSGPACK_FIEL...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by MSGPACK_FIE...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::array< uint8_t, 32 > r
std::array< uint8_t, 32 > s
static constexpr uint256_t modulus
constexpr field invert() const noexcept
static field serialize_from_buffer(const uint8_t *buffer)
static void serialize_to_buffer(const field &value, uint8_t *buffer)