#pragma once #include #include 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(&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. */ }