aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/crypto.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/crypto/crypto.h180
1 files changed, 100 insertions, 80 deletions
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 2dd2085ce..61641fbcf 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -1,66 +1,61 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#pragma once
#include <cstddef>
-#include <cstring>
+#include <mutex>
+#include <vector>
+
+#include "common/pod-class.h"
+#include "generic-ops.h"
+#include "hash.h"
namespace crypto {
+ extern "C" {
+#include "random.h"
+ }
+
+ extern std::mutex random_lock;
+
#pragma pack(push, 1)
- class hash {
+ POD_CLASS ec_point {
char data[32];
};
- class ec_point {
+ POD_CLASS ec_scalar {
char data[32];
};
- class ec_scalar {
- char data[32];
+ POD_CLASS public_key: ec_point {
+ friend class crypto_ops;
};
- class public_key: ec_point {
+ POD_CLASS secret_key: ec_scalar {
friend class crypto_ops;
};
- class secret_key: ec_scalar {
+ POD_CLASS key_derivation: ec_point {
friend class crypto_ops;
};
- class key_image: ec_point {
+ POD_CLASS key_image: ec_point {
friend class crypto_ops;
};
- class signature {
+ POD_CLASS signature {
ec_scalar c, r;
friend class crypto_ops;
};
#pragma pack(pop)
- static_assert(sizeof(hash) == 32 && sizeof(ec_point) == 32 &&
- sizeof(ec_scalar) == 32 && sizeof(public_key) == 32 &&
- sizeof(secret_key) == 32 && sizeof(key_image) == 32 &&
+ static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
+ sizeof(public_key) == 32 && sizeof(secret_key) == 32 &&
+ sizeof(key_derivation) == 32 && sizeof(key_image) == 32 &&
sizeof(signature) == 64, "Invalid structure size");
- extern "C" {
- void keccak(const void *data, std::size_t length, char *hash);
- }
-
- inline void keccak(const void *data, std::size_t length, hash &hash) {
- keccak(data, length, reinterpret_cast<char *>(&hash));
- }
-
- inline bool operator==(const hash &a, const hash &b) {
- return std::memcmp(&a, &b, sizeof(struct hash)) == 0;
- }
-
- inline bool operator==(const public_key &a, const public_key &b) {
- return std::memcmp(&a, &b, sizeof(struct public_key)) == 0;
- }
-
- inline bool operator==(const key_image &a, const key_image &b) {
- return std::memcmp(&a, &b, sizeof(struct key_image)) == 0;
- }
-
class crypto_ops {
crypto_ops();
crypto_ops(const crypto_ops &);
@@ -71,6 +66,14 @@ namespace crypto {
friend void generate_keys(public_key &, secret_key &);
static bool check_key(const public_key &);
friend bool check_key(const public_key &);
+ static bool secret_key_to_public_key(const secret_key &, public_key &);
+ friend bool secret_key_to_public_key(const secret_key &, public_key &);
+ static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
+ friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
+ static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
+ friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
+ static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
+ friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
static bool check_signature(const hash &, const public_key &, const signature &);
@@ -87,80 +90,97 @@ namespace crypto {
const public_key *const *, std::size_t, const signature *);
};
- /* Generate a new key pair.
- * pub: a newly generated public key.
- * sec: a newly generated secret key.
+ /* Generate a value filled with random bytes.
+ */
+ template<typename T>
+ typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
+ typename std::remove_cv<T>::type res;
+ std::lock_guard<std::mutex> lock(random_lock);
+ generate_random_bytes(sizeof(T), &res);
+ return res;
+ }
+
+ /* Generate a new key pair
*/
inline void generate_keys(public_key &pub, secret_key &sec) {
crypto_ops::generate_keys(pub, sec);
}
- /* Check a public key.
- * key: a key to check.
- * returns: true if the key is valid, false otherwise.
+ /* Check a public key. Returns true if it is valid, false otherwise.
*/
inline bool check_key(const public_key &key) {
return crypto_ops::check_key(key);
}
- /* Sign a message.
- * message_hash: hash of a message.
- * pub: public key used for signing. Assumed to be valid.
- * sec: secret key used for signing. Assumed to correspond to pub.
- * sig: the resulting signature.
+ /* Checks a private key and computes the corresponding public key.
*/
- inline void generate_signature(const hash &message_hash, const public_key &pub, const secret_key &sec, signature &sig) {
- crypto_ops::generate_signature(message_hash, pub, sec, sig);
+ inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
+ return crypto_ops::secret_key_to_public_key(sec, pub);
}
- /* Verify a signature.
- * message_hash: hash of a message.
- * pub: public key used for signing. Assumed to be valid, use check_key to check it first.
- * sig: a signature.
- * returns: true if the signature is valid, false otherwise.
+ /* To generate an ephemeral key used to send money to:
+ * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
+ * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
+ * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
+ * * 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).
*/
- inline bool check_signature(const hash &message_hash, const public_key &pub, const signature &sig) {
- return crypto_ops::check_signature(message_hash, pub, sig);
+ inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
+ return crypto_ops::generate_key_derivation(key1, key2, derivation);
+ }
+ inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
+ const public_key &base, public_key &derived_key) {
+ return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
+ }
+ inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
+ const secret_key &base, secret_key &derived_key) {
+ crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
}
- /* Generate the image of a key.
- * pub: public key used for signing. Assumed to be valid.
- * sec: secret key used for signing. Assumed to correspond to pub.
- * image: the resulting key image.
+ /* Generation and checking of a standard signature.
*/
- inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
- crypto_ops::generate_key_image(pub, sec, image);
+ inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
+ crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
+ }
+ inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
+ return crypto_ops::check_signature(prefix_hash, pub, sig);
}
- /* Sign a message using linkable ring signature.
- * message_hash: hash of a message.
- * image: image of the key used for signing. Use generate_key_image to create it. Assumed to correspond to the key used for signing.
- * pubs: pointer to an array of pointers to public keys of a ring. All keys are assumed to be valid, use check_key to check them first.
- * pubs_count: number of keys in a ring.
- * sec: secret key used for signing.
- * sec_index: index of the key used for signing in pubs. It is assumed that 0 <= sec_index < pubs_count and that sec corresponds to *pubs[sec_index].
- * sig: the resulting signature (occupies pubs_count elements). To verify it, image of the key is also necessary.
+ /* To send money to a key:
+ * * The sender generates an ephemeral key and includes it in transaction output.
+ * * To spend the money, the receiver generates a key image from it.
+ * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
+ * 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.
*/
- inline void generate_ring_signature(const hash &message_hash, const key_image &image,
+ inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
+ crypto_ops::generate_key_image(pub, sec, image);
+ }
+ inline 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) {
- crypto_ops::generate_ring_signature(message_hash, image, pubs, pubs_count, sec, sec_index, sig);
+ crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
+ }
+ inline 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) {
+ return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
}
- /* Verify a linkable ring signature.
- * message_hash: hash of a message.
- * image: image of the key used for signing.
- * pubs: pointer to an array of pointers to public keys of a ring. All keys are assumed to be valid, use check_key to check them first.
- * pubs_count: number of keys in a ring.
- * sig: a signature (occupies pubs_count elements).
- * returns: true if the signature is valid, false otherwise.
+ /* Variants with vector<const public_key *> parameters.
*/
- inline bool check_ring_signature(const hash &message_hash, const key_image &image,
- const public_key *const *pubs, std::size_t pubs_count,
+ inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
+ const std::vector<const public_key *> &pubs,
+ const secret_key &sec, std::size_t sec_index,
+ signature *sig) {
+ generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
+ }
+ inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
+ const std::vector<const public_key *> &pubs,
const signature *sig) {
- return crypto_ops::check_ring_signature(message_hash, image, pubs, pubs_count, sig);
+ return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
}
+}
- /* To check whether two signatures are linked, compare their key images. */
-} \ No newline at end of file
+CRYPTO_MAKE_COMPARABLE(public_key)
+CRYPTO_MAKE_HASHABLE(key_image)
+CRYPTO_MAKE_COMPARABLE(signature)