barretenberg
Loading...
Searching...
No Matches
proof_of_possession.hpp
1#pragma once
2
3#include <utility>
4
5#include "barretenberg/common/serialize.hpp"
6#include "schnorr.hpp"
7
8namespace crypto::schnorr {
9
18template <typename G1, typename Hash> struct ProofOfPossession {
19 using Fq = typename G1::coordinate_field;
20 using Fr = typename G1::subgroup_field;
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
28 Fr response = Fr::zero();
29
30 // restore default constructor to enable deserialization
31 ProofOfPossession() = default;
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`
52 Fr k = Fr::random_element();
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 serialize::write(challenge_buf, G1::affine_one);
110
111 // write X twice as per the spec
112 serialize::write(challenge_buf, public_key);
113 serialize::write(challenge_buf, public_key);
114
115 // write R
116 serialize::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, ProofOfPossession<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, ProofOfPossession<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 crypto::schnorr
Definition: affine_element.hpp:11
A proof of possession is a Schnorr proof of knowledge of a secret key corresponding to a given public...
Definition: proof_of_possession.hpp:18
ProofOfPossession(const key_pair &account)
Create a new proof of possession for a given account.
Definition: proof_of_possession.hpp:40
bool verify(const affine_element &public_key) const
verifies that an unserialized signature is valid
Definition: proof_of_possession.hpp:69
Definition: schnorr.hpp:17