Monero
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 
48 namespace 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 
116  class crypto_ops {
117  crypto_ops();
118  crypto_ops(const crypto_ops &);
119  void operator=(const crypto_ops &);
120  ~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>
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>
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>
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) {
215  return crypto_ops::check_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) {
221  return crypto_ops::secret_key_to_public_key(sec, 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) {
245  return crypto_ops::derive_subaddress_public_key(out_key, derivation, output_index, 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) {
311  crypto_ops::derive_view_tag(derivation, output_index, 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 
const char * res
Definition: hmac_keccak.cpp:42
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:237
POD_CLASS ec_point
Definition: crypto.h:55
const uint32_t T[512]
Definition: groestl_tables.h:36
#define CRYPTO_MAKE_COMPARABLE(type)
Definition: generic-ops.h:38
span< const std::uint8_t > as_byte_span(const T &src) noexcept
Definition: span.h:162
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &)
bool operator>(const public_key &p1, const public_key &p2)
Definition: crypto.h:337
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
Definition: crypto.h:116
static bool secret_key_to_public_key(const secret_key &, public_key &)
Definition: crypto.cpp:180
static bool check_signature(const hash &, const public_key &, const signature &)
Definition: crypto.cpp:319
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 &)
Definition: crypto.cpp:347
static void generate_key_image(const public_key &, const secret_key &, key_image &)
Definition: crypto.cpp:621
POD_CLASS key_derivation
Definition: crypto.h:88
static bool check_key(const public_key &)
Definition: crypto.cpp:175
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)
Definition: crypto.cpp:508
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
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:250
std::string data
Definition: base58.cpp:37
const char * key
Definition: hmac_keccak.cpp:40
int type
Definition: superscalar.cpp:50
crypto namespace.
Definition: crypto.cpp:60
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:72
POD_CLASS view_tag
Definition: crypto.h:103
#define CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(type)
Definition: generic-ops.h:79
tools::wallet2::message_signature_result_t result
Definition: signature.cpp:62
unsigned char uint8_t
Definition: stdint.h:124
POD_CLASS secret_keyV
Definition: crypto.h:79
#define POD_CLASS
Definition: pod-class.h:43
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:230
Definition: crypto.h:182
void random32_unbiased(unsigned char *bytes)
Definition: crypto.cpp:123
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition: crypto.h:202
static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &)
Definition: crypto.cpp:245
POD_CLASS public_key_memsafe
Definition: crypto.h:65
const crypto::secret_key null_skey
Definition: crypto.cpp:75
std::enable_if< std::is_integral< T >::value, T >::type rand_range(T range_min, T range_max)
Definition: crypto.h:193
void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
Definition: crypto.cpp:99
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
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition: crypto.h:277
void rand(size_t N, uint8_t *bytes)
Definition: crypto.h:167
constexpr uint32_t B
Definition: jit_compiler_a64.cpp:38
Definition: chaingen.h:294
const crypto::public_key null_pkey
Definition: crypto.cpp:74
static constexpr result_type max()
Definition: crypto.h:186
POD_CLASS public_keyM
Definition: crypto.h:84
POD_CLASS ec_scalar
Definition: crypto.h:59
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
static void derive_view_tag(const key_derivation &, std::size_t, view_tag &)
static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
Definition: crypto.cpp:153
void derive_view_tag(const key_derivation &derivation, std::size_t output_index, view_tag &vt)
Definition: crypto.h:310
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
friend class crypto_ops
Definition: crypto.h:100
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 &)
Definition: crypto.cpp:423
unsigned __int64 uint64_t
Definition: stdint.h:136
static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &)
secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
Definition: crypto.h:208
POD_CLASS public_key
Definition: crypto.h:61
version
Supported socks variants.
Definition: socks.h:57
r
Definition: testupnpigd.py:61
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &)
Definition: crypto.cpp:190
Definition: base.py:1
bool operator<(const public_key &p1, const public_key &p2)
Definition: crypto.h:336
POD_CLASS signature
Definition: crypto.h:98
static constexpr result_type min()
Definition: crypto.h:185
POD_CLASS key_image
Definition: crypto.h:92
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:16
Matcher< T > A()
Definition: gmock-matchers.h:3732
void operator=(const crypto_ops &)
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
bool check_key(const public_key &key)
Definition: crypto.h:214
Definition: mlocker.h:68
void hash_to_scalar(const void *data, size_t length, ec_scalar &res)
Definition: crypto.cpp:143
static bool check_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const signature *)
POD_CLASS hash
Definition: hash.h:48
static void generate_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *)
std::vector< secret_keyV > column_vectors
Definition: crypto.h:87
std::ostream & operator<<(std::ostream &o, const crypto::public_key &v)
Definition: crypto.h:314
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:220
POD_CLASS public_keyV
Definition: crypto.h:74
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
public_key_memsafe(const public_key &original)
Definition: crypto.h:69
result_type operator()() const
Definition: crypto.h:187
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &)
Definition: crypto.cpp:290
void add_extra_entropy_thread_safe(const void *ptr, size_t bytes)
Definition: crypto.cpp:105
#define CRYPTO_MAKE_HASHABLE(type)
Definition: generic-ops.h:75
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
uint64_t result_type
Definition: crypto.h:184
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.cpp:205
static void formatted(std::ostream &out, const span< const std::uint8_t > src)
Append < + src + > as hex to out.
Definition: hex.cpp:77
c
Definition: pymoduletest.py:79
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:253
int rows
Definition: crypto.h:76