Skip to content

Commit

Permalink
Merge pull request #1295 from AztecProtocol/defi-bridge-project
Browse files Browse the repository at this point in the history
Isolate code for Monday 15th release
  • Loading branch information
joss-aztec authored Aug 11, 2022
2 parents 98bf76f + 1d321fe commit 68dbd72
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 7 deletions.
8 changes: 7 additions & 1 deletion src/aztec/crypto/ecdsa/ecdsa_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <numeric/uint256/uint256.hpp>
#include <common/serialize.hpp>
#include "../hmac/hmac.hpp"

namespace crypto {
namespace ecdsa {
Expand All @@ -10,7 +11,12 @@ template <typename Hash, typename Fq, typename Fr, typename G1>
signature construct_signature(const std::string& message, const key_pair<Fr, G1>& account)
{
signature sig;
Fr k = Fr::random_element(); // TODO replace with HMAC

// use HMAC in PRF mode to derive 32-byte secret `k`
std::vector<uint8_t> pkey_buffer;
write(pkey_buffer, account.private_key);
Fr k = crypto::get_unbiased_field_from_hmac<Hash, Fr>(message, pkey_buffer);

typename G1::affine_element R(G1::one * k);
Fq::serialize_to_buffer(R.x, &sig.r[0]);

Expand Down
38 changes: 38 additions & 0 deletions src/aztec/crypto/hmac/hmac.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cstdint>
#include <string>
#include <vector>
#include <numeric/uintx/uintx.hpp>

namespace crypto {
/**
Expand Down Expand Up @@ -69,4 +70,41 @@ std::array<uint8_t, Hash::OUTPUT_SIZE> hmac(const MessageContainer& message, con
return result;
}

/**
* @brief Takes a size-HASH_OUTPUT buffer from HMAC and converts into a field element
*
* @details We assume HASH_OUTPUT = 32, which is insufficient entropy. We hash input with `0` and `1` to produce 64
* bytes of input data. This is then converted into a uin512_t, which is taken modulo Fr::modulus to produce our field
* element.
*
* @tparam Hash the hash function we're using
* @tparam Fr field type
* @param input the input buffer
* @return Fr output field element
*/
template <typename Hash, typename Fr, typename MessageContainer, typename KeyContainer>
Fr get_unbiased_field_from_hmac(const MessageContainer& message, const KeyContainer& key)
{
auto input = hmac<Hash, MessageContainer, KeyContainer>(message, key);

std::vector<uint8_t> lo_buffer(input.begin(), input.end());
lo_buffer.push_back(0);
std::vector<uint8_t> hi_buffer(input.begin(), input.end());
hi_buffer.push_back(1);

auto klo = Hash::hash(lo_buffer);
auto khi = Hash::hash(hi_buffer);

std::vector<uint8_t> full_buffer(khi.begin(), khi.end());
for (auto& v : klo) {
full_buffer.push_back(v);
}

uint512_t field_as_u512;
const uint8_t* ptr = &full_buffer[0];
numeric::read(ptr, field_as_u512);

Fr result((field_as_u512 % Fr::modulus).lo);
return result;
}
} // namespace crypto
5 changes: 3 additions & 2 deletions src/aztec/crypto/schnorr/schnorr.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <ecc/fields/field.hpp>

#include <crypto/hmac/hmac.hpp>

namespace crypto {
namespace schnorr {

Expand Down Expand Up @@ -33,9 +34,9 @@ signature construct_signature(const std::string& message, const key_pair<Fr, G1>
// use HMAC in PRF mode to derive 32-byte secret `k`
std::vector<uint8_t> pkey_buffer;
write(pkey_buffer, private_key);
std::array<uint8_t, Hash::OUTPUT_SIZE> k_buffer = crypto::hmac<Hash>(message, pkey_buffer);

Fr k = Fr::serialize_from_buffer(&k_buffer[0]);
Fr k = crypto::get_unbiased_field_from_hmac<Hash, Fr>(message, pkey_buffer);

typename G1::affine_element R(G1::one * k);

std::vector<uint8_t> message_buffer;
Expand Down
17 changes: 15 additions & 2 deletions src/aztec/ecc/groups/affine_element.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
#include <fstream>
#include <common/serialize.hpp>

namespace test_affine_element {

using namespace barretenberg;

TEST(AffineElement, ReadWriteBuffer)
TEST(affine_element, read_write_buffer)
{
g1::affine_element P = g1::affine_element(g1::element::random_element());
g1::affine_element Q;
Expand All @@ -22,4 +24,15 @@ TEST(AffineElement, ReadWriteBuffer)

ASSERT_FALSE(P == Q);
ASSERT_TRUE(P == R);
}
}

// Regression test to ensure that the point at infinity is not equal to its coordinate-wise reduction, which may lie
// on the curve, depending on the y-coordinate.
TEST(affine_element, infinity_regression)
{
g1::affine_element P;
P.self_set_infinity();
g1::affine_element R(0, P.y);
ASSERT_FALSE(P == R);
}
} // namespace test_affine_element
7 changes: 5 additions & 2 deletions src/aztec/ecc/groups/affine_element_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,11 @@ template <class Fq, class Fr, class T> constexpr bool affine_element<Fq, Fr, T>:
template <class Fq, class Fr, class T>
constexpr bool affine_element<Fq, Fr, T>::operator==(const affine_element& other) const noexcept
{
bool both_infinity = is_point_at_infinity() && other.is_point_at_infinity();
return both_infinity || ((x == other.x) && (y == other.y));
bool this_is_infinity = is_point_at_infinity();
bool other_is_infinity = other.is_point_at_infinity();
bool both_infinity = this_is_infinity && other_is_infinity;
bool only_one_is_infinity = this_is_infinity != other_is_infinity;
return !only_one_is_infinity && (both_infinity || ((x == other.x) && (y == other.y)));
}

/**
Expand Down

0 comments on commit 68dbd72

Please sign in to comment.