From 9c9085dec41e278014e7dcc0286597108ccc64d7 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Tue, 25 Jul 2023 08:38:16 +0000 Subject: [PATCH] code for removing pedersen from schnorr --- .../barretenberg/crypto/schnorr/schnorr.tcc | 26 +++++------------- .../stdlib/encryption/schnorr/schnorr.cpp | 27 +++++++++++-------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/cpp/src/barretenberg/crypto/schnorr/schnorr.tcc b/cpp/src/barretenberg/crypto/schnorr/schnorr.tcc index 6984479398..74167b6051 100644 --- a/cpp/src/barretenberg/crypto/schnorr/schnorr.tcc +++ b/cpp/src/barretenberg/crypto/schnorr/schnorr.tcc @@ -11,23 +11,12 @@ namespace schnorr { /** * @brief Generate the schnorr signature challenge parameter `e` given a message, signer pubkey and nonce * - * @details Normal Schnorr param e = H(R.x || pubkey || message) - * But we want to keep hash preimage to <= 64 bytes for a 32 byte message - * (for performance reasons in our join-split circuit!) - * - * barretenberg schnorr defines e as the following: - * - * e = H(pedersen(R.x || pubkey.x || pubkey.y), message) - * - * pedersen is collision resistant => e can be modelled as randomly distributed - * as long as H can be modelled as a random oracle - * * @tparam Hash the hash-function used as random-oracle * @tparam G1 Group over which the signature is produced * @param message what are we signing over? * @param pubkey the pubkey of the signer * @param R the nonce - * @return e = H(pedersen(R.x || pubkey.x || pubkey.y), message) as a 256-bit integer, + * @return e = H(R.x || pubkey.x || pubkey.y || message) as a 256-bit integer, * represented in a container of 32 uint8_t's * * @@ -41,15 +30,14 @@ static auto generate_schnorr_challenge(const std::string& message, const typename G1::affine_element& pubkey, const typename G1::affine_element& R) { - using Fq = typename G1::coordinate_field; - // create challenge message pedersen_commitment(R.x, pubkey) - Fq compressed_keys = crypto::pedersen_commitment::compress_native({ R.x, pubkey.x, pubkey.y }); std::vector e_buffer; - write(e_buffer, compressed_keys); + write(e_buffer, R.x); + write(e_buffer, pubkey.x); + write(e_buffer, pubkey.y); std::copy(message.begin(), message.end(), std::back_inserter(e_buffer)); - // hash the result of the pedersen hash digest - // we return auto since some hash implementation return + // Hash the buffer to produce a 256-bit integer + // We return auto since some hash implementation return // either a std::vector or a std::array with 32 bytes return Hash::hash(e_buffer); } @@ -148,7 +136,7 @@ bool verify_signature(const std::string& message, const typename G1::affine_elem // compare the _hashes_ rather than field elements modulo r - // e = H(pedersen(r, pk.x, pk.y), m), where r = x(R) + // e = H(r, pk.x, pk.y, m), where r = x(R) auto target_e = generate_schnorr_challenge(message, public_key, R); return std::equal(sig.e.begin(), sig.e.end(), target_e.begin(), target_e.end()); } diff --git a/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.cpp b/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.cpp index 52f7e698d4..e2b8c96f01 100644 --- a/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.cpp +++ b/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.cpp @@ -244,7 +244,7 @@ point variable_base_mul(const point& pub_key, const point& current_accu } // At this point, accumulator is [W + skew]pub + [2^{129}]collision_mask. - // If wnaf_skew, subtract pub_key frorm accumulator. + // If wnaf_skew, subtract pub_key from accumulator. field_t add_lambda = (accumulator.y + pub_key.y) / (accumulator.x - pub_key.x); field_t x_add = add_lambda.madd(add_lambda, -(accumulator.x + pub_key.x)); field_t y_add = add_lambda.madd((pub_key.x - x_add), pub_key.y); @@ -266,7 +266,7 @@ point variable_base_mul(const point& pub_key, const point& current_accu /** * @brief Make the computations needed to verify a signature (s, e), i.e., compute - * e' = hash(([s]g + [e]pub).x | message) + * e' = hash(([s]g + [e]pub).x | pub.x | pub.y | message) and return e'. * * @details TurboPlonk: ~10850 gates (~4k for variable_base_mul, ~6k for blake2s) for a string of length < 32. @@ -276,25 +276,30 @@ std::array, 2> verify_signature_internal(const byte_array& message const point& pub_key, const signature_bits& sig) { - // Compute [s]g, where s = (s_lo, s_hi) and g = G1::one. + // Compute [s]g, where s = (s_lo, s_hi) and g is the canonical generator. point R_1 = group::fixed_base_scalar_mul(sig.s_lo, sig.s_hi); // Compute [e]pub, where e = (e_lo, e_hi) point R_2 = variable_base_mul(pub_key, sig.e_lo, sig.e_hi); // check R_1 != R_2 + // TODO: This is checking that the x-coordinates are not equal. + // TODO: Theres no comment here stating why this is okay if for example R_1.y = -R_2.y (R_1.x - R_2.x).assert_is_not_zero("Cannot add points in Schnorr verification."); - // Compute x-coord of R_1 + R_2 = [s]g + [e]pub. + // Compute x-coord of R_3 = R_1 + R_2 = [s]g + [e]pub. field_t lambda = (R_1.y - R_2.y) / (R_1.x - R_2.x); - field_t x_3 = lambda * lambda - (R_1.x + R_2.x); + field_t R_3_x = lambda * lambda - (R_1.x + R_2.x); - // build input (pedersen(([s]g + [e]pub).x | pub.x | pub.y) | message) to hash function - // pedersen hash ([r].x | pub.x) to make sure the size of `hash_input` is <= 64 bytes for a 32 byte message - byte_array hash_input(stdlib::pedersen_commitment::compress({ x_3, pub_key.x, pub_key.y })); + // Compute e' = hash(R_3.x | pub.x | pub.y | message) + byte_array hash_input; + + hash_input.write(static_cast>(R_3_x)); + hash_input.write(static_cast>(pub_key.x)); + hash_input.write(static_cast>(pub_key.y)); hash_input.write(message); - // compute e' = hash(([s]g + [e]pub).x | message) byte_array output = blake2s(hash_input); + // TODO(check): why is hi the first 16 bytes field_t output_hi(output.slice(0, 16)); field_t output_lo(output.slice(16, 16)); @@ -303,7 +308,7 @@ std::array, 2> verify_signature_internal(const byte_array& message /** * @brief Verify that a signature (s, e) is valid, i.e., compute - * e' = hash(([s]g + [e]pub).x | message) + * e' = hash(([s]g + [e]pub).x | pub.x | pub.y | message) * and check that * e' == e is true. */ @@ -317,7 +322,7 @@ void verify_signature(const byte_array& message, const point& pub_key, con /** * @brief Attempt to verify a signature (s, e) and return the result, i.e., compute - * e' = hash(([s]g + [e]pub).x | message) + * e' = hash(([s]g + [e]pub).x | pub.x | pub.y | message) * and return the boolean witness e' == e. */ template