Skip to content

Commit

Permalink
c_binds and other ECDSA related fixes (#407)
Browse files Browse the repository at this point in the history
* Add v to stdlib ecdsa.

* create an engine if its empty.

* Add ecdsa c_bind.

* print v as a uint32.

* Add secp256k1 cbind.

add c_bind.hpp

Change hpp to h.

remove hpp.

* Add ecdsa in cmakelists.

remove stdlib_ecdsa from build.
  • Loading branch information
suyash67 authored and codygunton committed May 3, 2023
1 parent 602ea19 commit d183672
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 4 deletions.
4 changes: 4 additions & 0 deletions cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ if(WASM)
$<TARGET_OBJECTS:crypto_blake2s_objects>
$<TARGET_OBJECTS:crypto_blake3s_objects>
$<TARGET_OBJECTS:crypto_keccak_objects>
$<TARGET_OBJECTS:crypto_ecdsa_objects>
$<TARGET_OBJECTS:crypto_schnorr_objects>
$<TARGET_OBJECTS:crypto_generators_objects>
$<TARGET_OBJECTS:crypto_pedersen_hash_objects>
Expand Down Expand Up @@ -125,6 +126,7 @@ if(WASM)
$<TARGET_OBJECTS:crypto_blake3s_objects>
$<TARGET_OBJECTS:crypto_generators_objects>
$<TARGET_OBJECTS:crypto_keccak_objects>
$<TARGET_OBJECTS:crypto_ecdsa_objects>
$<TARGET_OBJECTS:crypto_schnorr_objects>
$<TARGET_OBJECTS:crypto_pedersen_hash_objects>
$<TARGET_OBJECTS:crypto_pedersen_commitment_objects>
Expand Down Expand Up @@ -179,6 +181,7 @@ if(WASM)
$<TARGET_OBJECTS:crypto_blake2s_objects>
$<TARGET_OBJECTS:crypto_blake3s_objects>
$<TARGET_OBJECTS:crypto_keccak_objects>
$<TARGET_OBJECTS:crypto_ecdsa_objects>
$<TARGET_OBJECTS:crypto_schnorr_objects>
$<TARGET_OBJECTS:crypto_generators_objects>
$<TARGET_OBJECTS:crypto_pedersen_hash_objects>
Expand Down Expand Up @@ -215,6 +218,7 @@ else()
$<TARGET_OBJECTS:crypto_blake2s_objects>
$<TARGET_OBJECTS:crypto_blake3s_objects>
$<TARGET_OBJECTS:crypto_keccak_objects>
$<TARGET_OBJECTS:crypto_ecdsa_objects>
$<TARGET_OBJECTS:crypto_schnorr_objects>
$<TARGET_OBJECTS:crypto_generators_objects>
$<TARGET_OBJECTS:crypto_pedersen_hash_objects>
Expand Down
70 changes: 70 additions & 0 deletions cpp/src/barretenberg/crypto/ecdsa/c_bind.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "ecdsa.hpp"
#include <barretenberg/ecc/curves/secp256k1/secp256k1.hpp>

#define WASM_EXPORT __attribute__((visibility("default")))

extern "C" {

WASM_EXPORT void ecdsa__compute_public_key(uint8_t const* private_key, uint8_t* public_key_buf)
{
auto priv_key = from_buffer<secp256k1::fr>(private_key);
secp256k1::g1::affine_element pub_key = secp256k1::g1::one * priv_key;
write(public_key_buf, pub_key);
}

WASM_EXPORT void ecdsa__construct_signature(uint8_t const* message,
size_t msg_len,
uint8_t const* private_key,
uint8_t* output_sig_r,
uint8_t* output_sig_s,
uint8_t* output_sig_v)
{
using serialize::write;
auto priv_key = from_buffer<secp256k1::fr>(private_key);
secp256k1::g1::affine_element pub_key = secp256k1::g1::one * priv_key;
crypto::ecdsa::key_pair<secp256k1::fr, secp256k1::g1> key_pair = { priv_key, pub_key };

auto sig = crypto::ecdsa::construct_signature<Sha256Hasher, secp256k1::fq, secp256k1::fr, secp256k1::g1>(
std::string((char*)message, msg_len), key_pair);
write(output_sig_r, sig.r);
write(output_sig_s, sig.s);
write(output_sig_v, sig.v);
}

WASM_EXPORT void ecdsa__recover_public_key_from_signature(uint8_t const* message,
size_t msg_len,
uint8_t const* sig_r,
uint8_t const* sig_s,
uint8_t* sig_v,
uint8_t* output_pub_key)
{
std::array<uint8_t, 32> r, s;
std::copy(sig_r, sig_r + 32, r.begin());
std::copy(sig_s, sig_s + 32, s.begin());
const uint8_t v = *sig_v;

crypto::ecdsa::signature sig = { r, s, v };
auto recovered_pub_key =
crypto::ecdsa::recover_public_key<Sha256Hasher, secp256k1::fq, secp256k1::fr, secp256k1::g1>(
std::string((char*)message, msg_len), sig);
write(output_pub_key, recovered_pub_key);
}

WASM_EXPORT bool ecdsa__verify_signature(uint8_t const* message,
size_t msg_len,
uint8_t const* pub_key,
uint8_t const* sig_r,
uint8_t const* sig_s,
uint8_t const* sig_v)
{
auto pubk = from_buffer<secp256k1::g1::affine_element>(pub_key);
std::array<uint8_t, 32> r, s;
std::copy(sig_r, sig_r + 32, r.begin());
std::copy(sig_s, sig_s + 32, s.begin());
const uint8_t v = *sig_v;

crypto::ecdsa::signature sig = { r, s, v };
return crypto::ecdsa::verify_signature<Sha256Hasher, secp256k1::fq, secp256k1::fr, secp256k1::g1>(
std::string((char*)message, msg_len), pubk, sig);
}
}
29 changes: 29 additions & 0 deletions cpp/src/barretenberg/crypto/ecdsa/c_bind.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <ecc/curves/secp256k1/secp256k1.hpp>

#define WASM_EXPORT __attribute__((visibility("default")))

extern "C" {

WASM_EXPORT void ecdsa__compute_public_key(uint8_t const* private_key, uint8_t* public_key_buf);

WASM_EXPORT void ecdsa__construct_signature(uint8_t const* message,
size_t msg_len,
uint8_t const* private_key,
uint8_t* output_sig_r,
uint8_t* output_sig_s,
uint8_t* output_sig_v);

WASM_EXPORT void ecdsa__recover_public_key_from_signature(uint8_t const* message,
size_t msg_len,
uint8_t const* sig_r,
uint8_t const* sig_s,
uint8_t* sig_v,
uint8_t* output_pub_key);

WASM_EXPORT bool ecdsa__verify_signature(uint8_t const* message,
size_t msg_len,
uint8_t const* pub_key,
uint8_t const* sig_r,
uint8_t const* sig_s,
uint8_t const* sig_v);
}
6 changes: 4 additions & 2 deletions cpp/src/barretenberg/crypto/ecdsa/ecdsa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,26 @@ bool verify_signature(const std::string& message,

inline bool operator==(signature const& lhs, signature const& rhs)
{
return lhs.r == rhs.r && lhs.s == rhs.s;
return lhs.r == rhs.r && lhs.s == rhs.s && lhs.v == rhs.v;
}

inline std::ostream& operator<<(std::ostream& os, signature const& sig)
{
os << "{ " << sig.r << ", " << sig.s << " }";
os << "{ " << sig.r << ", " << sig.s << ", " << static_cast<uint32_t>(sig.v) << " }";
return os;
}

template <typename B> inline void read(B& it, signature& sig)
{
using serialize::read;
read(it, sig.r);
read(it, sig.s);
read(it, sig.v);
}

template <typename B> inline void write(B& buf, signature const& sig)
{
using serialize::write;
write(buf, sig.r);
write(buf, sig.s);
write(buf, sig.v);
Expand Down
4 changes: 3 additions & 1 deletion cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,11 @@ void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Con

std::vector<uint8_t> rr(new_sig.r.begin(), new_sig.r.end());
std::vector<uint8_t> ss(new_sig.s.begin(), new_sig.s.end());
uint8_t vv = new_sig.v;

stdlib::ecdsa::signature<Composer> sig{ stdlib::byte_array<Composer>(&composer, rr),
stdlib::byte_array<Composer>(&composer, ss) };
stdlib::byte_array<Composer>(&composer, ss),
stdlib::uint8<Composer>(&composer, vv) };

pub_key_x_fq.assert_is_in_field();
pub_key_y_fq.assert_is_in_field();
Expand Down
30 changes: 30 additions & 0 deletions cpp/src/barretenberg/ecc/curves/secp256k1/c_bind.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "secp256k1.hpp"

#define WASM_EXPORT __attribute__((visibility("default")))

extern "C" {

WASM_EXPORT void ecc_secp256k1__mul(uint8_t const* point_buf, uint8_t const* scalar_buf, uint8_t* result)
{
auto point = from_buffer<secp256k1::g1::affine_element>(point_buf);
auto scalar = from_buffer<secp256k1::fr>(scalar_buf);
secp256k1::g1::affine_element r = point * scalar;
write(result, r);
}

WASM_EXPORT void ecc_secp256k1__get_random_scalar_mod_circuit_modulus(uint8_t* result)
{
barretenberg::fr output = barretenberg::fr::random_element();
write(result, output);
}

WASM_EXPORT void ecc_secp256k1__reduce512_buffer_mod_circuit_modulus(uint8_t* input, uint8_t* result)
{
uint512_t bigint_input = from_buffer<uint512_t>(input);

uint512_t barretenberg_modulus(barretenberg::fr::modulus);

uint512_t target_output = bigint_input % barretenberg_modulus;
write(result, target_output.lo);
}
}
12 changes: 12 additions & 0 deletions cpp/src/barretenberg/ecc/curves/secp256k1/c_bind.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "secp256k1.hpp"

#define WASM_EXPORT __attribute__((visibility("default")))

extern "C" {

WASM_EXPORT void ecc_secp256k1__mul(uint8_t const* point_buf, uint8_t const* scalar_buf, uint8_t* result);

WASM_EXPORT void ecc_secp256k1__get_random_scalar_mod_circuit_modulus(uint8_t* result);

WASM_EXPORT void ecc_secp256k1__reduce512_buffer_mod_circuit_modulus(uint8_t* input, uint8_t* result);
}
4 changes: 4 additions & 0 deletions cpp/src/barretenberg/ecc/groups/affine_element_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ affine_element<Fq, Fr, T> affine_element<Fq, Fr, T>::hash_to_curve(const uint64_
template <typename Fq, typename Fr, typename T>
affine_element<Fq, Fr, T> affine_element<Fq, Fr, T>::random_element(numeric::random::Engine* engine) noexcept
{
if (engine == nullptr) {
engine = &numeric::random::get_engine();
}

bool found_one = false;
Fq yy;
Fq x;
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 @@ -2,6 +2,7 @@

#include "barretenberg/crypto/ecdsa/ecdsa.hpp"
#include "../../primitives/byte_array/byte_array.hpp"
#include "../../primitives/uint/uint.hpp"
#include "../../primitives/composers/composers_fwd.hpp"

namespace proof_system::plonk {
Expand All @@ -11,6 +12,7 @@ namespace ecdsa {
template <typename Composer> struct signature {
stdlib::byte_array<Composer> r;
stdlib::byte_array<Composer> s;
stdlib::uint8<Composer> v;
};

template <typename Composer, typename Curve, typename Fq, typename Fr, typename G1>
Expand All @@ -25,9 +27,11 @@ static signature<Composer> from_witness(Composer* ctx, const crypto::ecdsa::sign
std::vector<uint8_t> s_vec(std::begin(input.s), std::end(input.s));
stdlib::byte_array<Composer> r(ctx, r_vec);
stdlib::byte_array<Composer> s(ctx, s_vec);
stdlib::uint8<Composer> v(ctx, input.v);
signature<Composer> out;
out.r = r;
out.s = s;
out.v = v;
return out;
}

Expand Down
5 changes: 4 additions & 1 deletion cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ TEST(stdlib_ecdsa, verify_signature)

std::vector<uint8_t> rr(signature.r.begin(), signature.r.end());
std::vector<uint8_t> ss(signature.s.begin(), signature.s.end());
uint8_t vv = signature.v;

stdlib::ecdsa::signature<Composer> sig{ curve::byte_array_ct(&composer, rr), curve::byte_array_ct(&composer, ss) };
stdlib::ecdsa::signature<Composer> sig{ curve::byte_array_ct(&composer, rr),
curve::byte_array_ct(&composer, ss),
stdlib::uint8<Composer>(&composer, vv) };

curve::byte_array_ct message(&composer, message_string);

Expand Down
5 changes: 5 additions & 0 deletions cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ bool_t<Composer> verify_signature(const stdlib::byte_array<Composer>& message,
{
Composer* ctx = message.get_context() ? message.get_context() : public_key.x.context;

// Check if revovery id v is either 27 ot 28.
// TODO(Suyash): check with Zac/Kesha/Cody.
field_t<Composer>(sig.v).assert_is_in_set({ field_t<Composer>(27), field_t<Composer>(28) },
"signature is non-standard");

stdlib::byte_array<Composer> hashed_message =
static_cast<stdlib::byte_array<Composer>>(stdlib::sha256<Composer>(message));

Expand Down

0 comments on commit d183672

Please sign in to comment.