Monero
crypto.h
Go to the documentation of this file.
1 // Copyright (c) 2014-2020, 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 
67  using secret_key = epee::mlocked<tools::scrubbed<ec_scalar>>;
68 
70  std::vector<public_key> keys;
71  int rows;
72  };
73 
75  std::vector<secret_key> keys;
76  int rows;
77  };
78 
80  int cols;
81  int rows;
82  std::vector<secret_keyV> column_vectors;
83  };
84 
86  friend class crypto_ops;
87  };
88 
90  friend class crypto_ops;
91  };
92 
94  ec_scalar c, r;
95  friend class crypto_ops;
96  };
97 #pragma pack(pop)
98 
99  void hash_to_scalar(const void *data, size_t length, ec_scalar &res);
100  void random32_unbiased(unsigned char *bytes);
101 
102  static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
103  sizeof(public_key) == 32 && sizeof(secret_key) == 32 &&
104  sizeof(key_derivation) == 32 && sizeof(key_image) == 32 &&
105  sizeof(signature) == 64, "Invalid structure size");
106 
107  class crypto_ops {
110  void operator=(const crypto_ops &);
112 
113  static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
114  friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
115  static bool check_key(const public_key &);
116  friend bool check_key(const public_key &);
117  static bool secret_key_to_public_key(const secret_key &, public_key &);
118  friend bool secret_key_to_public_key(const secret_key &, public_key &);
119  static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
120  friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
121  static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
122  friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
123  static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
124  friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
125  static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
126  friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
127  static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &);
128  friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &);
129  static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
130  friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
131  static bool check_signature(const hash &, const public_key &, const signature &);
132  friend bool check_signature(const hash &, const public_key &, const signature &);
133  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 &);
134  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 &);
135  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 &);
136  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 &);
137  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);
138  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);
139  static void generate_key_image(const public_key &, const secret_key &, key_image &);
140  friend void generate_key_image(const public_key &, const secret_key &, key_image &);
141  static void generate_ring_signature(const hash &, const key_image &,
142  const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
143  friend void generate_ring_signature(const hash &, const key_image &,
144  const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
145  static bool check_ring_signature(const hash &, const key_image &,
146  const public_key *const *, std::size_t, const signature *);
147  friend bool check_ring_signature(const hash &, const key_image &,
148  const public_key *const *, std::size_t, const signature *);
149  };
150 
151  void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes);
152  void add_extra_entropy_thread_safe(const void *ptr, size_t bytes);
153 
154  /* Generate N random bytes
155  */
156  inline void rand(size_t N, uint8_t *bytes) {
158  }
159 
160  /* Generate a value filled with random bytes.
161  */
162  template<typename T>
163  typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
164  typename std::remove_cv<T>::type res;
165  generate_random_bytes_thread_safe(sizeof(T), (uint8_t*)&res);
166  return res;
167  }
168 
169  /* UniformRandomBitGenerator using crypto::rand<uint64_t>()
170  */
172  {
173  typedef uint64_t result_type;
174  static constexpr result_type min() { return 0; }
175  static constexpr result_type max() { return result_type(-1); }
176  result_type operator()() const { return crypto::rand<result_type>(); }
177  };
178 
179  /* Generate a random value between range_min and range_max
180  */
181  template<typename T>
182  typename std::enable_if<std::is_integral<T>::value, T>::type rand_range(T range_min, T range_max) {
184  std::uniform_int_distribution<T> dis(range_min, range_max);
185  return dis(rd);
186  }
187 
188  /* Generate a random index between 0 and sz-1
189  */
190  template<typename T>
191  typename std::enable_if<std::is_unsigned<T>::value, T>::type rand_idx(T sz) {
192  return crypto::rand_range<T>(0, sz-1);
193  }
194 
195  /* Generate a new key pair
196  */
197  inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
198  return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
199  }
200 
201  /* Check a public key. Returns true if it is valid, false otherwise.
202  */
203  inline bool check_key(const public_key &key) {
204  return crypto_ops::check_key(key);
205  }
206 
207  /* Checks a private key and computes the corresponding public key.
208  */
209  inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
210  return crypto_ops::secret_key_to_public_key(sec, pub);
211  }
212 
213  /* To generate an ephemeral key used to send money to:
214  * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
215  * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
216  * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
217  * * 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).
218  */
219  inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
220  return crypto_ops::generate_key_derivation(key1, key2, derivation);
221  }
222  inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
223  const public_key &base, public_key &derived_key) {
224  return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
225  }
226  inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
227  return crypto_ops::derivation_to_scalar(derivation, output_index, res);
228  }
229  inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
230  const secret_key &base, secret_key &derived_key) {
231  crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
232  }
233  inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result) {
234  return crypto_ops::derive_subaddress_public_key(out_key, derivation, output_index, result);
235  }
236 
237  /* Generation and checking of a standard signature.
238  */
239  inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
240  crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
241  }
242  inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
243  return crypto_ops::check_signature(prefix_hash, pub, sig);
244  }
245 
246  /* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key
247  * derivation D, the signature proves the knowledge of the tx secret key r such that R=r*G and D=r*A
248  * 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
249  */
250  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) {
251  crypto_ops::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
252  }
253  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) {
254  crypto_ops::generate_tx_proof_v1(prefix_hash, R, A, B, D, r, sig);
255  }
256  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) {
257  return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig, version);
258  }
259 
260  /* To send money to a key:
261  * * The sender generates an ephemeral key and includes it in transaction output.
262  * * To spend the money, the receiver generates a key image from it.
263  * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
264  * 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.
265  */
266  inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
267  crypto_ops::generate_key_image(pub, sec, image);
268  }
269  inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
270  const public_key *const *pubs, std::size_t pubs_count,
271  const secret_key &sec, std::size_t sec_index,
272  signature *sig) {
273  crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
274  }
275  inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
276  const public_key *const *pubs, std::size_t pubs_count,
277  const signature *sig) {
278  return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
279  }
280 
281  /* Variants with vector<const public_key *> parameters.
282  */
283  inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
284  const std::vector<const public_key *> &pubs,
285  const secret_key &sec, std::size_t sec_index,
286  signature *sig) {
287  generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
288  }
289  inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
290  const std::vector<const public_key *> &pubs,
291  const signature *sig) {
292  return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
293  }
294 
295  inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
296  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
297  }
298  inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) {
299  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
300  }
301  inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
302  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
303  }
304  inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) {
305  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
306  }
307  inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) {
308  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
309  }
310 
311  const extern crypto::public_key null_pkey;
312  const extern crypto::secret_key null_skey;
313 }
314 
Definition: crypto.h:107
static bool check_key(const public_key &)
Definition: crypto.cpp:175
void operator=(const crypto_ops &)
static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &)
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
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &)
Definition: crypto.cpp:290
static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &)
Definition: crypto.cpp:245
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &)
crypto_ops(const crypto_ops &)
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.cpp:205
static bool check_signature(const hash &, const public_key &, const signature &)
Definition: crypto.cpp:319
static void generate_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *)
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
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
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &)
Definition: crypto.cpp:190
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 bool check_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const signature *)
static bool secret_key_to_public_key(const secret_key &, public_key &)
Definition: crypto.cpp:180
static void generate_key_image(const public_key &, const secret_key &, key_image &)
Definition: crypto.cpp:621
#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
const uint32_t T[512]
Definition: groestl_tables.h:36
Definition: base.py:1
list B
Definition: base.py:26
crypto namespace.
Definition: crypto.cpp:60
POD_CLASS secret_keyV
Definition: crypto.h:74
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:239
POD_CLASS public_keyM
Definition: crypto.h:79
bool check_key(const public_key &key)
Definition: crypto.h:203
void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
Definition: crypto.cpp:99
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:250
POD_CLASS signature
Definition: crypto.h:93
const crypto::secret_key null_skey
Definition: crypto.cpp:75
POD_CLASS public_keyV
Definition: crypto.h:69
std::enable_if< std::is_integral< T >::value, T >::type rand_range(T range_min, T range_max)
Definition: crypto.h:182
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:67
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:233
POD_CLASS key_derivation
Definition: crypto.h:83
secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
Definition: crypto.h:197
void derive_secret_key(const key_derivation &derivation, std::size_t output_index, const secret_key &base, secret_key &derived_key)
Definition: crypto.h:229
std::vector< secret_keyV > column_vectors
Definition: crypto.h:82
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:219
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:269
POD_CLASS public_key
Definition: crypto.h:61
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:256
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:222
void rand(size_t N, uint8_t *bytes)
Definition: crypto.h:156
POD_CLASS key_image
Definition: crypto.h:87
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:242
POD_CLASS ec_scalar
Definition: crypto.h:59
std::ostream & operator<<(std::ostream &o, const crypto::public_key &v)
Definition: crypto.h:295
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:209
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition: crypto.h:191
void hash_to_scalar(const void *data, size_t length, ec_scalar &res)
Definition: crypto.cpp:143
int rows
Definition: crypto.h:71
POD_CLASS hash
Definition: hash.h:48
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition: crypto.h:266
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:253
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:226
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:275
version
Supported socks variants.
Definition: socks.h:58
#define POD_CLASS
Definition: pod-class.h:43
Definition: crypto.h:172
static constexpr result_type min()
Definition: crypto.h:174
result_type operator()() const
Definition: crypto.h:176
uint64_t result_type
Definition: crypto.h:173
static constexpr result_type max()
Definition: crypto.h:175