3#include "../hmac/hmac.hpp"
4#include "barretenberg/common/serialize.hpp"
5#include "barretenberg/numeric/uint256/uint256.hpp"
10template <
typename Hash,
typename Fq,
typename Fr,
typename G1>
11signature construct_signature(
const std::string& message,
const key_pair<Fr, G1>& account)
16 std::vector<uint8_t> pkey_buffer;
17 write(pkey_buffer, account.private_key);
18 Fr k = crypto::get_unbiased_field_from_hmac<Hash, Fr>(message, pkey_buffer);
20 typename G1::affine_element R(G1::one * k);
21 Fq::serialize_to_buffer(R.x, &sig.r[0]);
23 std::vector<uint8_t> message_buffer;
24 std::copy(message.begin(), message.end(), std::back_inserter(message_buffer));
25 auto ev = Hash::hash(message_buffer);
27 Fr z = Fr::serialize_from_buffer(&ev[0]);
28 Fr r_fr = Fr::serialize_from_buffer(&sig.r[0]);
29 Fr s_fr = (z + r_fr * account.private_key) / k;
35 Fr::serialize_to_buffer(
Fr(s_uint256), &sig.s[0]);
45 bool y_parity =
uint256_t(R.y).get_bit(0);
46 bool recovery_bit = y_parity ^ is_s_low;
47 constexpr uint8_t offset = 27;
49 int value = offset + recovery_bit +
static_cast<uint8_t
>(2) * !is_r_finite;
50 ASSERT(value <= UINT8_MAX);
51 sig.v =
static_cast<uint8_t
>(value);
55template <
typename Hash,
typename Fq,
typename Fr,
typename G1>
56typename G1::affine_element recover_public_key(
const std::string& message,
const signature& sig)
58 using serialize::read;
64 const auto* r_buf = &sig.r[0];
65 const auto* s_buf = &sig.s[0];
66 const auto* v_buf = &sig.v;
72 if ((r_uint >= mod) || (s_uint >= mod)) {
73 throw_or_abort(
"r or s value exceeds the modulus");
75 if ((r_uint == 0) || (s_uint == 0)) {
76 throw_or_abort(
"r or s value is zero");
80 if (s_uint * 2 > mod) {
81 throw_or_abort(
"s value is not less than curve order by 2");
88 bool is_r_finite =
true;
90 if ((v_uint == 27) || (v_uint == 28)) {
92 }
else if ((v_uint == 29) || (v_uint == 30)) {
96 throw_or_abort(
"v value is not in {27, 28, 29, 30}");
103 auto uncompressed_points = G1::affine_element::from_compressed_unsafe(r_uint);
104 typename G1::affine_element point_R = uncompressed_points[!is_r_finite];
107 bool y_parity_R =
uint256_t(point_R.y).get_bit(0);
108 if ((v_uint & 1) ^ y_parity_R) {
109 point_R.y = -point_R.y;
113 std::vector<uint8_t> message_buffer;
114 std::copy(message.begin(), message.end(), std::back_inserter(message_buffer));
115 auto ev = Hash::hash(message_buffer);
116 Fr z = Fr::serialize_from_buffer(&ev[0]);
118 Fr r_inv = r.invert();
120 Fr u1 = -(z * r_inv);
123 typename G1::affine_element recovered_public_key(
typename G1::element(point_R) * u2 + G1::one * u1);
124 return recovered_public_key;
127template <
typename Hash,
typename Fq,
typename Fr,
typename G1>
128bool verify_signature(
const std::string& message,
const typename G1::affine_element& public_key,
const signature& sig)
130 using serialize::read;
134 if (!public_key.on_curve()) {
137 const auto* r_buf = &sig.r[0];
138 const auto* s_buf = &sig.s[0];
142 if ((r_uint >= mod) || (s_uint >= mod)) {
145 if ((r_uint == 0) || (s_uint == 0)) {
150 if (s_uint * 2 > mod) {
151 throw_or_abort(
"s value is not less than curve order by 2");
157 std::vector<uint8_t> message_buffer;
158 std::copy(message.begin(), message.end(), std::back_inserter(message_buffer));
159 auto ev = Hash::hash(message_buffer);
160 Fr z = Fr::serialize_from_buffer(&ev[0]);
162 Fr s_inv = s.invert();
167 typename G1::affine_element R(
typename G1::element(public_key) * u2 + G1::one * u1);
Definition: uint256.hpp:25