1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
#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. */
}
|