From 644e84afa0e529d367d2bef7fc309b79e6b87928 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Wed, 10 May 2023 18:34:52 +0000 Subject: [PATCH 1/4] verification takes a pre-hashed message : Note: if len(hash) > 32 bytes, then bigfield will fail --- .../stdlib/encryption/ecdsa/ecdsa.hpp | 4 ++ .../stdlib/encryption/ecdsa/ecdsa_impl.hpp | 37 +++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp index 59b97b6bbe..20d1c32aba 100644 --- a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp +++ b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp @@ -24,6 +24,10 @@ template verify_signature_noassert(const stdlib::byte_array& message, const G1& public_key, const signature& sig); +template +bool_t verify_signature_prehashed_message_noassert(const stdlib::byte_array& hashed_message, + const G1& public_key, + const signature& sig); template static signature from_witness(Composer* ctx, const crypto::ecdsa::signature& input) diff --git a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp index 76eab940c1..a28b7817a3 100644 --- a/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp +++ b/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp @@ -117,20 +117,17 @@ bool_t verify_signature(const stdlib::byte_array& message, * @tparam Fq * @tparam Fr * @tparam G1 - * @param message + * @param hashed_message * @param public_key * @param sig * @return bool_t */ template -bool_t verify_signature_noassert(const stdlib::byte_array& message, - const G1& public_key, - const signature& sig) +bool_t verify_signature_prehashed_message_noassert(const stdlib::byte_array& hashed_message, + const G1& public_key, + const signature& sig) { - Composer* ctx = message.get_context() ? message.get_context() : public_key.x.context; - - stdlib::byte_array hashed_message = - static_cast>(stdlib::sha256(message)); + Composer* ctx = hashed_message.get_context() ? hashed_message.get_context() : public_key.x.context; Fr z(hashed_message); z.assert_is_in_field(); @@ -186,6 +183,30 @@ bool_t verify_signature_noassert(const stdlib::byte_array& m return output; } +/** + * @brief Verify ECDSA signature. Returns 0 if signature fails (i.e. does not produce unsatisfiable constraints) + * + * @tparam Composer + * @tparam Curve + * @tparam Fq + * @tparam Fr + * @tparam G1 + * @param message + * @param public_key + * @param sig + * @return bool_t + */ +template +bool_t verify_signature_noassert(const stdlib::byte_array& message, + const G1& public_key, + const signature& sig) +{ + stdlib::byte_array hashed_message = + static_cast>(stdlib::sha256(message)); + + return verify_signature_prehashed_message_noassert(hashed_message, public_key, sig); +} + } // namespace ecdsa } // namespace stdlib } // namespace proof_system::plonk \ No newline at end of file From 2c5d8b72d466a6c862daebfb804877fb0c9aa9b5 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Wed, 10 May 2023 18:36:56 +0000 Subject: [PATCH 2/4] use hashed_message when generating signature --- .../dsl/acir_format/ecdsa_secp256k1.test.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp index 0724b15f91..27161755ff 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp @@ -14,6 +14,12 @@ size_t generate_ecdsa_constraint(acir_format::EcdsaSecp256k1Constraint& ecdsa_co { std::string message_string = "Instructions unclear, ask again later."; + // hash the message since the dsl ecdsa gadget uses the prehashed message + // NOTE: If the hash being used outputs more than 32 bytes, then big-field will panic + std::vector message_buffer; + std::copy(message_string.begin(), message_string.end(), std::back_inserter(message_buffer)); + auto hashed_message = sha256::sha256(message_buffer); + crypto::ecdsa::key_pair account; account.private_key = curve::fr::random_element(); account.public_key = curve::g1::one * account.private_key; @@ -29,9 +35,9 @@ size_t generate_ecdsa_constraint(acir_format::EcdsaSecp256k1Constraint& ecdsa_co std::vector pub_y_indices_in; std::vector signature_in; size_t offset = 1; - for (size_t i = 0; i < message_string.size(); ++i) { + for (size_t i = 0; i < hashed_message.size(); ++i) { message_in.emplace_back(i + offset); - const auto byte = static_cast(message_string[i]); + const auto byte = static_cast(hashed_message[i]); witness_values.emplace_back(byte); } offset += message_in.size(); From bc67c15dfc73cbf28b393d527b9bff3ba7f93c77 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Wed, 10 May 2023 18:37:26 +0000 Subject: [PATCH 3/4] modify acir structure and function to now use prehashed variant --- .../barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp | 10 +++++----- .../barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp index d4ec3e235d..a9208c0db7 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp @@ -118,11 +118,11 @@ void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Con } bool_ct signature_result = - stdlib::ecdsa::verify_signature_noassert(message, public_key, sig); + stdlib::ecdsa::verify_signature_prehashed_message_noassert(message, public_key, sig); bool_ct signature_result_normalized = signature_result.normalize(); composer.assert_equal(signature_result_normalized.witness_index, input.result); } diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp index 55d8f6c16d..34867370c0 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp @@ -5,9 +5,8 @@ namespace acir_format { struct EcdsaSecp256k1Constraint { - // This is just a bunch of bytes - // which need to be interpreted as a string - // Note this must be a bunch of bytes + // This is the byte representation of the hashed message. + // TODO: rename this to hashed_message std::vector message; // This is the supposed public key which signed the From 48f7033ad5a5eee9a885c47f7d384a704f7f0548 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Thu, 11 May 2023 12:27:37 +0000 Subject: [PATCH 4/4] message -> hashed_message --- cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp | 6 +++--- cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp | 7 +++---- .../barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp index a9208c0db7..5a9caaa699 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp @@ -89,7 +89,7 @@ void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Con auto new_sig = ecdsa_convert_signature(composer, input.signature); - auto message = ecdsa_vector_of_bytes_to_byte_array(composer, input.message); + auto message = ecdsa_vector_of_bytes_to_byte_array(composer, input.hashed_message); auto pub_key_x_byte_arr = ecdsa_vector_of_bytes_to_byte_array(composer, input.pub_x_indices); auto pub_key_y_byte_arr = ecdsa_vector_of_bytes_to_byte_array(composer, input.pub_y_indices); @@ -113,8 +113,8 @@ void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Con pub_key_x_byte_arr[i].assert_equal(field_ct::from_witness_index(&composer, input.pub_x_indices[i])); pub_key_y_byte_arr[i].assert_equal(field_ct::from_witness_index(&composer, input.pub_y_indices[i])); } - for (size_t i = 0; i < input.message.size(); ++i) { - message[i].assert_equal(field_ct::from_witness_index(&composer, input.message[i])); + for (size_t i = 0; i < input.hashed_message.size(); ++i) { + message[i].assert_equal(field_ct::from_witness_index(&composer, input.hashed_message[i])); } bool_ct signature_result = diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp index 34867370c0..93a87d386c 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp @@ -6,8 +6,7 @@ namespace acir_format { struct EcdsaSecp256k1Constraint { // This is the byte representation of the hashed message. - // TODO: rename this to hashed_message - std::vector message; + std::vector hashed_message; // This is the supposed public key which signed the // message, giving rise to the signature. @@ -32,7 +31,7 @@ void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Con template inline void read(B& buf, EcdsaSecp256k1Constraint& constraint) { using serialize::read; - read(buf, constraint.message); + read(buf, constraint.hashed_message); read(buf, constraint.signature); read(buf, constraint.pub_x_indices); read(buf, constraint.pub_y_indices); @@ -42,7 +41,7 @@ template inline void read(B& buf, EcdsaSecp256k1Constraint& constra template inline void write(B& buf, EcdsaSecp256k1Constraint const& constraint) { using serialize::write; - write(buf, constraint.message); + write(buf, constraint.hashed_message); write(buf, constraint.signature); write(buf, constraint.pub_x_indices); write(buf, constraint.pub_y_indices); diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp index 27161755ff..eae9b7dcd0 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp @@ -69,7 +69,7 @@ size_t generate_ecdsa_constraint(acir_format::EcdsaSecp256k1Constraint& ecdsa_co witness_values.emplace_back(1); ecdsa_constraint = acir_format::EcdsaSecp256k1Constraint{ - .message = message_in, + .hashed_message = message_in, .pub_x_indices = pub_x_indices_in, .pub_y_indices = pub_y_indices_in, .result = result_in,