Monero
crypto.h
Go to the documentation of this file.
1 // Copyright (c) 2014-2018, 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/thread/mutex.hpp>
36 #include <boost/thread/lock_guard.hpp>
37 #include <boost/optional.hpp>
38 #include <type_traits>
39 #include <vector>
40 
41 #include "common/pod-class.h"
42 #include "common/util.h"
43 #include "memwipe.h"
44 #include "mlocker.h"
45 #include "generic-ops.h"
46 #include "hex.h"
47 #include "span.h"
48 #include "hash.h"
49 
50 namespace crypto {
51 
52  extern "C" {
53 #include "random.h"
54  }
55 
56 #pragma pack(push, 1)
58  char data[32];
59  };
60 
62  char data[32];
63  };
64 
66  friend class crypto_ops;
67  };
68 
69  using secret_key = epee::mlocked<tools::scrubbed<ec_scalar>>;
70 
72  std::vector<public_key> keys;
73  int rows;
74  };
75 
77  std::vector<secret_key> keys;
78  int rows;
79  };
80 
82  int cols;
83  int rows;
84  std::vector<secret_keyV> column_vectors;
85  };
86 
88  friend class crypto_ops;
89  };
90 
92  friend class crypto_ops;
93  };
94 
96  ec_scalar c, r;
97  friend class crypto_ops;
98  };
99 #pragma pack(pop)
100 
101  void hash_to_scalar(const void *data, size_t length, ec_scalar &res);
102  void random32_unbiased(unsigned char *bytes);
103 
104  static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
105  sizeof(public_key) == 32 && sizeof(secret_key) == 32 &&
106  sizeof(key_derivation) == 32 && sizeof(key_image) == 32 &&
107  sizeof(signature) == 64, "Invalid structure size");
108 
109  class crypto_ops {
110  crypto_ops();
111  crypto_ops(const crypto_ops &);
112  void operator=(const crypto_ops &);
113  ~crypto_ops();
114 
115  static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
116  friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
117  static bool check_key(const public_key &);
118  friend bool check_key(const public_key &);
119  static bool secret_key_to_public_key(const secret_key &, public_key &);
120  friend bool secret_key_to_public_key(const secret_key &, public_key &);
121  static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
122  friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
123  static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
124  friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
125  static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
126  friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
127  static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
128  friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
129  static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &);
130  friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &);
131  static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
132  friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
133  static bool check_signature(const hash &, const public_key &, const signature &);
134  friend bool check_signature(const hash &, const public_key &, const signature &);
135  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 &);
136  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 &);
137  static bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &);
138  friend bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &);
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 
153  /* Generate N random bytes
154  */
155  inline void rand(size_t N, uint8_t *bytes) {
157  }
158 
159  /* Generate a value filled with random bytes.
160  */
161  template<typename T>
162  typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
163  typename std::remove_cv<T>::type res;
164  generate_random_bytes_thread_safe(sizeof(T), (uint8_t*)&res);
165  return res;
166  }
167 
168  /* Generate a new key pair
169  */
170  inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
171  return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
172  }
173 
174  /* Check a public key. Returns true if it is valid, false otherwise.
175  */
176  inline bool check_key(const public_key &key) {
177  return crypto_ops::check_key(key);
178  }
179 
180  /* Checks a private key and computes the corresponding public key.
181  */
182  inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
183  return crypto_ops::secret_key_to_public_key(sec, pub);
184  }
185 
186  /* To generate an ephemeral key used to send money to:
187  * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
188  * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
189  * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
190  * * 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).
191  */
192  inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
193  return crypto_ops::generate_key_derivation(key1, key2, derivation);
194  }
195  inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
196  const public_key &base, public_key &derived_key) {
197  return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
198  }
199  inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
200  return crypto_ops::derivation_to_scalar(derivation, output_index, res);
201  }
202  inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
203  const secret_key &base, secret_key &derived_key) {
204  crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
205  }
206  inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result) {
207  return crypto_ops::derive_subaddress_public_key(out_key, derivation, output_index, result);
208  }
209 
210  /* Generation and checking of a standard signature.
211  */
212  inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
213  crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
214  }
215  inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
216  return crypto_ops::check_signature(prefix_hash, pub, sig);
217  }
218 
219  /* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key
220  * derivation D, the signature proves the knowledge of the tx secret key r such that R=r*G and D=r*A
221  * 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
222  */
223  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) {
224  crypto_ops::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
225  }
226  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) {
227  return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig);
228  }
229 
230  /* To send money to a key:
231  * * The sender generates an ephemeral key and includes it in transaction output.
232  * * To spend the money, the receiver generates a key image from it.
233  * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
234  * 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.
235  */
236  inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
237  crypto_ops::generate_key_image(pub, sec, image);
238  }
239  inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
240  const public_key *const *pubs, std::size_t pubs_count,
241  const secret_key &sec, std::size_t sec_index,
242  signature *sig) {
243  crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
244  }
245  inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
246  const public_key *const *pubs, std::size_t pubs_count,
247  const signature *sig) {
248  return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
249  }
250 
251  /* Variants with vector<const public_key *> parameters.
252  */
253  inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
254  const std::vector<const public_key *> &pubs,
255  const secret_key &sec, std::size_t sec_index,
256  signature *sig) {
257  generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
258  }
259  inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
260  const std::vector<const public_key *> &pubs,
261  const signature *sig) {
262  return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
263  }
264 
265  inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
266  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
267  }
268  inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) {
269  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
270  }
271  inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
272  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
273  }
274  inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) {
275  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
276  }
277  inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) {
278  epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
279  }
280 
281  const extern crypto::public_key null_pkey;
282  const extern crypto::secret_key null_skey;
283 }
284 
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:199
POD_CLASS ec_point
Definition: crypto.h:57
const uint32_t T[512]
Definition: groestl_tables.h:33
#define CRYPTO_MAKE_COMPARABLE(type)
Definition: generic-ops.h:38
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &)
void derive_secret_key(const key_derivation &derivation, std::size_t output_index, const secret_key &base, secret_key &derived_key)
Definition: crypto.h:202
Definition: crypto.h:109
static bool secret_key_to_public_key(const secret_key &, public_key &)
Definition: crypto.cpp:164
static bool check_signature(const hash &, const public_key &, const signature &)
Definition: crypto.cpp:291
list B
Definition: base.py:26
static void generate_key_image(const public_key &, const secret_key &, key_image &)
Definition: crypto.cpp:483
POD_CLASS key_derivation
Definition: crypto.h:85
static bool check_key(const public_key &)
Definition: crypto.cpp:159
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:245
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:212
crypto namespace.
Definition: crypto.cpp:59
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:69
#define CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(type)
Definition: generic-ops.h:79
POD_CLASS secret_keyV
Definition: crypto.h:76
#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:192
void random32_unbiased(unsigned char *bytes)
Definition: crypto.cpp:111
static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &)
Definition: crypto.cpp:229
const crypto::secret_key null_skey
Definition: crypto.cpp:74
void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
Definition: crypto.cpp:92
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:223
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition: crypto.h:236
void rand(size_t N, uint8_t *bytes)
Definition: crypto.h:155
const crypto::public_key null_pkey
Definition: crypto.cpp:73
POD_CLASS public_keyM
Definition: crypto.h:81
POD_CLASS ec_scalar
Definition: crypto.h:61
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:206
static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
Definition: crypto.cpp:137
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:239
friend class crypto_ops
Definition: crypto.h:97
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:315
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:170
POD_CLASS public_key
Definition: crypto.h:63
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &)
Definition: crypto.cpp:174
Definition: base.py:1
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)
Definition: crypto.h:226
POD_CLASS signature
Definition: crypto.h:95
POD_CLASS key_image
Definition: crypto.h:89
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:195
bool check_key(const public_key &key)
Definition: crypto.h:176
void hash_to_scalar(const void *data, size_t length, ec_scalar &res)
Definition: crypto.cpp:127
static bool check_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const signature *)
static bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional< public_key > &, const public_key &, const signature &)
Definition: crypto.cpp:387
POD_CLASS hash
Definition: hash.h:49
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:84
std::ostream & operator<<(std::ostream &o, const crypto::public_key &v)
Definition: crypto.h:265
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:182
POD_CLASS public_keyV
Definition: crypto.h:71
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &)
Definition: crypto.cpp:261
#define CRYPTO_MAKE_HASHABLE(type)
Definition: generic-ops.h:75
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.cpp:189
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:215
int rows
Definition: crypto.h:73