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

[Temporary] Pending bb work for aztec3 #368

Merged
merged 9 commits into from
May 4, 2023
Merged
7 changes: 7 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 All @@ -91,6 +92,7 @@ if(WASM)
$<TARGET_OBJECTS:stdlib_pedersen_commitment_objects>
$<TARGET_OBJECTS:stdlib_blake2s_objects>
$<TARGET_OBJECTS:stdlib_blake3s_objects>
$<TARGET_OBJECTS:stdlib_keccak_objects>
$<TARGET_OBJECTS:stdlib_sha256_objects>
$<TARGET_OBJECTS:stdlib_aes128_objects>
$<TARGET_OBJECTS:stdlib_merkle_tree_objects>
Expand Down Expand Up @@ -124,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 @@ -178,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 All @@ -193,6 +197,7 @@ if(WASM)
$<TARGET_OBJECTS:stdlib_pedersen_commitment_objects>
$<TARGET_OBJECTS:stdlib_blake2s_objects>
$<TARGET_OBJECTS:stdlib_blake3s_objects>
$<TARGET_OBJECTS:stdlib_keccak_objects>
$<TARGET_OBJECTS:stdlib_sha256_objects>
$<TARGET_OBJECTS:stdlib_aes128_objects>
$<TARGET_OBJECTS:stdlib_merkle_tree_objects>
Expand All @@ -213,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 All @@ -228,6 +234,7 @@ else()
$<TARGET_OBJECTS:stdlib_pedersen_commitment_objects>
$<TARGET_OBJECTS:stdlib_blake2s_objects>
$<TARGET_OBJECTS:stdlib_blake3s_objects>
$<TARGET_OBJECTS:stdlib_keccak_objects>
$<TARGET_OBJECTS:stdlib_sha256_objects>
$<TARGET_OBJECTS:stdlib_aes128_objects>
$<TARGET_OBJECTS:stdlib_merkle_tree_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
2 changes: 1 addition & 1 deletion cpp/src/barretenberg/crypto/generators/generator_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,4 +294,4 @@ const fixed_base_ladder* generator_data::get_hash_ladder(size_t num_bits) const
}

} // namespace generators
} // namespace crypto
} // namespace crypto
9 changes: 5 additions & 4 deletions cpp/src/barretenberg/crypto/pedersen_hash/c_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,23 @@ extern "C" {

WASM_EXPORT void pedersen_hash__init()
{
// TODO: do we need this if we are using lookup-pedersen in merkle trees?
crypto::generators::init_generator_data();
}

WASM_EXPORT void pedersen__hash_pair(uint8_t const* left, uint8_t const* right, uint8_t* result)
{
auto lhs = barretenberg::fr::serialize_from_buffer(left);
auto rhs = barretenberg::fr::serialize_from_buffer(right);
auto r = crypto::pedersen_hash::hash_multiple({ lhs, rhs });
auto r = crypto::pedersen_hash::lookup::hash_multiple({ lhs, rhs });
barretenberg::fr::serialize_to_buffer(r, result);
}

WASM_EXPORT void pedersen__hash_multiple(uint8_t const* inputs_buffer, uint8_t* output)
{
std::vector<grumpkin::fq> to_compress;
read(inputs_buffer, to_compress);
auto r = crypto::pedersen_hash::hash_multiple(to_compress);
auto r = crypto::pedersen_hash::lookup::hash_multiple(to_compress);
barretenberg::fr::serialize_to_buffer(r, output);
}

Expand All @@ -36,7 +37,7 @@ WASM_EXPORT void pedersen__hash_multiple_with_hash_index(uint8_t const* inputs_b
{
std::vector<grumpkin::fq> to_compress;
read(inputs_buffer, to_compress);
auto r = crypto::pedersen_hash::hash_multiple(to_compress, hash_index);
auto r = crypto::pedersen_hash::lookup::hash_multiple(to_compress, hash_index);
barretenberg::fr::serialize_to_buffer(r, output);
}

Expand All @@ -54,7 +55,7 @@ WASM_EXPORT uint8_t* pedersen__hash_to_tree(uint8_t const* data)
fields.reserve(num_outputs);

for (size_t i = 0; fields.size() < num_outputs; i += 2) {
fields.push_back(crypto::pedersen_hash::hash_multiple({ fields[i], fields[i + 1] }));
fields.push_back(crypto::pedersen_hash::lookup::hash_multiple({ fields[i], fields[i + 1] }));
}

auto buf_size = 4 + num_outputs * sizeof(grumpkin::fq);
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);
}
7 changes: 7 additions & 0 deletions cpp/src/barretenberg/ecc/groups/affine_element.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ template <typename Fq, typename Fr, typename Params> class alignas(64) affine_el

constexpr bool on_curve() const noexcept;

/**
* @brief Samples a random point on the curve.
*
* @return A randomly chosen point on the curve
*/
static affine_element random_element(numeric::random::Engine* engine = nullptr) noexcept;

/**
* @brief Hash a seed value to curve.
*
Expand Down
33 changes: 33 additions & 0 deletions cpp/src/barretenberg/ecc/groups/affine_element_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,5 +229,38 @@ affine_element<Fq, Fr, T> affine_element<Fq, Fr, T>::hash_to_curve(const uint64_

return affine_element<Fq, Fr, T>(x_out, y_out_);
}

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;
Fq y;
while (!found_one) {
// Sample a random x-coordinate and check if it satisfies curve equation.
x = Fq::random_element(engine);
yy = x.sqr() * x + T::b;
if constexpr (T::has_a) {
yy += (x * T::a);
}
auto [found_root, y1] = yy.sqrt();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When !found_root it makes sense to skip the work below here (sampling a random byte and doing a field negation), but doesn't matter unless we plan to generate a lot of points with this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was Kesha's suggestion and I agree with him. If we don't sample a bit and negate the y-coordinate, we're sampling a random point from only "upper" half of the curve points. To really get a "random" point on the curve, we need to randomly change the sign of the y coordinate.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this make sense, but my point is that if found_root is false, then you don't need to bother sampling a random byte and negating a coordinate, so it would be more efficient to to wrap everything below line 251 in an if (found_root) block. About half the time the while loop will execute more than once, meaning that if you're generating 2 billion random points of the curve, then you will sample about 1 billion unneeded bytes and do about 1 billion unneeded 256-bit field element negations.

y = y1;

// Negate the y-coordinate based on a randomly sampled bit.
bool random_bit = (engine->get_random_uint8() & 1);
if (random_bit) {
y = -y;
}

found_one = found_root;
}
return affine_element<Fq, Fr, T>(x, y);
}

} // namespace group_elements
} // namespace barretenberg
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
Loading