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 T rand() {
175 static_assert(std::is_standard_layout<T>(), "cannot write random bytes into non-standard layout type");
176 static_assert(std::is_trivially_copyable<T>(), "cannot write random bytes into non-trivially copyable type");
177 typename std::remove_cv<T>::type res;
179 return res;
180 }
181
182 /* UniformRandomBitGenerator using crypto::rand<uint64_t>()
183 */
185 {
187 static constexpr result_type min() { return 0; }
188 static constexpr result_type max() { return result_type(-1); }
190 };
191
192 /* Generate a random value between range_min and range_max
193 */
194 template<typename T>
195 typename std::enable_if<std::is_integral<T>::value, T>::type rand_range(T range_min, T range_max) {
197 std::uniform_int_distribution<T> dis(range_min, range_max);
198 return dis(rd);
199 }
200
201 /* Generate a random index between 0 and sz-1
202 */
203 template<typename T>
204 typename std::enable_if<std::is_unsigned<T>::value, T>::type rand_idx(T sz) {
205 return crypto::rand_range<T>(0, sz-1);
206 }
207
208 /* Generate a new key pair
209 */
210 inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
211 return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
212 }
213
214 /* Check a public key. Returns true if it is valid, false otherwise.
215 */
216 inline bool check_key(const public_key &key) {
218 }
219
220 /* Checks a private key and computes the corresponding public key.
221 */
222 inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
224 }
225
226 /* To generate an ephemeral key used to send money to:
227 * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
228 * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
229 * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
230 * * 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).
231 */
232 inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
233 return crypto_ops::generate_key_derivation(key1, key2, derivation);
234 }
235 inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
236 const public_key &base, public_key &derived_key) {
237 return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
238 }
239 inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
241 }
242 inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
243 const secret_key &base, secret_key &derived_key) {
244 crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
245 }
246 inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result) {
248 }
249
250 /* Generation and checking of a standard signature.
251 */
252 inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
253 crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
254 }
255 inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
256 return crypto_ops::check_signature(prefix_hash, pub, sig);
257 }
258
259 /* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key
260 * derivation D, the signature proves the knowledge of the tx secret key r such that R=r*G and D=r*A
261 * 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
262 */
263 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) {
264 crypto_ops::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
265 }
266 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) {
267 crypto_ops::generate_tx_proof_v1(prefix_hash, R, A, B, D, r, sig);
268 }
269 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) {
270 return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig, version);
271 }
272
273 /* To send money to a key:
274 * * The sender generates an ephemeral key and includes it in transaction output.
275 * * To spend the money, the receiver generates a key image from it.
276 * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
277 * 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.
278 */
279 inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
280 crypto_ops::generate_key_image(pub, sec, image);
281 }
282 inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
283 const public_key *const *pubs, std::size_t pubs_count,
284 const secret_key &sec, std::size_t sec_index,
285 signature *sig) {
286 crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
287 }
288 inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
289 const public_key *const *pubs, std::size_t pubs_count,
290 const signature *sig) {
291 return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
292 }
293
294 /* Variants with vector<const public_key *> parameters.
295 */
296 inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
297 const std::vector<const public_key *> &pubs,
298 const secret_key &sec, std::size_t sec_index,
299 signature *sig) {
300 generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
301 }
302 inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
303 const std::vector<const public_key *> &pubs,
304 const signature *sig) {
305 return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
306 }
307
308 /* Derive a 1-byte view tag from the sender-receiver shared secret to reduce scanning time.
309 * 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
310 * for an expected 99.6% of outputs (expected false positive rate = 1/2^8 = 1/256 = 0.4% = 100% - 99.6%).
311 */
312 inline void derive_view_tag(const key_derivation &derivation, std::size_t output_index, view_tag &vt) {
314 }
315
316 inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
318 }
319 /* Do NOT overload the << operator for crypto::secret_key here. Use secret_key_explicit_print_ref
320 * instead to prevent accidental implicit dumping of secret key material to the logs (which has
321 * happened before). For the same reason, do not overload it for crypto::ec_scalar either since
322 * crypto::secret_key is a subclass. I'm not sorry that it's obtuse; that's the point, bozo.
323 */
325 inline std::ostream &operator <<(std::ostream &o, const secret_key_explicit_print_ref v) {
326 epee::to_hex::formatted(o, epee::as_byte_span(unwrap(unwrap(v.sk)))); return o;
327 }
328 inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
330 }
331 inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) {
333 }
334 inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) {
336 }
337 inline std::ostream &operator <<(std::ostream &o, const crypto::view_tag &v) {
339 }
340
341 const extern crypto::public_key null_pkey;
342 const extern crypto::secret_key null_skey;
343
344 inline bool operator<(const public_key &p1, const public_key &p2) { return memcmp(&p1, &p2, sizeof(public_key)) < 0; }
345 inline bool operator>(const public_key &p1, const public_key &p2) { return p2 < p1; }
346}
347
348CRYPTO_MAKE_HASHABLE(public_key)
350CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe)
351CRYPTO_MAKE_HASHABLE(key_image)
352CRYPTO_MAKE_COMPARABLE(signature)
Definition crypto.h:116
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 &)
static void derive_view_tag(const key_derivation &, std::size_t, view_tag &)
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:84
#define CRYPTO_MAKE_COMPARABLE(type)
Definition generic-ops.h:39
#define CRYPTO_MAKE_HASHABLE(type)
Definition generic-ops.h:80
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:252
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:312
bool check_key(const public_key &key)
Definition crypto.h:216
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:263
T rand()
Definition crypto.h:174
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:345
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:72
std::enable_if< std::is_integral< T >::value, T >::type rand_range(T range_min, T range_max)
Definition crypto.h:195
unsigned char uint8_t
Definition hash.h:125
POD_CLASS public_keyV
Definition crypto.h:74
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:246
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:210
void derive_secret_key(const key_derivation &derivation, std::size_t output_index, const secret_key &base, secret_key &derived_key)
Definition crypto.h:242
std::vector< secret_keyV > column_vectors
Definition crypto.h:87
unsigned __int64 uint64_t
Definition hash.h:137
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition crypto.h:232
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:282
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:269
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:235
std::ostream & operator<<(std::ostream &o, const crypto::public_key &v)
Definition crypto.h:316
POD_CLASS key_image
Definition crypto.h:95
bool operator<(const public_key &p1, const public_key &p2)
Definition crypto.h:344
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition crypto.h:255
POD_CLASS ec_scalar
Definition crypto.h:59
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition crypto.h:222
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition crypto.h:204
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:49
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:266
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition crypto.h:239
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:288
span< const std::uint8_t > as_byte_span(const T &src) noexcept
Definition span.h:161
#define POD_CLASS
Definition pod-class.h:43
tools::wallet2::message_signature_result_t result
Definition signature.cpp:62
Definition crypto.h:185
static constexpr result_type min()
Definition crypto.h:187
result_type operator()() const
Definition crypto.h:189
uint64_t result_type
Definition crypto.h:186
static constexpr result_type max()
Definition crypto.h:188
const crypto::secret_key & sk
Definition crypto.h:324
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)