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);
34 typename G1::affine_element R(
typename G1::element(G1::one).mul_const_time(k));
43 s = is_s_low ? s : -s;
58 bool recovery_id = is_s_low ? y_parity : !y_parity;
60 int value = is_r_finite ? ECDSA_RECOVERY_ID_OFFSET + recovery_id
61 : ECDSA_RECOVERY_ID_OFFSET + recovery_id + ECDSA_R_FINITENESS_OFFSET;
63 sig.
v =
static_cast<uint8_t
>(
value);
68template <
typename Hash,
typename Fq,
typename Fr,
typename G1>
72 using AffineElement = G1::affine_element;
80 const auto* r_buf = &sig.
r[0];
81 const auto* s_buf = &sig.
s[0];
82 const auto* v_buf = &sig.
v;
90 BB_ASSERT_LT(r_uint, mod,
"r value exceeds the modulus");
91 BB_ASSERT_LT(s_uint, mod,
"s value exceeds the modulus");
92 BB_ASSERT_LT(s_uint, (mod + 1) / 2,
"s value is not less than curve order by 2");
93 BB_ASSERT(r_uint != 0,
"r value is zero");
94 BB_ASSERT(s_uint != 0,
"s value is zero");
97 BB_ASSERT_GTE(v_uint, ECDSA_RECOVERY_ID_OFFSET,
"v value is too small");
98 BB_ASSERT_LTE(v_uint, ECDSA_RECOVERY_ID_OFFSET + 3,
"v value is too large");
99 bool is_r_finite = v_uint < ECDSA_RECOVERY_ID_OFFSET + 2;
100 v_uint -= ECDSA_RECOVERY_ID_OFFSET;
106 auto uncompressed_points = AffineElement::from_compressed_unsafe(r_uint);
107 AffineElement point_R = uncompressed_points[is_r_finite ? 0 : 1];
111 bool v_parity = v_uint & 1;
113 if ((v_parity && !y_parity_R) || (!v_parity && y_parity_R)) {
114 point_R.y = -point_R.y;
118 Fr z = ecdsa_hash_message<Hash, Fr>(message);
122 Fr u1 = -(z * r_inv);
125 AffineElement recovered_public_key(point_R * u2 + G1::one * u1);
126 return recovered_public_key;
129template <
typename Hash,
typename Fq,
typename Fr,
typename G1>
131 const typename G1::affine_element& public_key,
136 using AffineElement = G1::affine_element;
139 if ((!public_key.on_curve()) || (public_key.is_point_at_infinity())) {
148 const auto* r_buf = &sig.
r[0];
149 const auto* s_buf = &sig.
s[0];
155 vinfo(
"The r component of the signature exceeds the modulus of the scalar field of the curve.");
158 if (s_uint >= (mod + 1) / 2) {
159 vinfo(
"The s component of the signature exceeds (modulus + 1) / 2.");
163 vinfo(
"The r component of the signature is zero.");
167 vinfo(
"The s component of the signature is zero.");
172 Fr z = ecdsa_hash_message<Hash, Fr>(message);
183 AffineElement R = (G1::one * u1) + (
Element(public_key) * u2);
184 if (R.is_point_at_infinity()) {
185 vinfo(
"Result of the scalar multiplication is the point at infinity.");
199 static_assert(Hash::OUTPUT_SIZE <= 32,
"Hash output size is too large for our implementation of ECDSA.");
203 std::vector<uint8_t> message_buffer;
205 auto ev = Hash::hash(message_buffer);
207 if (Hash::OUTPUT_SIZE * 8 > MODULUS_BIT_LENGTH) {
208 const uint8_t* ptr = ev.data();
213 ev_uint = ev_uint >> (Hash::OUTPUT_SIZE * 8 - MODULUS_BIT_LENGTH);
216 uint8_t* ptr_write = ev.
data();
217 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 secure_erase(std::array< T, N > &buffer)
void write(B &buf, schnorr_key_pair< grumpkin::fr, grumpkin::g1 > const &keypair)
void read(B &it, schnorr_key_pair< grumpkin::fr, grumpkin::g1 > &keypair)
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.
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 SERIALIZATIO...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by SERIALIZATI...
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)