forked from microsoft/Picnic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
picnic.h
352 lines (321 loc) · 13.2 KB
/
picnic.h
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/*! @file picnic.h
* @brief Public API for the Picnic signature scheme.
*
* This file is part of the reference implementation of the Picnic and Fish
* signature schemes, described in the paper:
*
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives <br/>
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
* Zaverucha <br/>
* Cryptology ePrint Archive: Report 2017/279 <br/>
* http://eprint.iacr.org/2017/279 <br/>
*
* The code is provided under the MIT license, see LICENSE for
* more details.
*
*/
// Doxygen mainpage:
/** @mainpage
*
* This is a reference implementation of the Picnic and Fish signature
* schemes, described in the paper:
*
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives <br/>
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
* Zaverucha <br/>
* Cryptology ePrint Archive: Report 2017/279 <br/>
* http://eprint.iacr.org/2017/279 <br/>
*
* The library API is documented in \ref picnic.h.
*
* Authors: Steven Goldfeder and Greg Zaverucha <br/>
* May 2017
*/
#ifndef PICNIC_H
#define PICNIC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdlib.h>
/* Maximum lengths in bytes */
#define PICNIC_MAX_PUBLICKEY_SIZE 64 /**< Largest public key size, in bytes */
#define PICNIC_MAX_PRIVATEKEY_SIZE 64 /**< Largest private key size, in bytes */
#define PICNIC_MAX_SIGNATURE_SIZE 263786 /**< Largest signature size, in bytes */
/** Parameter sets */
typedef enum picnic_params_t {
PARAMETER_SET_INVALID = 0,
LowMC_256_256_42_14_FS = 1, /**< LowMC with Fiat-Shamir balanced number of s-boxes (42) and rounds (14). */
LowMC_256_256_42_14_UR = 2, /**< LowMC with Unruh balanced number of s-boxes (42) and rounds (14). */
LowMC_256_256_1_316_FS = 3, /**< LowMC with Fiat-Shamir and a small number of s-boxes (1) with a large number of rounds (316). */
LowMC_256_256_1_316_UR = 4, /**< LowMC with Unruh and a small number of s-boxes (1) with a large number of rounds (316). */
LowMC_256_256_10_38_FS = 5, /**< LowMC with Fiat-Shamir balanced number of s-boxes (10) and rounds (38). */
LowMC_256_256_10_38_UR = 6, /**< LowMC with Unruh balanced number of s-boxes (10) and rounds (38). */
PARAMETER_SET_MAX_INDEX = 7
} picnic_params_t;
/** Public key */
typedef struct {
picnic_params_t params; /**< The parameter set used with this public key. */
uint8_t pubInput[PICNIC_MAX_PUBLICKEY_SIZE / 2]; /**< The input plaintext block to LowMC. */
uint8_t ciphertext[PICNIC_MAX_PUBLICKEY_SIZE / 2]; /**< The encryption of pubInput under the private key. */
} picnic_publickey_t;
/** Private key */
typedef struct {
picnic_params_t params; /**< The parameter set used with this private key. */
uint8_t data[PICNIC_MAX_PRIVATEKEY_SIZE]; /**< The private key data. */
picnic_publickey_t* pk; /**< The corresponding public key. */
} picnic_privatekey_t;
/**
* Library initialization.
* Must be called before calling any of the other functions.
*
* Used to initialize OpenSSL and load LowMC constants and precomputed tables.
* Initialization is specific to a parameter set.
*
* @param[in] params The parameter set that will be used.
* @param[in] flags If flags is 1, OpenSSL is not initialized. This is useful
* if the application using picnic.h also uses OpenSSL, and does not want the
* picnic_init to perform OpenSSL initialization. If flags is 1, fucntions in
* picnic.h assume that OpenSSL has been initialized, and that the SHA-256, and
* AES algorithms are available.
*
* @return 0 on success, nonzero for error
*
* @see picnic_shutdown()
*/
int picnic_init(picnic_params_t params, unsigned int flags);
/**
* Free resources allocated by picnic_init().
*
* @param[in] flags If flags is 1, the OpenSSL shutdown steps are not
* performed. This is useful if the application using picnic.h also uses
* OpenSSL, and does not want picnic_shutdown to shutdown OpenSSL.
*
* @see picnic_init()
*/
void picnic_shutdown(unsigned int flags);
/**
* Get a string representation of the parameter set.
*
* @param parameters A parameter set
*
* @return A null-terminated string describing the parameter set.
*/
const char* picnic_get_param_name(picnic_params_t parameters);
/* Signature API */
/**
* Key generation function.
* Generates a public and private key pair, for the specified parameter set.
*
* @param[in] parameters The parameter set to use when generating a key.
* @param[out] pk The new public key.
* @param[out] sk The new private key.
*
* @return Returns 0 for success, or a nonzero value indicating an error.
*
* @see picnic_verify(), picnic_sign()
*/
int picnic_keygen(picnic_params_t parameters, picnic_publickey_t* pk,
picnic_privatekey_t* sk);
/**
* Signature function.
* Signs a message with the given keypair.
*
* @param[in] sk The signer's private key.
* @param[in] message The message to be signed.
* @param[in] message_len The length of the message, in bytes.
* @param[out] signature A buffer to hold the signature. The required size does
* not exceed PICNIC_MAX_SIGNATURE_SIZE bytes. The specific max number of
* bytes required for a parameter set is given by picnic_signature_size(). Note
* that the length of each signature varies slightly, for the parameter sets
* using the FS transform. The parameter sets using the Unruh transform have a
* fixed length.
* @param[in,out] signature_len The length of the provided signature buffer.
* On success, this is set to the number of bytes written to the signature buffer.
*
* @return Returns 0 for success, or a nonzero value indicating an error.
*
* @see picnic_verify(), picnic_keygen(), picnic_signature_size()
*/
int picnic_sign(picnic_privatekey_t* sk, uint8_t* message, size_t message_len,
uint8_t* signature, size_t* signature_len);
/**
* Get the number of bytes required to hold a signature.
*
* @param[in] parameters The parameter set of the signature.
*
* @return The number of bytes required to hold the signature created by
* picnic_sign
*
* @note The size of signatures with parameter sets using the FS transform vary
* slightly based on the random choices made during signing. This function
* will return a suffcient number of bytes to hold a signature, and the
* picnic_sign() function returns the exact number used for a given signature.
*
* @see picnic_sign()
*/
size_t picnic_signature_size(picnic_params_t parameters);
/**
* Verification function.
* Verifies a signature is valid with respect to a public key and message.
*
* @param[in] pk The signer's public key.
* @param[in] message The message the signature purpotedly signs.
* @param[in] message_len The length of the message, in bytes.
* @param[out] signature The signature
* @param[in,out] signature_len The length of the signature.
*
* @return Returns 0 for success, indicating a valid signature, or a nonzero
* value indicating an error or an invalid signature.
*
* @see picnic_sign(), picnic_keygen()
*/
int picnic_verify(picnic_publickey_t* pk, uint8_t* message, size_t message_len,
uint8_t* signature, size_t signature_len);
/**
* Serialize a public key.
*
* @param[in] key The public key to serialize
* @param[out] buf The buffer to write the key to.
* Must have size at least PICNIC_MAX_PUBLICKEY_SIZE + 1 bytes.
* @param[in] buflen The length of buf, in bytes
*
* @return Returns the number of bytes written.
*/
int picnic_write_public_key(picnic_publickey_t* key, uint8_t* buf, size_t buflen);
/**
* De-serialize a public key.
*
* @param[in] key The public key object to be populated.
* @param[out] buf The buffer to read the public key from.
* Must be at least PICNIC_MAX_PUBLICKEY_SIZE + 1 bytes.
* @param[in] buflen The length of buf, in bytes
*
* @return Returns the number of bytes written.
*/
int picnic_read_public_key(picnic_publickey_t* key, uint8_t* buf, size_t buflen);
/**
* Serialize a private key.
*
* @param[in] key The private key to serialize
* @param[out] buf The buffer to write the key to.
* Must have size at least PICNIC_MAX_PRIVATEKEY_SIZE + 1 bytes.
* @param[in] buflen The length of buf, in bytes
*
* @return Returns the number of bytes written.
*/
int picnic_write_private_key(picnic_privatekey_t* key, uint8_t* buf, size_t buflen);
/**
* De-serialize a private key.
*
* @param[in] key The private key object to be populated
* @param[out] buf The buffer to write the key to.
* Must have size at least PICNIC_MAX_PRIVATEKEY_SIZE + 1 bytes.
* @param[in] buflen The length of buf, in bytes
* @param[in] publickey The corresponding public key
*
* @return Returns 0 on success, or a nonzero value indicating an error.
*/
int picnic_read_private_key(picnic_privatekey_t* key, uint8_t* buf, size_t buflen, picnic_publickey_t* publickey);
/**
* Check that a key pair is valid.
*
* @param[in] privatekey The private key to check
* @param[in] publickey The public key to check
*
* @return Returns 0 if the key pair is valid, or a nonzero value indicating an error
*/
int picnic_validate_keypair(const picnic_privatekey_t* privatekey, const picnic_publickey_t* publickey);
/**
* Serialize a public key.
*
* @param[in] key The public key to serialize
* @param[out] buf The buffer to write the key to.
* Must have size at least PICNIC_MAX_PUBLICKEY_SIZE + 1 bytes.
* @param[in] buflen The length of buf, in bytes
*
* @return Returns the number of bytes written.
*/
int picnic_write_public_key(picnic_publickey_t* key, uint8_t* buf, size_t buflen);
/**
* De-serialize a public key.
*
* @param[in] key The public key object to be populated.
* @param[out] buf The buffer to read the public key from.
* Must be at least PICNIC_MAX_PUBLICKEY_SIZE + 1 bytes.
* @param[in] buflen The length of buf, in bytes
*
* @return Returns 0 on success or a nonzer value indicating an error.
*/
int picnic_read_public_key(picnic_publickey_t* key, uint8_t* buf, size_t buflen);
/**
* Serialize a private key.
*
* @param[in] key The private key to serialize
* @param[out] buf The buffer to write the key to.
* Must have size at least PICNIC_MAX_PRIVATEKEY_SIZE + 1 bytes.
* @param[in] buflen The length of buf, in bytes
*
* @return Returns the number of bytes written.
*/
int picnic_write_private_key(picnic_privatekey_t* key, uint8_t* buf, size_t buflen);
/**
* De-serialize a private key.
*
* @param[in] key The private key object to be populated
* @param[out] buf The buffer to read the key from.
* Must have size at least PICNIC_MAX_PRIVATEKEY_SIZE + 1 bytes.
* @param[in] buflen The length of buf, in bytes
* @param[in] publickey The corresponding public key
*
* @return Returns 0 on success, or a nonzero value indicating an error.
*/
int picnic_read_private_key(picnic_privatekey_t* key, uint8_t* buf, size_t buflen, picnic_publickey_t* publickey);
/**
* Check that a key pair is valid.
*
* @param[in] privatekey The private key to check
* @param[in] publickey The public key to check
*
* @return Returns 0 if the key pair is valid, or a nonzero value indicating an error
*/
int picnic_validate_keypair(const picnic_privatekey_t* privatekey, const picnic_publickey_t* publickey);
/**
* picnic_random_bytes is used to generate random bytes in key generation and
* signing. See the provided implementation "random_bytes_default_openssl"
* based on OpenSSL's RAND_bytes.
*
* To use another RNG, make sure it has the same behavior as
* random_bytes_default_openssl, and change the definition of
* picnic_random_bytes.
*/
#define picnic_random_bytes random_bytes_default_openssl
/*
* Note signing digests and streaming APIs
*
* Sometimes signaure APIs include "sign_digest" and "verify_digest" functions,
* that allow the caller to hash the message themselves and provide the digest
* to the sign/verify functions. Example use cases for these APIs are
* applications that must sign very large messages, which don't fit in memory,
* or that must signa long stream data. Applications that really need this
* behavior could provide a digest to the sign/verify APIs provided here.
* This is discouraged however, because the message will then be hashed twice,
* the challenge used in the proof will be:
* c = H(random, per-signature values || H(M))
* instead of
* c = H(random, per-signature values || M).
* In the former case, a collision for H immediately gives a forgery (in the
* GMR security game, but not necessarily in all applications). For this reason
* the latter case arguably provides better security.
*
* A better way to implement a streaming API (not provided by this library)
* would be to hash the first part of the challenge, then continue hashing the
* message as a stream, then finish computing the signature.
*
*/
#ifdef __cplusplus
}
#endif
#endif /*PICNIC_H*/