mirror of
https://github.com/monero-project/monero.git
synced 2024-11-18 18:11:03 +00:00
166 lines
6.2 KiB
C
166 lines
6.2 KiB
C
|
#pragma once
|
||
|
|
||
|
#include <cstddef>
|
||
|
#include <cstring>
|
||
|
|
||
|
namespace crypto {
|
||
|
|
||
|
#pragma pack(push, 1)
|
||
|
class hash {
|
||
|
char data[32];
|
||
|
};
|
||
|
|
||
|
class ec_point {
|
||
|
char data[32];
|
||
|
};
|
||
|
|
||
|
class ec_scalar {
|
||
|
char data[32];
|
||
|
};
|
||
|
|
||
|
class public_key: ec_point {
|
||
|
friend class crypto_ops;
|
||
|
};
|
||
|
|
||
|
class secret_key: ec_scalar {
|
||
|
friend class crypto_ops;
|
||
|
};
|
||
|
|
||
|
class key_image: ec_point {
|
||
|
friend class crypto_ops;
|
||
|
};
|
||
|
|
||
|
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 &&
|
||
|
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 &);
|
||
|
void operator=(const crypto_ops &);
|
||
|
~crypto_ops();
|
||
|
|
||
|
static void generate_keys(public_key &, secret_key &);
|
||
|
friend void generate_keys(public_key &, secret_key &);
|
||
|
static bool check_key(const public_key &);
|
||
|
friend bool check_key(const public_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 &);
|
||
|
friend bool check_signature(const hash &, const public_key &, const signature &);
|
||
|
static void generate_key_image(const public_key &, const secret_key &, key_image &);
|
||
|
friend void generate_key_image(const public_key &, const secret_key &, key_image &);
|
||
|
static void generate_ring_signature(const hash &, const key_image &,
|
||
|
const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
|
||
|
friend void generate_ring_signature(const hash &, const key_image &,
|
||
|
const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
|
||
|
static bool check_ring_signature(const hash &, const key_image &,
|
||
|
const public_key *const *, std::size_t, const signature *);
|
||
|
friend bool check_ring_signature(const hash &, const key_image &,
|
||
|
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.
|
||
|
*/
|
||
|
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.
|
||
|
*/
|
||
|
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.
|
||
|
*/
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
/* 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.
|
||
|
*/
|
||
|
inline bool check_signature(const hash &message_hash, const public_key &pub, const signature &sig) {
|
||
|
return crypto_ops::check_signature(message_hash, pub, sig);
|
||
|
}
|
||
|
|
||
|
/* 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.
|
||
|
*/
|
||
|
inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
|
||
|
crypto_ops::generate_key_image(pub, sec, image);
|
||
|
}
|
||
|
|
||
|
/* 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.
|
||
|
*/
|
||
|
inline void generate_ring_signature(const hash &message_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);
|
||
|
}
|
||
|
|
||
|
/* 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.
|
||
|
*/
|
||
|
inline bool check_ring_signature(const hash &message_hash, const key_image &image,
|
||
|
const public_key *const *pubs, std::size_t pubs_count,
|
||
|
const signature *sig) {
|
||
|
return crypto_ops::check_ring_signature(message_hash, image, pubs, pubs_count, sig);
|
||
|
}
|
||
|
|
||
|
/* To check whether two signatures are linked, compare their key images. */
|
||
|
}
|