Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds prehashed message variant of EcDSA #437

Merged
merged 4 commits into from
May 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -113,16 +113,16 @@ 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 =
stdlib::ecdsa::verify_signature_noassert<Composer,
secp256k1_ct,
secp256k1_ct::fq_ct,
secp256k1_ct::bigfr_ct,
secp256k1_ct::g1_bigfr_ct>(message, public_key, sig);
stdlib::ecdsa::verify_signature_prehashed_message_noassert<Composer,
secp256k1_ct,
secp256k1_ct::fq_ct,
secp256k1_ct::bigfr_ct,
secp256k1_ct::g1_bigfr_ct>(message, public_key, sig);
bool_ct signature_result_normalized = signature_result.normalize();
composer.assert_equal(signature_result_normalized.witness_index, input.result);
}
Expand Down
10 changes: 4 additions & 6 deletions cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +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
std::vector<uint32_t> message;
// This is the byte representation of the hashed message.
std::vector<uint32_t> hashed_message;

// This is the supposed public key which signed the
// message, giving rise to the signature.
Expand All @@ -33,7 +31,7 @@ void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Con
template <typename B> 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);
Expand All @@ -43,7 +41,7 @@ template <typename B> inline void read(B& buf, EcdsaSecp256k1Constraint& constra
template <typename B> 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);
Expand Down
12 changes: 9 additions & 3 deletions cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t> 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<curve::fr, curve::g1> account;
account.private_key = curve::fr::random_element();
account.public_key = curve::g1::one * account.private_key;
Expand All @@ -29,9 +35,9 @@ size_t generate_ecdsa_constraint(acir_format::EcdsaSecp256k1Constraint& ecdsa_co
std::vector<uint32_t> pub_y_indices_in;
std::vector<uint32_t> 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<uint8_t>(message_string[i]);
const auto byte = static_cast<uint8_t>(hashed_message[i]);
witness_values.emplace_back(byte);
}
offset += message_in.size();
Expand Down Expand Up @@ -63,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,
Expand Down
4 changes: 4 additions & 0 deletions cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ template <typename Composer, typename Curve, typename Fq, typename Fr, typename
bool_t<Composer> verify_signature_noassert(const stdlib::byte_array<Composer>& message,
const G1& public_key,
const signature<Composer>& sig);
template <typename Composer, typename Curve, typename Fq, typename Fr, typename G1>
bool_t<Composer> verify_signature_prehashed_message_noassert(const stdlib::byte_array<Composer>& hashed_message,
const G1& public_key,
const signature<Composer>& sig);

template <typename Composer>
static signature<Composer> from_witness(Composer* ctx, const crypto::ecdsa::signature& input)
Expand Down
37 changes: 29 additions & 8 deletions cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,20 +117,17 @@ bool_t<Composer> verify_signature(const stdlib::byte_array<Composer>& message,
* @tparam Fq
* @tparam Fr
* @tparam G1
* @param message
* @param hashed_message
* @param public_key
* @param sig
* @return bool_t<Composer>
*/
template <typename Composer, typename Curve, typename Fq, typename Fr, typename G1>
bool_t<Composer> verify_signature_noassert(const stdlib::byte_array<Composer>& message,
const G1& public_key,
const signature<Composer>& sig)
bool_t<Composer> verify_signature_prehashed_message_noassert(const stdlib::byte_array<Composer>& hashed_message,
const G1& public_key,
const signature<Composer>& sig)
{
Composer* ctx = message.get_context() ? message.get_context() : public_key.x.context;

stdlib::byte_array<Composer> hashed_message =
static_cast<stdlib::byte_array<Composer>>(stdlib::sha256<Composer>(message));
Composer* ctx = hashed_message.get_context() ? hashed_message.get_context() : public_key.x.context;

Fr z(hashed_message);
z.assert_is_in_field();
Expand Down Expand Up @@ -186,6 +183,30 @@ bool_t<Composer> verify_signature_noassert(const stdlib::byte_array<Composer>& 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<Composer>
*/
template <typename Composer, typename Curve, typename Fq, typename Fr, typename G1>
bool_t<Composer> verify_signature_noassert(const stdlib::byte_array<Composer>& message,
const G1& public_key,
const signature<Composer>& sig)
{
stdlib::byte_array<Composer> hashed_message =
static_cast<stdlib::byte_array<Composer>>(stdlib::sha256<Composer>(message));

return verify_signature_prehashed_message_noassert<Composer, Curve, Fq, Fr, G1>(hashed_message, public_key, sig);
}

} // namespace ecdsa
} // namespace stdlib
} // namespace proof_system::plonk