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)
52
53 affine_element R = G1::one * k;
54
55 auto challenge_bytes = generate_challenge(public_key, R);
56 std::copy(challenge_bytes.begin(), challenge_bytes.end(), challenge.begin());
57
58 Fr challenge_fr = Fr::serialize_from_buffer(&challenge_bytes[0]);
59 response = k - challenge_fr * secret_key;
60 secure_erase_bytes(&k, sizeof(k));
61 secure_erase_bytes(&secret_key, sizeof(secret_key));
62 }
63
70 bool verify(const affine_element& public_key) const
71 {
72 Fr challenge_fr = Fr::serialize_from_buffer(&challenge[0]);
73 // this ensures that a default constructed proof is invalid
74 if (response.is_zero())
75 return false;
76
77 if (!public_key.on_curve() || public_key.is_point_at_infinity())
78 return false;
79
80 // R = e•pk + z•G
81 affine_element R = element(public_key) * challenge_fr + G1::one * response;
82 if (R.is_point_at_infinity())
83 return false;
84
85 // recompute the challenge e
86 auto challenge_computed = generate_challenge(public_key, R);
87 return std::equal(challenge.begin(), challenge.end(), challenge_computed.begin(), challenge_computed.end());
88 }
89
90 private:
98 static auto generate_challenge(const affine_element& public_key, const affine_element& R)
99 {
100 // Domain separation challenges
101 const std::string domain_separator_pop("h_reg");
102
103 // buffer containing (domain_sep, G, X, X, R)
104 std::vector<uint8_t> challenge_buf;
105
106 // write domain separator
107 std::copy(domain_separator_pop.begin(), domain_separator_pop.end(), std::back_inserter(challenge_buf));
108
109 // write the group generator
110 write(challenge_buf, G1::affine_one);
111
112 // write X twice as per the spec
113 write(challenge_buf, public_key);
114 write(challenge_buf, public_key);
115
116 // write R
117 write(challenge_buf, R);
118
119 // generate the raw bits of H_reg(X,X,R)
120 return Hash::hash(challenge_buf);
121 }
122};
123
124template <typename B, typename G1, typename Hash>
125inline void read(B& it, SchnorrProofOfPossession<G1, Hash>& proof_of_possession)
126{
127 read(it, proof_of_possession.challenge);
128 read(it, proof_of_possession.response);
129}
130
131template <typename B, typename G1, typename Hash>
132inline void write(B& buf, SchnorrProofOfPossession<G1, Hash> const& proof_of_possession)
133{
134 write(buf, proof_of_possession.challenge);
135 write(buf, proof_of_possession.response);
136}
137
138} // 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)
void secure_erase_bytes(void *ptr, size_t size)
Definition hmac.hpp:18
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()