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
116 static const ec_point EC_I = {1};
117
121 void operator=(const crypto_ops &);
123
124 static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
125 friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
126 static bool check_key(const public_key &);
127 friend bool check_key(const public_key &);
128 static bool secret_key_to_public_key(const secret_key &, public_key &);
129 friend bool secret_key_to_public_key(const secret_key &, public_key &);
130 static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
131 friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
132 static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
133 friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
134 static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
135 friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
136 static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
137 friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
138 static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &);
139 friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &);
140 static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
141 friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
142 static bool check_signature(const hash &, const public_key &, const signature &);
143 friend bool check_signature(const hash &, const public_key &, const signature &);
144 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 &);
145 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 &);
146 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 &);
147 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 &);
148 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);
149 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);
150 static void generate_key_image(const public_key &, const secret_key &, key_image &);
151 friend void generate_key_image(const public_key &, const secret_key &, key_image &);
152 static 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 friend void generate_ring_signature(const hash &, const key_image &,
155 const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
156 static bool check_ring_signature(const hash &, const key_image &,
157 const public_key *const *, std::size_t, const signature *);
158 friend bool check_ring_signature(const hash &, const key_image &,
159 const public_key *const *, std::size_t, const signature *);
160 static void derive_view_tag(const key_derivation &, std::size_t, view_tag &);
161 friend void derive_view_tag(const key_derivation &, std::size_t, view_tag &);
162 };
163
164 void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes);
165 void add_extra_entropy_thread_safe(const void *ptr, size_t bytes);
166
167 /* Generate N random bytes
168 */
169 inline void rand(size_t N, uint8_t *bytes) {
171 }
172
173 /* Generate a value filled with random bytes.
174 */
175 template<typename T>
176 T rand() {
177 static_assert(std::is_standard_layout<T>(), "cannot write random bytes into non-standard layout type");
178 static_assert(std::is_trivially_copyable<T>(), "cannot write random bytes into non-trivially copyable type");
179 typename std::remove_cv<T>::type res;
181 return res;
182 }
183
184 /* UniformRandomBitGenerator using crypto::rand<uint64_t>()
185 */
187 {
189 static constexpr result_type min() { return 0; }
190 static constexpr result_type max() { return result_type(-1); }
192 };
193
194 /* Generate a random value between range_min and range_max
195 */
196 template<typename T>
197 typename std::enable_if<std::is_integral<T>::value, T>::type rand_range(T range_min, T range_max) {
199 std::uniform_int_distribution<T> dis(range_min, range_max);
200 return dis(rd);
201 }
202
203 /* Generate a random index between 0 and sz-1
204 */
205 template<typename T>
206 typename std::enable_if<std::is_unsigned<T>::value, T>::type rand_idx(T sz) {
207 return crypto::rand_range<T>(0, sz-1);
208 }
209
210 /* Generate a new key pair
211 */
212 inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
213 return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
214 }
215
216 /* Check a public key. Returns true if it is valid, false otherwise.
217 */
218 inline bool check_key(const public_key &key) {
219 return crypto_ops::check_key(key);
220 }
221
222 bool get_valid_torsion_cleared_point_vartime(const ec_point &point, ec_point &torsion_cleared_out);
223 // Return a canonical key in the prime-order subgroup, or identity on decode failure.
225
226 /* Checks a private key and computes the corresponding public key.
227 */
228 inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
230 }
231
232 /* To generate an ephemeral key used to send money to:
233 * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
234 * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
235 * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
236 * * 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).
237 */
238 inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
239 return crypto_ops::generate_key_derivation(key1, key2, derivation);
240 }
241 inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
242 const public_key &base, public_key &derived_key) {
243 return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
244 }
245 inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
246 return crypto_ops::derivation_to_scalar(derivation, output_index, res);
247 }
248 inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
249 const secret_key &base, secret_key &derived_key) {
250 crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
251 }
252 inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result) {
254 }
255
256 /* Generation and checking of a standard signature.
257 */
258 inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
259 crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
260 }
261 inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
262 return crypto_ops::check_signature(prefix_hash, pub, sig);
263 }
264
265 /* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key
266 * derivation D, the signature proves the knowledge of the tx secret key r such that R=r*G and D=r*A
267 * 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
268 */
269 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) {
270 crypto_ops::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
271 }
272 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) {
273 crypto_ops::generate_tx_proof_v1(prefix_hash, R, A, B, D, r, sig);
274 }
275 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) {
276 return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig, version);
277 }
278
279 /* To send money to a key:
280 * * The sender generates an ephemeral key and includes it in transaction output.
281 * * To spend the money, the receiver generates a key image from it.
282 * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
283 * 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.
284 */
285 inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
286 crypto_ops::generate_key_image(pub, sec, image);
287 }
288 inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
289 const public_key *const *pubs, std::size_t pubs_count,
290 const secret_key &sec, std::size_t sec_index,
291 signature *sig) {
292 crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
293 }
294 inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
295 const public_key *const *pubs, std::size_t pubs_count,
296 const signature *sig) {
297 return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
298 }
299
300 /* Variants with vector<const public_key *> parameters.
301 */
302 inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
303 const std::vector<const public_key *> &pubs,
304 const secret_key &sec, std::size_t sec_index,
305 signature *sig) {
306 generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
307 }
308 inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
309 const std::vector<const public_key *> &pubs,
310 const signature *sig) {
311 return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
312 }
313
314 /* Derive a 1-byte view tag from the sender-receiver shared secret to reduce scanning time.
315 * 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
316 * for an expected 99.6% of outputs (expected false positive rate = 1/2^8 = 1/256 = 0.4% = 100% - 99.6%).
317 */
318 inline void derive_view_tag(const key_derivation &derivation, std::size_t output_index, view_tag &vt) {
320 }
321
322 inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
324 }
325 /* Do NOT overload the << operator for crypto::secret_key here. Use secret_key_explicit_print_ref
326 * instead to prevent accidental implicit dumping of secret key material to the logs (which has
327 * happened before). For the same reason, do not overload it for crypto::ec_scalar either since
328 * crypto::secret_key is a subclass. I'm not sorry that it's obtuse; that's the point, bozo.
329 */
331 inline std::ostream &operator <<(std::ostream &o, const secret_key_explicit_print_ref v) {
332 epee::to_hex::formatted(o, epee::as_byte_span(unwrap(unwrap(v.sk)))); return o;
333 }
334 inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
336 }
337 inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) {
339 }
340 inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) {
342 }
343 inline std::ostream &operator <<(std::ostream &o, const crypto::view_tag &v) {
345 }
346
347 const extern crypto::public_key null_pkey;
348 const extern crypto::secret_key null_skey;
349
350 inline bool operator<(const public_key &p1, const public_key &p2) { return memcmp(&p1, &p2, sizeof(public_key)) < 0; }
351 inline bool operator>(const public_key &p1, const public_key &p2) { return p2 < p1; }
352}
353
354CRYPTO_MAKE_HASHABLE(public_key)
356CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe)
357CRYPTO_MAKE_HASHABLE(key_image)
358CRYPTO_MAKE_COMPARABLE(signature)
Definition crypto.h:118
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:525
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &)
Definition crypto.cpp:307
static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &)
Definition crypto.cpp:262
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:222
static bool check_signature(const hash &, const public_key &, const signature &)
Definition crypto.cpp:336
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:440
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:207
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:364
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:197
static void generate_key_image(const public_key &, const secret_key &, key_image &)
Definition crypto.cpp:638
#define CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(type)
Definition generic-ops.h:95
#define CRYPTO_MAKE_COMPARABLE(type)
Definition generic-ops.h:43
#define CRYPTO_MAKE_HASHABLE(type)
Definition generic-ops.h:91
void * memcpy(void *a, const void *b, size_t c)
Definition glibc_compat.cpp:16
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
POD_CLASS public_keyM
Definition crypto.h:84
void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
Definition crypto.cpp:99
POD_CLASS ec_point
Definition crypto.h:55
T rand()
Definition crypto.h:176
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:351
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:72
static const ec_point EC_I
Definition crypto.h:116
std::enable_if< std::is_integral< T >::value, T >::type rand_range(T range_min, T range_max)
Definition crypto.h:197
unsigned char uint8_t
Definition hash.h:125
POD_CLASS public_keyV
Definition crypto.h:74
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
std::vector< secret_keyV > column_vectors
Definition crypto.h:87
unsigned __int64 uint64_t
Definition hash.h:137
bool get_valid_torsion_cleared_point_vartime(const ec_point &point, ec_point &torsion_cleared_out)
Definition crypto.cpp:180
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:288
POD_CLASS public_key
Definition crypto.h:64
void random32_unbiased(unsigned char *bytes)
Definition crypto.cpp:123
std::ostream & operator<<(std::ostream &o, const crypto::public_key &v)
Definition crypto.h:322
void rand(size_t N, uint8_t *bytes)
Definition crypto.h:169
POD_CLASS key_image
Definition crypto.h:95
bool operator<(const public_key &p1, const public_key &p2)
Definition crypto.h:350
POD_CLASS ec_scalar
Definition crypto.h:59
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition crypto.h:206
int rows
Definition crypto.h:76
POD_CLASS hash
Definition hash.h:49
public_key pubkey_clear_torsion(const public_key &pubkey)
Definition crypto.cpp:190
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:294
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:187
static constexpr result_type min()
Definition crypto.h:189
result_type operator()() const
Definition crypto.h:191
uint64_t result_type
Definition crypto.h:188
static constexpr result_type max()
Definition crypto.h:190
const crypto::secret_key & sk
Definition crypto.h:330
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
void hash_to_scalar(const void *data, std::size_t length, crypto::ec_scalar &res)
Definition crypto.cpp:73
std::string data
Definition base58.cpp:37
#define T(x)