Monero
Loading...
Searching...
No Matches
crypto.h
Go to the documentation of this file.
1// Copyright (c) 2014-2022, The Monero Project
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification, are
6// permitted provided that the following conditions are met:
7//
8// 1. Redistributions of source code must retain the above copyright notice, this list of
9// conditions and the following disclaimer.
10//
11// 2. Redistributions in binary form must reproduce the above copyright notice, this list
12// of conditions and the following disclaimer in the documentation and/or other
13// materials provided with the distribution.
14//
15// 3. Neither the name of the copyright holder nor the names of its contributors may be
16// used to endorse or promote products derived from this software without specific
17// prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
30
31#pragma once
32
33#include <cstddef>
34#include <iostream>
35#include <boost/optional.hpp>
36#include <type_traits>
37#include <vector>
38#include <random>
39
40#include "common/pod-class.h"
41#include "memwipe.h"
42#include "mlocker.h"
43#include "generic-ops.h"
44#include "hex.h"
45#include "span.h"
46#include "hash.h"
47
48namespace crypto {
49
50 extern "C" {
51#include "random.h"
52 }
53
54#pragma pack(push, 1)
56 char data[32];
57 };
58
60 char data[32];
61 };
62
64 friend class crypto_ops;
65 };
66
68 public_key_memsafe() = default;
69 public_key_memsafe(const public_key &original) { memcpy(this->data, original.data, 32); }
70 };
71
73
75 std::vector<public_key> keys;
76 int rows;
77 };
78
80 std::vector<secret_key> keys;
81 int rows;
82 };
83
85 int cols;
86 int rows;
87 std::vector<secret_keyV> column_vectors;
88 };
89
91 friend class crypto_ops;
92 };
93
95 friend class crypto_ops;
96 };
97
99 ec_scalar c, r;
100 friend class crypto_ops;
101 };
102
104 char data;
105 };
106#pragma pack(pop)
107
108 void hash_to_scalar(const void *data, size_t length, ec_scalar &res);
109 void random32_unbiased(unsigned char *bytes);
110
111 static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
112 sizeof(public_key) == 32 && sizeof(public_key_memsafe) == 32 && sizeof(secret_key) == 32 &&
113 sizeof(key_derivation) == 32 && sizeof(key_image) == 32 &&
114 sizeof(signature) == 64 && sizeof(view_tag) == 1, "Invalid structure size");
115
119 void operator=(const crypto_ops &);
121
122 static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
123 friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
124 static bool check_key(const public_key &);
125 friend bool check_key(const public_key &);
126 static bool secret_key_to_public_key(const secret_key &, public_key &);
127 friend bool secret_key_to_public_key(const secret_key &, public_key &);
128 static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
129 friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
130 static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
131 friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
132 static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
133 friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
134 static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
135 friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
136 static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &);
137 friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &);
138 static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
139 friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
140 static bool check_signature(const hash &, const public_key &, const signature &);
141 friend bool check_signature(const hash &, const public_key &, const signature &);
142 static void generate_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
143 friend void generate_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
144 static void generate_tx_proof_v1(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
145 friend void generate_tx_proof_v1(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
146 static bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &, const int);
147 friend bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &, const int);
148 static void generate_key_image(const public_key &, const secret_key &, key_image &);
149 friend void generate_key_image(const public_key &, const secret_key &, key_image &);
150 static void generate_ring_signature(const hash &, const key_image &,
151 const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
152 friend void generate_ring_signature(const hash &, const key_image &,
153 const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
154 static bool check_ring_signature(const hash &, const key_image &,
155 const public_key *const *, std::size_t, const signature *);
156 friend bool check_ring_signature(const hash &, const key_image &,
157 const public_key *const *, std::size_t, const signature *);
158 static void derive_view_tag(const key_derivation &, std::size_t, view_tag &);
159 friend void derive_view_tag(const key_derivation &, std::size_t, view_tag &);
160 };
161
162 void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes);
163 void add_extra_entropy_thread_safe(const void *ptr, size_t bytes);
164
165 /* Generate N random bytes
166 */
167 inline void rand(size_t N, uint8_t *bytes) {
169 }
170
171 /* Generate a value filled with random bytes.
172 */
173 template<typename T>
174 typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
175 typename std::remove_cv<T>::type res;
177 return res;
178 }
179
180 /* UniformRandomBitGenerator using crypto::rand<uint64_t>()
181 */
183 {
185 static constexpr result_type min() { return 0; }
186 static constexpr result_type max() { return result_type(-1); }
187 result_type operator()() const { return crypto::rand<result_type>(); }
188 };
189
190 /* Generate a random value between range_min and range_max
191 */
192 template<typename T>
193 typename std::enable_if<std::is_integral<T>::value, T>::type rand_range(T range_min, T range_max) {
195 std::uniform_int_distribution<T> dis(range_min, range_max);
196 return dis(rd);
197 }
198
199 /* Generate a random index between 0 and sz-1
200 */
201 template<typename T>
202 typename std::enable_if<std::is_unsigned<T>::value, T>::type rand_idx(T sz) {
203 return crypto::rand_range<T>(0, sz-1);
204 }
205
206 /* Generate a new key pair
207 */
208 inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
209 return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
210 }
211
212 /* Check a public key. Returns true if it is valid, false otherwise.
213 */
214 inline bool check_key(const public_key &key) {
216 }
217
218 /* Checks a private key and computes the corresponding public key.
219 */
220 inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
222 }
223
224 /* To generate an ephemeral key used to send money to:
225 * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
226 * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
227 * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
228 * * The receiver can either derive the public key (to check that the transaction is addressed to him) or the private key (to spend the money).
229 */
230 inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
231 return crypto_ops::generate_key_derivation(key1, key2, derivation);
232 }
233 inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
234 const public_key &base, public_key &derived_key) {
235 return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
236 }
237 inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
239 }
240 inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
241 const secret_key &base, secret_key &derived_key) {
242 crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
243 }
244 inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result) {
246 }
247
248 /* Generation and checking of a standard signature.
249 */
250 inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
251 crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
252 }
253 inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
254 return crypto_ops::check_signature(prefix_hash, pub, sig);
255 }
256
257 /* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key
258 * derivation D, the signature proves the knowledge of the tx secret key r such that R=r*G and D=r*A
259 * When the recipient's address is a subaddress, the tx pubkey R is defined as R=r*B where B is the recipient's spend pubkey
260 */
261 inline void generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, signature &sig) {
262 crypto_ops::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
263 }
264 inline void generate_tx_proof_v1(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, signature &sig) {
265 crypto_ops::generate_tx_proof_v1(prefix_hash, R, A, B, D, r, sig);
266 }
267 inline bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig, const int version) {
268 return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig, version);
269 }
270
271 /* To send money to a key:
272 * * The sender generates an ephemeral key and includes it in transaction output.
273 * * To spend the money, the receiver generates a key image from it.
274 * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
275 * To check the signature, it is necessary to collect all the keys that were used to generate it. To detect double spends, it is necessary to check that each key image is used at most once.
276 */
277 inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
278 crypto_ops::generate_key_image(pub, sec, image);
279 }
280 inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
281 const public_key *const *pubs, std::size_t pubs_count,
282 const secret_key &sec, std::size_t sec_index,
283 signature *sig) {
284 crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
285 }
286 inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
287 const public_key *const *pubs, std::size_t pubs_count,
288 const signature *sig) {
289 return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
290 }
291
292 /* Variants with vector<const public_key *> parameters.
293 */
294 inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
295 const std::vector<const public_key *> &pubs,
296 const secret_key &sec, std::size_t sec_index,
297 signature *sig) {
298 generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
299 }
300 inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
301 const std::vector<const public_key *> &pubs,
302 const signature *sig) {
303 return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
304 }
305
306 /* Derive a 1-byte view tag from the sender-receiver shared secret to reduce scanning time.
307 * When scanning outputs that were not sent to the user, checking the view tag for a match removes the need to proceed with expensive EC operations
308 * for an expected 99.6% of outputs (expected false positive rate = 1/2^8 = 1/256 = 0.4% = 100% - 99.6%).
309 */
310 inline void derive_view_tag(const key_derivation &derivation, std::size_t output_index, view_tag &vt) {
312 }
313
314 inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
316 }
317 inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) {
319 }
320 inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
322 }
323 inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) {
325 }
326 inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) {
328 }
329 inline std::ostream &operator <<(std::ostream &o, const crypto::view_tag &v) {
331 }
332
333 const extern crypto::public_key null_pkey;
334 const extern crypto::secret_key null_skey;
335
336 inline bool operator<(const public_key &p1, const public_key &p2) { return memcmp(&p1, &p2, sizeof(public_key)) < 0; }
337 inline bool operator>(const public_key &p1, const public_key &p2) { return p2 < p1; }
338}
339
340CRYPTO_MAKE_HASHABLE(public_key)
342CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe)
343CRYPTO_MAKE_HASHABLE(key_image)
344CRYPTO_MAKE_COMPARABLE(signature)
Definition: crypto.h:116
void operator=(const crypto_ops &)
friend bool secret_key_to_public_key(const secret_key &, public_key &)
Definition: crypto.h:220
static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &)
friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:237
friend void generate_key_image(const public_key &, const secret_key &, key_image &)
Definition: crypto.h:277
friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &)
Definition: crypto.h:244
friend void generate_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional< public_key > &, const public_key &, const secret_key &, signature &)
Definition: crypto.h:261
friend void derive_view_tag(const key_derivation &, std::size_t, view_tag &)
Definition: crypto.h:310
friend bool check_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const signature *)
Definition: crypto.h:286
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &)
friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &)
Definition: crypto.h:250
static void derive_view_tag(const key_derivation &, std::size_t, view_tag &)
crypto_ops(const crypto_ops &)
friend void generate_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *)
Definition: crypto.h:280
friend void generate_tx_proof_v1(const hash &, const public_key &, const public_key &, const boost::optional< public_key > &, const public_key &, const secret_key &, signature &)
Definition: crypto.h:264
friend bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional< public_key > &, const public_key &, const signature &, const int)
Definition: crypto.h:267
static void generate_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *)
friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &)
Definition: crypto.h:233
static bool check_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const signature *)
friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &)
Definition: crypto.h:240
friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &)
Definition: crypto.h:230
friend bool check_key(const public_key &)
Definition: crypto.h:214
friend bool check_signature(const hash &, const public_key &, const signature &)
Definition: crypto.h:253
friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key, bool recover)
Definition: crypto.h:208
#define CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(type)
Definition: generic-ops.h:79
#define CRYPTO_MAKE_COMPARABLE(type)
Definition: generic-ops.h:38
#define CRYPTO_MAKE_HASHABLE(type)
Definition: generic-ops.h:75
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:16
const char * res
Definition: hmac_keccak.cpp:42
const char * key
Definition: hmac_keccak.cpp:40
static int version
Definition: mdb_load.c:29
Definition: base.py:1
crypto namespace.
Definition: crypto.cpp:60
POD_CLASS secret_keyV
Definition: crypto.h:79
void add_extra_entropy_thread_safe(const void *ptr, size_t bytes)
Definition: crypto.cpp:105
const crypto::public_key null_pkey
Definition: crypto.cpp:74
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:250
POD_CLASS public_keyM
Definition: crypto.h:84
void derive_view_tag(const key_derivation &derivation, std::size_t output_index, view_tag &vt)
Definition: crypto.h:310
bool check_key(const public_key &key)
Definition: crypto.h:214
void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
Definition: crypto.cpp:99
std::enable_if< std::is_pod< T >::value, T >::type rand()
Definition: crypto.h:174
POD_CLASS ec_point
Definition: crypto.h:55
void generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional< public_key > &B, const public_key &D, const secret_key &r, signature &sig)
Definition: crypto.h:261
POD_CLASS signature
Definition: crypto.h:98
const crypto::secret_key null_skey
Definition: crypto.cpp:75
bool operator>(const public_key &p1, const public_key &p2)
Definition: crypto.h:337
std::enable_if< std::is_integral< T >::value, T >::type rand_range(T range_min, T range_max)
Definition: crypto.h:193
POD_CLASS public_keyV
Definition: crypto.h:74
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:72
bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result)
Definition: crypto.h:244
POD_CLASS key_derivation
Definition: crypto.h:91
POD_CLASS view_tag
Definition: crypto.h:103
POD_CLASS public_key_memsafe
Definition: crypto.h:68
secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
Definition: crypto.h:208
void derive_secret_key(const key_derivation &derivation, std::size_t output_index, const secret_key &base, secret_key &derived_key)
Definition: crypto.h:240
std::vector< secret_keyV > column_vectors
Definition: crypto.h:87
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:230
void generate_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const secret_key &sec, std::size_t sec_index, signature *sig)
Definition: crypto.h:280
POD_CLASS public_key
Definition: crypto.h:64
bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional< public_key > &B, const public_key &D, const signature &sig, const int version)
Definition: crypto.h:267
void random32_unbiased(unsigned char *bytes)
Definition: crypto.cpp:123
bool derive_public_key(const key_derivation &derivation, std::size_t output_index, const public_key &base, public_key &derived_key)
Definition: crypto.h:233
std::ostream & operator<<(std::ostream &o, const crypto::public_key &v)
Definition: crypto.h:314
POD_CLASS key_image
Definition: crypto.h:95
bool operator<(const public_key &p1, const public_key &p2)
Definition: crypto.h:336
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:253
POD_CLASS ec_scalar
Definition: crypto.h:59
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:220
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition: crypto.h:202
void hash_to_scalar(const void *data, size_t length, ec_scalar &res)
Definition: crypto.cpp:143
int rows
Definition: crypto.h:76
POD_CLASS hash
Definition: hash.h:48
void generate_tx_proof_v1(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional< public_key > &B, const public_key &D, const secret_key &r, signature &sig)
Definition: crypto.h:264
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:237
bool check_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const signature *sig)
Definition: crypto.h:286
span< const std::uint8_t > as_byte_span(const T &src) noexcept
Definition: span.h:152
#define POD_CLASS
Definition: pod-class.h:43
tools::wallet2::message_signature_result_t result
Definition: signature.cpp:62
unsigned char uint8_t
Definition: stdint.h:124
unsigned __int64 uint64_t
Definition: stdint.h:136
Definition: crypto.h:183
static constexpr result_type min()
Definition: crypto.h:185
result_type operator()() const
Definition: crypto.h:187
uint64_t result_type
Definition: crypto.h:184
static constexpr result_type max()
Definition: crypto.h:186
Definition: mlocker.h:68
static void formatted(std::ostream &out, const span< const std::uint8_t > src)
Append < + src + > as hex to out.
Definition: hex.cpp:77
Definition: chaingen.h:294
std::string data
Definition: base58.cpp:37
static crypto::key_image generate_key_image()
Definition: ringdb.cpp:55
#define T(x)