Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ecdsa_constraints.test.cpp
Go to the documentation of this file.
2#include "acir_format.hpp"
9
10#include <algorithm>
11#include <gtest/gtest.h>
12#include <vector>
13
14using namespace bb;
15using namespace bb::crypto;
16using namespace acir_format;
17
18template <class Curve> class EcdsaTestingFunctions {
19 public:
20 using Builder = Curve::Builder;
21 using FrNative = Curve::fr;
22 using FqNative = Curve::fq;
23 using G1Native = Curve::g1;
25
27 public:
28 enum class Target : uint8_t {
29 None,
30 HashIsNotAByteArray, // Set one element of the hash > 255
31 ZeroR, // Set R=0 (tests ECDSA validation)
32 ZeroS, // Set S=0 (tests ECDSA validation)
33 HighS, // Set S=high (tests malleability protection)
34 P, // Invalidate public key
35 Result // Invalid signature with claimed valid result
36 };
37
43
44 static std::vector<std::string> get_labels()
45 {
46 return { "None", "Hash is not a byte array", "Zero R", "Zero S", "High S", "Public key", "Result" };
47 }
48 };
49
50 // Reproducible test
51 static constexpr FrNative private_key =
52 FrNative("0xd67abee717b3fc725adf59e2cc8cd916435c348b277dd814a34e3ceb279436c2");
53
55
57 AcirConstraint ecdsa_constraints,
58 WitnessVector witness_values,
59 const InvalidWitness::Target& invalid_witness_target)
60 {
61 // For most ECDSA invalidation cases, we set result=0 to ensure that the failure mode caught by the test is
62 // specific to the particular case being tested, not just simple verification failure.
63 // For the "Result" case we test the mismatch between actual and claimed result.
64 if (invalid_witness_target != InvalidWitness::Target::None &&
65 invalid_witness_target != InvalidWitness::Target::Result) {
66 witness_values[ecdsa_constraints.result] = bb::fr(0);
67 }
68
69 switch (invalid_witness_target) {
71 // Set all bytes of hash to 256 (invalid as it doesn't fit in one byte)
72 for (size_t idx = 0; idx < 32; idx++) {
73 witness_values[ecdsa_constraints.hashed_message[idx]] = bb::fr(256);
74 };
75 break;
77 // Set r = 0 (invalid ECDSA signature component)
78 for (size_t idx = 0; idx < 32; idx++) {
79 witness_values[ecdsa_constraints.signature[idx]] = bb::fr(0);
80 };
81 break;
83 // Set s = 0 (tests ECDSA validation: s must be non-zero)
84 for (size_t idx = 32; idx < 64; idx++) {
85 witness_values[ecdsa_constraints.signature[idx]] = bb::fr(0);
86 };
87 break;
89 // Set s = high value (tests signature malleability protection)
90 for (size_t idx = 32; idx < 64; idx++) {
91 witness_values[ecdsa_constraints.signature[idx]] = bb::fr(255);
92 };
93 break;
95 // Invalidate public key
96 witness_values[ecdsa_constraints.pub_x_indices[0]] += bb::fr(1);
97 break;
99 // Test enforcement of verification result: tamper signature but claim it's valid
100 witness_values[ecdsa_constraints.signature[31]] = bb::fr(0);
101 witness_values[ecdsa_constraints.result] = bb::fr(1);
102 break;
104 break;
105 }
106
107 return { ecdsa_constraints, witness_values };
108 }
109
113 static void generate_constraints(EcdsaConstraint& ecdsa_constraint, WitnessVector& witness_values)
114 {
115 std::string message_string = "Instructions unclear, ask again later.";
116
117 // Hash the message
118 std::vector<uint8_t> message_buffer(message_string.begin(), message_string.end());
119 std::array<uint8_t, 32> hashed_message = Sha256Hasher::hash(message_buffer);
120
121 // Generate ECDSA key pair
123 account.private_key = private_key;
124 account.public_key = G1Native::one * account.private_key;
125
126 // Generate signature
127 ecdsa_signature signature =
128 ecdsa_construct_signature<Sha256Hasher, FqNative, FrNative, G1Native>(message_string, account);
129
130 // Serialize public key coordinates into bytes
131 std::array<uint8_t, 32> buffer_x;
132 std::array<uint8_t, 32> buffer_y;
133 FqNative::serialize_to_buffer(account.public_key.x, &buffer_x[0]);
134 FqNative::serialize_to_buffer(account.public_key.y, &buffer_y[0]);
135
136 // Create witness indices and witnesses
137 std::array<uint32_t, 32> hashed_message_indices =
138 add_to_witness_and_track_indices<std::span<uint8_t>, 32>(witness_values, std::span(hashed_message));
139
140 std::array<uint32_t, 32> pub_x_indices =
141 add_to_witness_and_track_indices<std::span<uint8_t>, 32>(witness_values, std::span(buffer_x));
142
143 std::array<uint32_t, 32> pub_y_indices =
144 add_to_witness_and_track_indices<std::span<uint8_t>, 32>(witness_values, std::span(buffer_y));
145
146 std::array<uint32_t, 32> r_indices =
147 add_to_witness_and_track_indices<std::span<uint8_t>, 32>(witness_values, std::span(signature.r));
148
149 std::array<uint32_t, 32> s_indices =
150 add_to_witness_and_track_indices<std::span<uint8_t>, 32>(witness_values, std::span(signature.s));
151
152 uint32_t result_index = add_to_witness_and_track_indices(witness_values, bb::fr(1));
153
154 uint32_t predicate_index = add_to_witness_and_track_indices(witness_values, bb::fr(1));
155
156 // Restructure vectors into array
157 std::array<uint32_t, 64> signature_indices;
158 std::ranges::copy(r_indices, signature_indices.begin());
159 std::ranges::copy(s_indices, signature_indices.begin() + 32);
160
161 ecdsa_constraint = EcdsaConstraint{ .type = Curve::type,
162 .hashed_message = hashed_message_indices,
163 .signature = signature_indices,
164 .pub_x_indices = pub_x_indices,
165 .pub_y_indices = pub_y_indices,
166 .predicate = WitnessOrConstant<bb::fr>::from_index(predicate_index),
167 .result = result_index };
168 }
169};
170
171template <class Curve>
172class EcdsaConstraintsTest : public ::testing::Test, public TestClassWithPredicate<EcdsaTestingFunctions<Curve>> {
173 protected:
175};
176
177using CurveTypes = testing::Types<stdlib::secp256k1<UltraCircuitBuilder>,
181
183
184TYPED_TEST(EcdsaConstraintsTest, GenerateVKFromConstraints)
185{
186 using Flavor =
188 TestFixture::template test_vk_independence<Flavor>();
189}
190
192{
194 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
195}
196
198{
200 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
201}
202
204{
206 TestFixture::test_witness_false();
207}
208
210{
211 // This test is equal to WitnessFalse but also checks that each configuration would have failed if the
212 // predicate were witness true. It can be useful for debugging.
214 TestFixture::test_witness_false_slow();
215}
216
218{
220 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
221}
#define BB_DISABLE_ASSERTS()
Definition assert.hpp:33
static constexpr FrNative private_key
static void generate_constraints(EcdsaConstraint &ecdsa_constraint, WitnessVector &witness_values)
Generate valid ECDSA constraint with witness predicate equal to true.
static ProgramMetadata generate_metadata()
static std::pair< AcirConstraint, WitnessVector > invalidate_witness(AcirConstraint ecdsa_constraints, WitnessVector witness_values, const InvalidWitness::Target &invalid_witness_target)
Test class for ACIR constraints that contain a predicate.
std::vector< bb::fr > WitnessVector
std::vector< uint32_t > add_to_witness_and_track_indices(std::vector< bb::fr > &witness, const T &input)
Append values to a witness vector and track their indices.
Definition utils.hpp:90
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
TYPED_TEST_SUITE(BoomerangRecursiveVerifierTest, Flavors)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
field< Bn254FrParams > fr
Definition fr.hpp:174
::testing::Types< curve::BN254, curve::Grumpkin > CurveTypes
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static std::vector< std::string > get_labels()
std::array< uint32_t, 32 > pub_x_indices
std::array< uint32_t, 32 > hashed_message
std::array< uint32_t, 64 > signature
Metadata required to create a circuit.
static WitnessOrConstant from_index(uint32_t index)
static auto hash(const B &message)
Definition hashers.hpp:36
G1::affine_element public_key
Definition ecdsa.hpp:20
std::array< uint8_t, 32 > r
Definition ecdsa.hpp:26
std::array< uint8_t, 32 > s
Definition ecdsa.hpp:27