82 BB_ASSERT_EQ(
builder !=
nullptr,
true,
"At least one of the inputs should be non-constant.");
90 bool_ct is_x_less_than_modulus = public_key.x().is_less_than(
91 Fq::modulus,
"ECDSA input validation: x coordinate of the public key bigger than the base field modulus.");
92 bool_ct is_y_less_than_modulus = public_key.y().is_less_than(
93 Fq::modulus,
"ECDSA input validation: y coordinate of the public key bigger than the base field modulus.");
96 bool_ct is_point_at_infinity = public_key.is_point_at_infinity();
102 typename Curve::AffineElementNative native_double_generator(Curve::GroupNative::one + Curve::GroupNative::one);
103 G1 double_generator(
Fq(native_double_generator.x),
Fq(native_double_generator.y),
false);
104 G1 corrected_public_key = G1::conditional_assign(
105 is_point_at_infinity || !is_x_less_than_modulus || !is_y_less_than_modulus, double_generator, public_key);
107 corrected_public_key.validate_on_curve(
108 "ECDSA input validation: the public key is not a point on the elliptic curve.",
false) ==
Fq::zero();
112 bool_ct is_r_in_range = r.is_less_than(
113 Fr::modulus,
"ECDSA input validation: the r component of the signature is bigger than Fr::modulus.");
114 bool_ct is_r_zero = r ==
Fr::zero();
118 bool_ct is_s_in_range =
120 "ECDSA input validation: the s component of the signature is bigger than (Fr::modulus + 1)/2.");
121 bool_ct is_s_zero = s ==
Fr::zero();
125 Fr corrected_s = Fr::conditional_assign(is_s_zero,
Fr::one(), s);
127 Fr u1 = z.div_without_denominator_check(corrected_s);
128 Fr u2 = r.div_without_denominator_check(corrected_s);
131 bool_ct is_u2_acceptable = bool_ct(
true);
135 result = G1::secp256k1_ecdsa_mul(corrected_public_key, u1, u2);
139 G1 fake_glv_pubkey = G1::conditional_assign(!is_point_on_curve, double_generator, corrected_public_key);
142 const auto mul_out = G1::secp256r1_ecdsa_mul(fake_glv_pubkey, u1, u2);
144 is_u2_acceptable = mul_out.u2_is_acceptable;
147 { G1::one(
builder), corrected_public_key }, { u1, u2 }, 0,
false);
151 bool_ct result_is_infinity =
result.is_point_at_infinity();
154 result.x().reduce_mod_target_modulus();
157 Fr result_x_mod_r = Fr::unsafe_construct_from_limbs(
result.x().get_limb(0).element,
158 result.x().get_limb(1).element,
159 result.x().get_limb(2).element,
160 result.x().get_limb(3).element);
162 for (
size_t idx = 0; idx < 4; idx++) {
163 result_x_mod_r.set_limb_max(idx,
result.x().get_limb(idx).maximum_value);
167 bool_ct x_matches = result_x_mod_r == r;
168 bool_ct is_signature_valid = x_matches && !is_point_at_infinity && !result_is_infinity && is_r_in_range &&
169 !is_r_zero && is_s_in_range && !is_s_zero && is_point_on_curve &&
170 is_x_less_than_modulus && is_y_less_than_modulus && is_u2_acceptable;
173 if (is_signature_valid.get_value()) {
174 vinfo(
"ECDSA signature verification succeeded.");
176 vinfo(
"ECDSA signature verification failed");
179 return is_signature_valid;
194 using FrNative =
typename Curve::ScalarFieldNative;
195 using FqNative =
typename Curve::BaseFieldNative;
196 using G1Native =
typename Curve::GroupNative;
203 std::string message_string =
"Instructions unclear, ask again later.";
206 for (
size_t i = 0; i < num_iterations; i++) {
212 crypto::ecdsa_construct_signature<crypto::Sha256Hasher, FqNative, FrNative, G1Native>(message_string,
215 bool native_verification = crypto::ecdsa_verify_signature<crypto::Sha256Hasher, FqNative, FrNative, G1Native>(
216 message_string, account.
public_key, signature);
217 BB_ASSERT_EQ(native_verification,
true,
"Native ECDSA verification failed while generating test circuit.");
219 std::vector<uint8_t> rr(signature.
r.begin(), signature.
r.end());
220 std::vector<uint8_t> ss(signature.
s.begin(), signature.
s.end());
227 auto hash_arr =
crypto::sha256(std::vector<uint8_t>(message_string.begin(), message_string.end()));
232 stdlib::ecdsa_verify_signature<Builder, Curve, Fq, Fr, G1>(hashed_message, public_key, sig);
bool_t< Builder > ecdsa_verify_signature(const stdlib::byte_array< Builder > &hashed_message, const G1 &public_key, const ecdsa_signature< Builder > &sig)
Verify ECDSA signature. Returns bool_t(true/false) depending on whether the signature is valid or not...