Electroneum
crypto.h
Go to the documentation of this file.
1 // Copyrights(c) 2017-2019, The Electroneum Project
2 // Copyrights(c) 2014-2017, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31 
32 #pragma once
33 
34 #include <cstddef>
35 #include <boost/thread/mutex.hpp>
36 #include <boost/thread/lock_guard.hpp>
37 #include <boost/archive/iterators/binary_from_base64.hpp>
38 #include <boost/archive/iterators/base64_from_binary.hpp>
39 #include <boost/archive/iterators/transform_width.hpp>
40 #include <boost/algorithm/string.hpp>
41 #include <boost/algorithm/hex.hpp>
42 #include <vector>
43 
44 #include "ed25519-donna/ed25519.h"
45 
46 #include "common/pod-class.h"
47 #include "generic-ops.h"
48 #include "hash.h"
49 
50 namespace crypto {
51 
52  extern "C" {
53 #include "random.h"
54  }
55 
56  extern boost::mutex random_lock;
57 
58 #pragma pack(push, 1)
60  char data[32];
61  };
62 
64  char data[32];
65  };
66 
68  friend class crypto_ops;
69  };
70 
72  friend class crypto_ops;
73  };
74 
76  std::vector<public_key> keys;
77  int rows;
78  };
79 
81  std::vector<secret_key> keys;
82  int rows;
83  };
84 
86  int cols;
87  int rows;
88  std::vector<secret_keyV> column_vectors;
89  };
90 
92  friend class crypto_ops;
93  };
94 
96  friend class crypto_ops;
97  };
98 
100  ec_scalar c, r;
101  friend class crypto_ops;
102  };
103 #pragma pack(pop)
104 
105  static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
106  sizeof(public_key) == 32 && sizeof(secret_key) == 32 &&
107  sizeof(key_derivation) == 32 && sizeof(key_image) == 32 &&
108  sizeof(signature) == 64, "Invalid structure size");
109 
110  class crypto_ops {
111  crypto_ops();
112  crypto_ops(const crypto_ops &);
113  void operator=(const crypto_ops &);
114  ~crypto_ops();
115 
116  static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
117  friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
118  static bool check_key(const public_key &);
119  friend bool check_key(const public_key &);
120  static bool secret_key_to_public_key(const secret_key &, public_key &);
121  friend bool secret_key_to_public_key(const secret_key &, public_key &);
122  static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
123  friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
124  static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
125  friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
126  static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
127  friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
128  static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
129  friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
130  static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
131  friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
132  static bool check_signature(const hash &, const public_key &, const signature &);
133  friend bool check_signature(const hash &, const public_key &, const signature &);
134  static void generate_tx_proof(const hash &, const public_key &, const public_key &, const public_key &, const secret_key &, signature &);
135  friend void generate_tx_proof(const hash &, const public_key &, const public_key &, const public_key &, const secret_key &, signature &);
136  static bool check_tx_proof(const hash &, const public_key &, const public_key &, const public_key &, const signature &);
137  friend bool check_tx_proof(const hash &, const public_key &, const public_key &, const public_key &, const signature &);
138  static void generate_key_image(const public_key &, const secret_key &, key_image &);
139  friend void generate_key_image(const public_key &, const secret_key &, key_image &);
140  static void generate_ring_signature(const hash &, const key_image &,
141  const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
142  friend void generate_ring_signature(const hash &, const key_image &,
143  const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
144  static bool check_ring_signature(const hash &, const key_image &,
145  const public_key *const *, std::size_t, const signature *);
146  friend bool check_ring_signature(const hash &, const key_image &,
147  const public_key *const *, std::size_t, const signature *);
148 
149  static std::string sign_message(const std::string &message, const std::string &privateKey);
150  friend std::string sign_message(const std::string &message, const std::string &privateKey);
151  static bool verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature);
152  friend bool verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature);
153  static bool verify_signature(const std::string &message, std::vector<std::string> publicKey, const std::string &signature);
154  friend bool verify_signature(const std::string &message, std::vector<std::string> publicKey, const std::string &signature);
155 
156  static std::vector<std::string> create_ed25519_keypair();
157  friend std::vector<std::string> create_ed25519_keypair();
158 
159  static std::string base64_decode(std::string val);
160  friend std::string base64_decode(std::string val);
161  static std::string base64_encode(std::string val);
162  friend std::string base64_encode(std::string val);
163  };
164 
165  /* Generate N random bytes
166  */
167  inline void rand(size_t N, uint8_t *bytes) {
168  boost::lock_guard<boost::mutex> lock(random_lock);
170  }
171 
172  /* Generate a value filled with random bytes.
173  */
174  template<typename T>
175  typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
176  typename std::remove_cv<T>::type res;
177  boost::lock_guard<boost::mutex> lock(random_lock);
179  return res;
180  }
181 
182  /* Generate a new key pair
183  */
184  inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
185  return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
186  }
187 
188  /* Check a public key. Returns true if it is valid, false otherwise.
189  */
190  inline bool check_key(const public_key &key) {
191  return crypto_ops::check_key(key);
192  }
193 
194  /* Checks a private key and computes the corresponding public key.
195  */
196  inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
197  return crypto_ops::secret_key_to_public_key(sec, pub);
198  }
199 
200  /* To generate an ephemeral key used to send money to:
201  * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
202  * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
203  * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
204  * * 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).
205  */
206  inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
207  return crypto_ops::generate_key_derivation(key1, key2, derivation);
208  }
209  inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
210  const public_key &base, public_key &derived_key) {
211  return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
212  }
213  inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
214  return crypto_ops::derivation_to_scalar(derivation, output_index, res);
215  }
216  inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
217  const secret_key &base, secret_key &derived_key) {
218  crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
219  }
220 
221  /* Generation and checking of a standard signature.
222  */
223  inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
224  crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
225  }
226  inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
227  return crypto_ops::check_signature(prefix_hash, pub, sig);
228  }
229 
230  /* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key
231  * derivation D, the signature proves the knowledge of the tx secret key r such that R=r*G and D=r*A
232  */
233  inline void generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const public_key &D, const secret_key &r, signature &sig) {
234  crypto_ops::generate_tx_proof(prefix_hash, R, A, D, r, sig);
235  }
236  inline bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const public_key &D, const signature &sig) {
237  return crypto_ops::check_tx_proof(prefix_hash, R, A, D, sig);
238  }
239 
240  /* To send money to a key:
241  * * The sender generates an ephemeral key and includes it in transaction output.
242  * * To spend the money, the receiver generates a key image from it.
243  * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
244  * 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.
245  */
246  inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
247  crypto_ops::generate_key_image(pub, sec, image);
248  }
249  inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
250  const public_key *const *pubs, std::size_t pubs_count,
251  const secret_key &sec, std::size_t sec_index,
252  signature *sig) {
253  crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
254  }
255  inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
256  const public_key *const *pubs, std::size_t pubs_count,
257  const signature *sig) {
258  return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
259  }
260 
261  /* Variants with vector<const public_key *> parameters.
262  */
263  inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
264  const std::vector<const public_key *> &pubs,
265  const secret_key &sec, std::size_t sec_index,
266  signature *sig) {
267  generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
268  }
269  inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
270  const std::vector<const public_key *> &pubs,
271  const signature *sig) {
272  return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
273  }
274 
275  inline std::string sign_message(const std::string &message, const std::string &privateKey) {
276  return crypto_ops::sign_message(message, privateKey);
277  }
278 
279  inline bool verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature) {
280  return crypto_ops::verify_signature(message, publicKey, signature);
281  }
282 
283  inline bool verify_signature(const std::string &message, std::vector<std::string> publicKey, const std::string &signature) {
284  return crypto_ops::verify_signature(message, publicKey, signature);
285  }
286 
287  inline std::vector<std::string> create_ed25519_keypair() {
289  }
290 
291  inline std::string base64_decode(const std::string &val) {
292  using namespace boost::archive::iterators;
293  using It = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
294  return boost::algorithm::trim_right_copy_if(std::string(It(std::begin(val)), It(std::end(val))), [](char c) {
295  return c == '\0';
296  });
297  }
298 
299  inline std::string base64_encode(const std::string &val) {
300  using namespace boost::archive::iterators;
301  using It = base64_from_binary<transform_width<std::string::const_iterator, 6, 8>>;
302  auto tmp = std::string(It(std::begin(val)), It(std::end(val)));
303  return tmp.append((3 - val.size() % 3) % 3, '=');
304  }
305 }
306 
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:213
POD_CLASS ec_point
Definition: crypto.h:59
const uint32_t T[512]
Definition: groestl_tables.h:34
void generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const public_key &D, const secret_key &r, signature &sig)
Definition: crypto.h:233
#define CRYPTO_MAKE_COMPARABLE(type)
Definition: generic-ops.h:38
static std::string base64_encode(std::string val)
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:216
Definition: crypto.h:110
static bool secret_key_to_public_key(const secret_key &, public_key &)
Definition: crypto.cpp:128
static bool check_signature(const hash &, const public_key &, const signature &)
Definition: crypto.cpp:229
static void generate_key_image(const public_key &, const secret_key &, key_image &)
Definition: crypto.cpp:378
POD_CLASS key_derivation
Definition: crypto.h:89
static bool check_key(const public_key &)
Definition: crypto.cpp:123
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:255
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:223
crypto namespace.
Definition: crypto.cpp:47
POD_CLASS secret_keyV
Definition: crypto.h:80
#define POD_CLASS
Definition: pod-class.h:44
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:206
void generate_random_bytes_not_thread_safe(size_t n, void *result)
Definition: random.c:117
boost::mutex random_lock
Definition: crypto.cpp:61
std::string base64_encode(const std::string &val)
Definition: crypto.h:299
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition: crypto.h:246
void rand(size_t N, uint8_t *bytes)
Definition: crypto.h:167
bool verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature)
Definition: crypto.h:279
POD_CLASS public_keyM
Definition: crypto.h:85
POD_CLASS ec_scalar
Definition: crypto.h:63
static void generate_tx_proof(const hash &, const public_key &, const public_key &, const public_key &, const secret_key &, signature &)
Definition: crypto.cpp:250
static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
Definition: crypto.cpp:101
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:249
friend class crypto_ops
Definition: crypto.h:101
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:184
type
Definition: json.h:74
std::string base64_decode(const std::string &val)
Definition: crypto.h:291
static bool check_tx_proof(const hash &, const public_key &, const public_key &, const public_key &, const signature &)
Definition: crypto.cpp:300
POD_CLASS public_key
Definition: crypto.h:65
bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const public_key &D, const signature &sig)
Definition: crypto.h:236
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &)
Definition: crypto.cpp:138
Definition: base.py:1
POD_CLASS signature
Definition: crypto.h:99
static std::string base64_decode(std::string val)
static bool verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature)
Definition: crypto.cpp:522
POD_CLASS key_image
Definition: crypto.h:93
POD_CLASS secret_key
Definition: crypto.h:69
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:209
bool check_key(const public_key &key)
Definition: crypto.h:190
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:46
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< std::string > create_ed25519_keypair()
Definition: crypto.h:287
std::vector< secret_keyV > column_vectors
Definition: crypto.h:88
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:196
POD_CLASS public_keyV
Definition: crypto.h:75
std::string sign_message(const std::string &message, const std::string &privateKey)
Definition: crypto.h:275
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &)
Definition: crypto.cpp:206
static std::string sign_message(const std::string &message, const std::string &privateKey)
Definition: crypto.cpp:507
#define CRYPTO_MAKE_HASHABLE(type)
Definition: generic-ops.h:48
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.cpp:153
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:226
int rows
Definition: crypto.h:77
static std::vector< std::string > create_ed25519_keypair()
Definition: crypto.cpp:547