diff --git a/cpp/.aztec-packages-commit b/cpp/.aztec-packages-commit index 656b947ce1..8b25206ff9 100644 --- a/cpp/.aztec-packages-commit +++ b/cpp/.aztec-packages-commit @@ -1 +1 @@ -3e16992198189112739e3710860e7d7717366108 \ No newline at end of file +master \ No newline at end of file diff --git a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.test.cpp b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.test.cpp index 2e09f9ed98..27205d7bd5 100644 --- a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.test.cpp +++ b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.test.cpp @@ -1,6 +1,7 @@ #include "../../primitives/bigfield/bigfield.hpp" #include "../../primitives/biggroup/biggroup.hpp" #include "../../primitives/curves/secp256k1.hpp" +#include "../../primitives/curves/secp256r1.hpp" #include "ecdsa.hpp" #include "barretenberg/crypto/ecdsa/ecdsa.hpp" #include "barretenberg/common/test.hpp" @@ -11,6 +12,7 @@ using namespace proof_system::plonk; namespace test_stdlib_ecdsa { using Composer = proof_system::UltraCircuitBuilder; using curve = stdlib::secp256k1; +using curveR1 = stdlib::secp256r1; TEST(stdlib_ecdsa, verify_signature) { @@ -55,6 +57,49 @@ TEST(stdlib_ecdsa, verify_signature) EXPECT_EQ(proof_result, true); } +TEST(stdlib_ecdsa, verify_r1_signature) +{ + Composer composer = Composer(); + + std::string message_string = "Instructions unclear, ask again later."; + + crypto::ecdsa::key_pair account; + account.private_key = curveR1::fr::random_element(); + account.public_key = curveR1::g1::one * account.private_key; + + crypto::ecdsa::signature signature = + crypto::ecdsa::construct_signature(message_string, + account); + + bool first_result = crypto::ecdsa::verify_signature( + message_string, account.public_key, signature); + EXPECT_EQ(first_result, true); + + curveR1::g1_bigfr_ct public_key = curveR1::g1_bigfr_ct::from_witness(&composer, account.public_key); + + std::vector rr(signature.r.begin(), signature.r.end()); + std::vector ss(signature.s.begin(), signature.s.end()); + uint8_t vv = signature.v; + + stdlib::ecdsa::signature sig{ curveR1::byte_array_ct(&composer, rr), + curveR1::byte_array_ct(&composer, ss), + stdlib::uint8(&composer, vv) }; + + curveR1::byte_array_ct message(&composer, message_string); + + curveR1::bool_ct signature_result = + stdlib::ecdsa::verify_signature( + message, public_key, sig); + + EXPECT_EQ(signature_result.get_value(), true); + + std::cerr << "composer gates = " << composer.get_num_gates() << std::endl; + benchmark_info( + Composer::NAME_STRING, "ECDSA", "Signature Verification Test", "Gate Count", composer.get_num_gates()); + bool proof_result = composer.check_circuit(); + EXPECT_EQ(proof_result, true); +} + TEST(stdlib_ecdsa, verify_signature_noassert_succeed) { Composer composer = Composer(); diff --git a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp index b902228ecf..7e709ff12d 100644 --- a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp +++ b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp @@ -81,11 +81,13 @@ bool_t verify_signature(const stdlib::byte_array& message, Fr u1 = z / s; Fr u2 = r / s; + public_key.validate_on_curve(); + G1 result; // TODO(Cody): Having Plookup should not determine which curve is used. - if constexpr (HasPlookup) { - ASSERT(Curve::type == proof_system::CurveType::SECP256K1); - public_key.validate_on_curve(); + // Use special plookup secp256k1 ECDSA mul if available (this relies on k1 endomorphism, and cannot be used for + // other curves) + if constexpr (HasPlookup && Curve::type == proof_system::CurveType::SECP256K1) { result = G1::secp256k1_ecdsa_mul(public_key, u1, u2); } else { result = G1::batch_mul({ G1::one(ctx), public_key }, { u1, u2 }); @@ -155,10 +157,12 @@ bool_t verify_signature_prehashed_message_noassert(const stdlib::byte_ Fr u1 = z / s; Fr u2 = r / s; + public_key.validate_on_curve(); + G1 result; - if constexpr (HasPlookup) { - ASSERT(Curve::type == proof_system::CurveType::SECP256K1); - public_key.validate_on_curve(); + // Use special plookup secp256k1 ECDSA mul if available (this relies on k1 endomorphism, and cannot be used for + // other curves) + if constexpr (HasPlookup && Curve::type == proof_system::CurveType::SECP256K1) { result = G1::secp256k1_ecdsa_mul(public_key, u1, u2); } else { result = G1::batch_mul({ G1::one(ctx), public_key }, { u1, u2 }); diff --git a/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp b/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp index 9a87350f8a..62945b1b6a 100644 --- a/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp +++ b/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp @@ -55,7 +55,7 @@ template class element { } else { Fq a(get_context(), uint256_t(NativeGroup::curve_a)); // we validate y^2 = x^3 + ax + b by setting "fix_remainder_zero = true" when calling mult_madd - Fq::mult_madd({ x.sqr(), x, y }, { -x, a, y }, { b }, true); + Fq::mult_madd({ x.sqr(), x, y }, { x, a, -y }, { b }, true); } }