Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
proof_of_possession.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8
9#include <utility>
10
12#include "schnorr.hpp"
13
14namespace bb::crypto {
15
24template <typename G1, typename Hash> struct SchnorrProofOfPossession {
25 using Fq = typename G1::Fq;
26 using Fr = typename G1::Fr;
27 using affine_element = typename G1::affine_element;
28 using element = typename G1::element;
30
31 // challenge = e = H_reg(pk,pk,R)
32 std::array<uint8_t, 32> challenge;
33 // response = z = k - e * sk
35
36 // restore default constructor to enable deserialization
38
47 {
48 auto secret_key = account.private_key;
49 auto public_key = account.public_key;
50
51 // Fr::random_element() will call std::random_device, which in turn relies on system calls to generate a string
52 // of random bits. It is important to ensure that the execution environment will correctly supply system calls
53 // that give std::random_device access to an entropy source that produces a string of non-deterministic
54 // uniformly random bits. For example, when compiling into a wasm binary, it is essential that the random_get
55 // method is overloaded to utilise a suitable entropy source
56 // (see https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md)
57 // TODO: securely erase `k`
59
60 affine_element R = G1::one * k;
61
62 auto challenge_bytes = generate_challenge(public_key, R);
63 std::copy(challenge_bytes.begin(), challenge_bytes.end(), challenge.begin());
64
65 Fr challenge_fr = Fr::serialize_from_buffer(&challenge_bytes[0]);
66 response = k - challenge_fr * secret_key;
67 }
68
75 bool verify(const affine_element& public_key) const
76 {
77 Fr challenge_fr = Fr::serialize_from_buffer(&challenge[0]);
78 // this ensures that a default constructed proof is invalid
79 if (response.is_zero())
80 return false;
81
82 if (!public_key.on_curve() || public_key.is_point_at_infinity())
83 return false;
84
85 // R = e•pk + z•G
86 affine_element R = element(public_key) * challenge_fr + G1::one * response;
87 if (R.is_point_at_infinity())
88 return false;
89
90 // recompute the challenge e
91 auto challenge_computed = generate_challenge(public_key, R);
92 return std::equal(challenge.begin(), challenge.end(), challenge_computed.begin(), challenge_computed.end());
93 }
94
95 private:
103 static auto generate_challenge(const affine_element& public_key, const affine_element& R)
104 {
105 // Domain separation challenges
106 const std::string domain_separator_pop("h_reg");
107
108 // buffer containing (domain_sep, G, X, X, R)
109 std::vector<uint8_t> challenge_buf;
110
111 // write domain separator
112 std::copy(domain_separator_pop.begin(), domain_separator_pop.end(), std::back_inserter(challenge_buf));
113
114 // write the group generator
115 write(challenge_buf, G1::affine_one);
116
117 // write X twice as per the spec
118 write(challenge_buf, public_key);
119 write(challenge_buf, public_key);
120
121 // write R
122 write(challenge_buf, R);
123
124 // generate the raw bits of H_reg(X,X,R)
125 return Hash::hash(challenge_buf);
126 }
127};
128
129template <typename B, typename G1, typename Hash>
130inline void read(B& it, SchnorrProofOfPossession<G1, Hash>& proof_of_possession)
131{
132 read(it, proof_of_possession.challenge);
133 read(it, proof_of_possession.response);
134}
135
136template <typename B, typename G1, typename Hash>
137inline void write(B& buf, SchnorrProofOfPossession<G1, Hash> const& proof_of_possession)
138{
139 write(buf, proof_of_possession.challenge);
140 write(buf, proof_of_possession.response);
141}
142
143} // namespace bb::crypto
uint8_t const * buf
Definition data_store.hpp:9
void read(B &it, SchnorrProofOfPossession< G1, Hash > &proof_of_possession)
void write(B &buf, SchnorrProofOfPossession< G1, Hash > const &proof_of_possession)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
A proof of possession is a Schnorr proof of knowledge of a secret key corresponding to a given public...
typename G1::affine_element affine_element
static auto generate_challenge(const affine_element &public_key, const affine_element &R)
Generate the Fiat-Shamir challenge e = H_reg(G,X,X,R)
SchnorrProofOfPossession(const key_pair &account)
Create a new proof of possession for a given account.
bool verify(const affine_element &public_key) const
verifies that an unserialized signature is valid
G1::affine_element public_key
Definition schnorr.hpp:24
static field random_element(numeric::RNG *engine=nullptr) noexcept
static field serialize_from_buffer(const uint8_t *buffer)
static constexpr field zero()