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#pragma once
2
3#include <utility>
4
6#include "schnorr.hpp"
7
8namespace bb::crypto {
9
18template <typename G1, typename Hash> struct SchnorrProofOfPossession {
19 using Fq = typename G1::Fq;
20 using Fr = typename G1::Fr;
21 using affine_element = typename G1::affine_element;
22 using element = typename G1::element;
24
25 // challenge = e = H_reg(pk,pk,R)
26 std::array<uint8_t, 32> challenge;
27 // response = z = k - e * sk
29
30 // restore default constructor to enable deserialization
32
41 {
42 auto secret_key = account.private_key;
43 auto public_key = account.public_key;
44
45 // Fr::random_element() will call std::random_device, which in turn relies on system calls to generate a string
46 // of random bits. It is important to ensure that the execution environment will correctly supply system calls
47 // that give std::random_device access to an entropy source that produces a string of non-deterministic
48 // uniformly random bits. For example, when compiling into a wasm binary, it is essential that the random_get
49 // method is overloaded to utilise a suitable entropy source
50 // (see https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md)
51 // TODO: securely erase `k`
53
54 affine_element R = G1::one * k;
55
56 auto challenge_bytes = generate_challenge(public_key, R);
57 std::copy(challenge_bytes.begin(), challenge_bytes.end(), challenge.begin());
58
59 Fr challenge_fr = Fr::serialize_from_buffer(&challenge_bytes[0]);
60 response = k - challenge_fr * secret_key;
61 }
62
69 bool verify(const affine_element& public_key) const
70 {
71 Fr challenge_fr = Fr::serialize_from_buffer(&challenge[0]);
72 // this ensures that a default constructed proof is invalid
73 if (response.is_zero())
74 return false;
75
76 if (!public_key.on_curve() || public_key.is_point_at_infinity())
77 return false;
78
79 // R = e•pk + z•G
80 affine_element R = element(public_key) * challenge_fr + G1::one * response;
81 if (R.is_point_at_infinity())
82 return false;
83
84 // recompute the challenge e
85 auto challenge_computed = generate_challenge(public_key, R);
86 return std::equal(challenge.begin(), challenge.end(), challenge_computed.begin(), challenge_computed.end());
87 }
88
89 private:
97 static auto generate_challenge(const affine_element& public_key, const affine_element& R)
98 {
99 // Domain separation challenges
100 const std::string domain_separator_pop("h_reg");
101
102 // buffer containing (domain_sep, G, X, X, R)
103 std::vector<uint8_t> challenge_buf;
104
105 // write domain separator
106 std::copy(domain_separator_pop.begin(), domain_separator_pop.end(), std::back_inserter(challenge_buf));
107
108 // write the group generator
109 write(challenge_buf, G1::affine_one);
110
111 // write X twice as per the spec
112 write(challenge_buf, public_key);
113 write(challenge_buf, public_key);
114
115 // write R
116 write(challenge_buf, R);
117
118 // generate the raw bits of H_reg(X,X,R)
119 return Hash::hash(challenge_buf);
120 }
121};
122
123template <typename B, typename G1, typename Hash>
124inline void read(B& it, SchnorrProofOfPossession<G1, Hash>& proof_of_possession)
125{
126 read(it, proof_of_possession.challenge);
127 read(it, proof_of_possession.response);
128}
129
130template <typename B, typename G1, typename Hash>
131inline void write(B& buf, SchnorrProofOfPossession<G1, Hash> const& proof_of_possession)
132{
133 write(buf, proof_of_possession.challenge);
134 write(buf, proof_of_possession.response);
135}
136
137} // 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:18
static field random_element(numeric::RNG *engine=nullptr) noexcept
static field serialize_from_buffer(const uint8_t *buffer)
static constexpr field zero()