]>
Commit | Line | Data |
---|---|---|
47e6618e JN |
1 | /********************************************************************** |
2 | * Copyright (c) 2020 Jonas Nick * | |
3 | * Distributed under the MIT software license, see the accompanying * | |
4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* | |
5 | **********************************************************************/ | |
6 | ||
7 | #ifndef _SECP256K1_MODULE_EXTRAKEYS_TESTS_ | |
8 | #define _SECP256K1_MODULE_EXTRAKEYS_TESTS_ | |
9 | ||
10 | #include "secp256k1_extrakeys.h" | |
11 | ||
4cd2ee47 JN |
12 | static secp256k1_context* api_test_context(int flags, int *ecount) { |
13 | secp256k1_context *ctx0 = secp256k1_context_create(flags); | |
14 | secp256k1_context_set_error_callback(ctx0, counting_illegal_callback_fn, ecount); | |
15 | secp256k1_context_set_illegal_callback(ctx0, counting_illegal_callback_fn, ecount); | |
16 | return ctx0; | |
17 | } | |
18 | ||
19 | void test_xonly_pubkey(void) { | |
20 | secp256k1_pubkey pk; | |
21 | secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; | |
22 | secp256k1_ge pk1; | |
23 | secp256k1_ge pk2; | |
24 | secp256k1_fe y; | |
25 | unsigned char sk[32]; | |
26 | unsigned char xy_sk[32]; | |
27 | unsigned char buf32[32]; | |
28 | unsigned char ones32[32]; | |
29 | unsigned char zeros64[64] = { 0 }; | |
30 | int pk_parity; | |
31 | int i; | |
32 | ||
33 | int ecount; | |
34 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
35 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
36 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
37 | ||
38 | secp256k1_rand256(sk); | |
39 | memset(ones32, 0xFF, 32); | |
40 | secp256k1_rand256(xy_sk); | |
41 | CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); | |
42 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); | |
43 | ||
44 | /* Test xonly_pubkey_from_pubkey */ | |
45 | ecount = 0; | |
46 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); | |
47 | CHECK(secp256k1_xonly_pubkey_from_pubkey(sign, &xonly_pk, &pk_parity, &pk) == 1); | |
48 | CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &xonly_pk, &pk_parity, &pk) == 1); | |
49 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, NULL, &pk_parity, &pk) == 0); | |
50 | CHECK(ecount == 1); | |
51 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1); | |
52 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, NULL) == 0); | |
53 | CHECK(ecount == 2); | |
54 | memset(&pk, 0, sizeof(pk)); | |
55 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 0); | |
56 | CHECK(ecount == 3); | |
57 | ||
58 | /* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */ | |
59 | memset(sk, 0, sizeof(sk)); | |
60 | sk[0] = 1; | |
61 | CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1); | |
62 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1); | |
63 | CHECK(memcmp(&pk, &xonly_pk, sizeof(pk)) == 0); | |
64 | CHECK(pk_parity == 0); | |
65 | ||
66 | /* Choose a secret key such that pubkey and xonly_pubkey are each others | |
67 | * negation. */ | |
68 | sk[0] = 2; | |
69 | CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1); | |
70 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1); | |
71 | CHECK(memcmp(&xonly_pk, &pk, sizeof(xonly_pk)) != 0); | |
72 | CHECK(pk_parity == 1); | |
73 | secp256k1_pubkey_load(ctx, &pk1, &pk); | |
74 | secp256k1_pubkey_load(ctx, &pk2, (secp256k1_pubkey *) &xonly_pk); | |
75 | CHECK(secp256k1_fe_equal(&pk1.x, &pk2.x) == 1); | |
76 | secp256k1_fe_negate(&y, &pk2.y, 1); | |
77 | CHECK(secp256k1_fe_equal(&pk1.y, &y) == 1); | |
78 | ||
79 | /* Test xonly_pubkey_serialize and xonly_pubkey_parse */ | |
80 | ecount = 0; | |
81 | CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0); | |
82 | CHECK(ecount == 1); | |
83 | CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0); | |
84 | CHECK(memcmp(buf32, zeros64, 32) == 0); | |
85 | CHECK(ecount == 2); | |
86 | { | |
87 | /* A pubkey filled with 0s will fail to serialize due to pubkey_load | |
88 | * special casing. */ | |
89 | secp256k1_xonly_pubkey pk_tmp; | |
90 | memset(&pk_tmp, 0, sizeof(pk_tmp)); | |
91 | CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &pk_tmp) == 0); | |
92 | } | |
93 | /* pubkey_load called illegal callback */ | |
94 | CHECK(ecount == 3); | |
95 | ||
96 | CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &xonly_pk) == 1); | |
97 | ecount = 0; | |
98 | CHECK(secp256k1_xonly_pubkey_parse(none, NULL, buf32) == 0); | |
99 | CHECK(ecount == 1); | |
100 | CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, NULL) == 0); | |
101 | CHECK(ecount == 2); | |
102 | ||
103 | /* Serialization and parse roundtrip */ | |
104 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1); | |
105 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1); | |
106 | CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk_tmp, buf32) == 1); | |
107 | CHECK(memcmp(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0); | |
108 | ||
109 | /* Test parsing invalid field elements */ | |
110 | memset(&xonly_pk, 1, sizeof(xonly_pk)); | |
111 | /* Overflowing field element */ | |
112 | CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, ones32) == 0); | |
113 | CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); | |
114 | memset(&xonly_pk, 1, sizeof(xonly_pk)); | |
115 | /* There's no point with x-coordinate 0 on secp256k1 */ | |
116 | CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, zeros64) == 0); | |
117 | CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); | |
118 | /* If a random 32-byte string can not be parsed with ec_pubkey_parse | |
119 | * (because interpreted as X coordinate it does not correspond to a point on | |
120 | * the curve) then xonly_pubkey_parse should fail as well. */ | |
121 | for (i = 0; i < count; i++) { | |
122 | unsigned char rand33[33]; | |
123 | secp256k1_rand256(&rand33[1]); | |
124 | rand33[0] = SECP256K1_TAG_PUBKEY_EVEN; | |
125 | if (!secp256k1_ec_pubkey_parse(ctx, &pk, rand33, 33)) { | |
126 | memset(&xonly_pk, 1, sizeof(xonly_pk)); | |
127 | CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 0); | |
128 | CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); | |
129 | } else { | |
130 | CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 1); | |
131 | } | |
132 | } | |
133 | CHECK(ecount == 2); | |
134 | ||
135 | secp256k1_context_destroy(none); | |
136 | secp256k1_context_destroy(sign); | |
137 | secp256k1_context_destroy(verify); | |
138 | } | |
139 | ||
910d9c28 JN |
140 | void test_xonly_pubkey_tweak(void) { |
141 | unsigned char zeros64[64] = { 0 }; | |
142 | unsigned char overflows[32]; | |
143 | unsigned char sk[32]; | |
144 | secp256k1_pubkey internal_pk; | |
145 | secp256k1_xonly_pubkey internal_xonly_pk; | |
146 | secp256k1_pubkey output_pk; | |
147 | int pk_parity; | |
148 | unsigned char tweak[32]; | |
149 | int i; | |
150 | ||
151 | int ecount; | |
152 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
153 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
154 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
155 | ||
156 | memset(overflows, 0xff, sizeof(overflows)); | |
157 | secp256k1_rand256(tweak); | |
158 | secp256k1_rand256(sk); | |
159 | CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1); | |
160 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); | |
161 | ||
162 | ecount = 0; | |
163 | CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 0); | |
164 | CHECK(ecount == 1); | |
165 | CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 0); | |
166 | CHECK(ecount == 2); | |
167 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); | |
168 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0); | |
169 | CHECK(ecount == 3); | |
170 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0); | |
171 | CHECK(ecount == 4); | |
172 | /* NULL internal_xonly_pk zeroes the output_pk */ | |
173 | CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); | |
174 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0); | |
175 | CHECK(ecount == 5); | |
176 | /* NULL tweak zeroes the output_pk */ | |
177 | CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); | |
178 | ||
179 | /* Invalid tweak zeroes the output_pk */ | |
180 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0); | |
181 | CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); | |
182 | ||
183 | /* A zero tweak is fine */ | |
184 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1); | |
185 | ||
186 | /* Fails if the resulting key was infinity */ | |
187 | for (i = 0; i < count; i++) { | |
188 | secp256k1_scalar scalar_tweak; | |
189 | /* Because sk may be negated before adding, we need to try with tweak = | |
190 | * sk as well as tweak = -sk. */ | |
191 | secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); | |
192 | secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); | |
193 | secp256k1_scalar_get_b32(tweak, &scalar_tweak); | |
194 | CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0) | |
195 | || (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0)); | |
196 | CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); | |
197 | } | |
198 | ||
199 | /* Invalid pk with a valid tweak */ | |
200 | memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk)); | |
201 | secp256k1_rand256(tweak); | |
202 | ecount = 0; | |
203 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0); | |
204 | CHECK(ecount == 1); | |
205 | CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); | |
206 | ||
207 | secp256k1_context_destroy(none); | |
208 | secp256k1_context_destroy(sign); | |
209 | secp256k1_context_destroy(verify); | |
210 | } | |
211 | ||
212 | void test_xonly_pubkey_tweak_check(void) { | |
213 | unsigned char zeros64[64] = { 0 }; | |
214 | unsigned char overflows[32]; | |
215 | unsigned char sk[32]; | |
216 | secp256k1_pubkey internal_pk; | |
217 | secp256k1_xonly_pubkey internal_xonly_pk; | |
218 | secp256k1_pubkey output_pk; | |
219 | secp256k1_xonly_pubkey output_xonly_pk; | |
220 | unsigned char output_pk32[32]; | |
221 | unsigned char buf32[32]; | |
222 | int pk_parity; | |
223 | unsigned char tweak[32]; | |
224 | ||
225 | int ecount; | |
226 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
227 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
228 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
229 | ||
230 | memset(overflows, 0xff, sizeof(overflows)); | |
231 | secp256k1_rand256(tweak); | |
232 | secp256k1_rand256(sk); | |
233 | CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1); | |
234 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); | |
235 | ||
236 | ecount = 0; | |
237 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); | |
238 | CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1); | |
239 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1); | |
240 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); | |
241 | CHECK(ecount == 1); | |
242 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); | |
243 | CHECK(ecount == 2); | |
244 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); | |
245 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0); | |
246 | CHECK(ecount == 3); | |
247 | /* invalid pk_parity value */ | |
248 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0); | |
249 | CHECK(ecount == 3); | |
250 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0); | |
251 | CHECK(ecount == 4); | |
252 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0); | |
253 | CHECK(ecount == 5); | |
254 | ||
255 | memset(tweak, 1, sizeof(tweak)); | |
256 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1); | |
257 | CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1); | |
258 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &output_xonly_pk, &pk_parity, &output_pk) == 1); | |
259 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk32, &output_xonly_pk) == 1); | |
260 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, tweak) == 1); | |
261 | ||
262 | /* Wrong pk_parity */ | |
263 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, !pk_parity, &internal_xonly_pk, tweak) == 0); | |
264 | /* Wrong public key */ | |
265 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &internal_xonly_pk) == 1); | |
266 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); | |
267 | ||
268 | /* Overflowing tweak not allowed */ | |
269 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); | |
270 | CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0); | |
271 | CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); | |
272 | CHECK(ecount == 5); | |
273 | ||
274 | secp256k1_context_destroy(none); | |
275 | secp256k1_context_destroy(sign); | |
276 | secp256k1_context_destroy(verify); | |
277 | } | |
278 | ||
279 | /* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1 | |
280 | * additional pubkeys by calling tweak_add. Then verifies every tweak starting | |
281 | * from the last pubkey. */ | |
282 | #define N_PUBKEYS 32 | |
283 | void test_xonly_pubkey_tweak_recursive(void) { | |
284 | unsigned char sk[32]; | |
285 | secp256k1_pubkey pk[N_PUBKEYS]; | |
286 | unsigned char pk_serialized[32]; | |
287 | unsigned char tweak[N_PUBKEYS - 1][32]; | |
288 | int i; | |
289 | ||
290 | secp256k1_rand256(sk); | |
291 | CHECK(secp256k1_ec_pubkey_create(ctx, &pk[0], sk) == 1); | |
292 | /* Add tweaks */ | |
293 | for (i = 0; i < N_PUBKEYS - 1; i++) { | |
294 | secp256k1_xonly_pubkey xonly_pk; | |
295 | memset(tweak[i], i + 1, sizeof(tweak[i])); | |
296 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i]) == 1); | |
297 | CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &pk[i + 1], &xonly_pk, tweak[i]) == 1); | |
298 | } | |
299 | ||
300 | /* Verify tweaks */ | |
301 | for (i = N_PUBKEYS - 1; i > 0; i--) { | |
302 | secp256k1_xonly_pubkey xonly_pk; | |
303 | int pk_parity; | |
304 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk[i]) == 1); | |
305 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk_serialized, &xonly_pk) == 1); | |
306 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i - 1]) == 1); | |
307 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk_serialized, pk_parity, &xonly_pk, tweak[i - 1]) == 1); | |
308 | } | |
309 | } | |
310 | #undef N_PUBKEYS | |
311 | ||
58254463 JN |
312 | void test_keypair(void) { |
313 | unsigned char sk[32]; | |
314 | unsigned char zeros96[96] = { 0 }; | |
315 | unsigned char overflows[32]; | |
316 | secp256k1_keypair keypair; | |
317 | secp256k1_pubkey pk, pk_tmp; | |
318 | secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; | |
319 | int pk_parity, pk_parity_tmp; | |
320 | int ecount; | |
321 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
322 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
323 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
324 | ||
325 | CHECK(sizeof(zeros96) == sizeof(keypair)); | |
326 | memset(overflows, 0xFF, sizeof(overflows)); | |
327 | ||
328 | /* Test keypair_create */ | |
329 | ecount = 0; | |
330 | secp256k1_rand256(sk); | |
331 | CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0); | |
332 | CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); | |
333 | CHECK(ecount == 1); | |
334 | CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0); | |
335 | CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); | |
336 | CHECK(ecount == 2); | |
337 | CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); | |
338 | CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0); | |
339 | CHECK(ecount == 3); | |
340 | CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0); | |
341 | CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); | |
342 | CHECK(ecount == 4); | |
343 | ||
344 | /* Invalid secret key */ | |
345 | CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0); | |
346 | CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); | |
347 | CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0); | |
348 | CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); | |
349 | ||
350 | /* Test keypair_pub */ | |
351 | ecount = 0; | |
352 | secp256k1_rand256(sk); | |
353 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
354 | CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); | |
355 | CHECK(secp256k1_keypair_pub(none, NULL, &keypair) == 0); | |
356 | CHECK(ecount == 1); | |
357 | CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0); | |
358 | CHECK(ecount == 2); | |
359 | CHECK(memcmp(zeros96, &pk, sizeof(pk)) == 0); | |
360 | ||
361 | /* Using an invalid keypair is fine for keypair_pub */ | |
362 | memset(&keypair, 0, sizeof(keypair)); | |
363 | CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); | |
364 | CHECK(memcmp(zeros96, &pk, sizeof(pk)) == 0); | |
365 | ||
366 | /* keypair holds the same pubkey as pubkey_create */ | |
367 | CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); | |
368 | CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); | |
369 | CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1); | |
370 | CHECK(memcmp(&pk, &pk_tmp, sizeof(pk)) == 0); | |
371 | ||
372 | /** Test keypair_xonly_pub **/ | |
373 | ecount = 0; | |
374 | secp256k1_rand256(sk); | |
375 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
376 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); | |
377 | CHECK(secp256k1_keypair_xonly_pub(none, NULL, &pk_parity, &keypair) == 0); | |
378 | CHECK(ecount == 1); | |
379 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1); | |
380 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0); | |
381 | CHECK(ecount == 2); | |
382 | CHECK(memcmp(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); | |
383 | /* Using an invalid keypair will set the xonly_pk to 0 (first reset | |
384 | * xonly_pk). */ | |
385 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); | |
386 | memset(&keypair, 0, sizeof(keypair)); | |
387 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0); | |
388 | CHECK(memcmp(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); | |
389 | CHECK(ecount == 3); | |
390 | ||
391 | /** keypair holds the same xonly pubkey as pubkey_create **/ | |
392 | CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); | |
393 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); | |
394 | CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); | |
395 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1); | |
396 | CHECK(memcmp(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0); | |
397 | CHECK(pk_parity == pk_parity_tmp); | |
398 | ||
399 | secp256k1_context_destroy(none); | |
400 | secp256k1_context_destroy(sign); | |
401 | secp256k1_context_destroy(verify); | |
402 | } | |
403 | ||
6fcb5b84 JN |
404 | void test_keypair_add(void) { |
405 | unsigned char sk[32]; | |
406 | secp256k1_keypair keypair; | |
407 | unsigned char overflows[32]; | |
408 | unsigned char zeros96[96] = { 0 }; | |
409 | unsigned char tweak[32]; | |
410 | int i; | |
411 | int ecount = 0; | |
412 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
413 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
414 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
415 | ||
416 | CHECK(sizeof(zeros96) == sizeof(keypair)); | |
417 | secp256k1_rand256(sk); | |
418 | secp256k1_rand256(tweak); | |
419 | memset(overflows, 0xFF, 32); | |
420 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
421 | ||
422 | CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 0); | |
423 | CHECK(ecount == 1); | |
424 | CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 0); | |
425 | CHECK(ecount == 2); | |
426 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1); | |
427 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0); | |
428 | CHECK(ecount == 3); | |
429 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0); | |
430 | CHECK(ecount == 4); | |
431 | /* This does not set the keypair to zeroes */ | |
432 | CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) != 0); | |
433 | ||
434 | /* Invalid tweak zeroes the keypair */ | |
435 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
436 | CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, overflows) == 0); | |
437 | CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0); | |
438 | ||
439 | /* A zero tweak is fine */ | |
440 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
441 | CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, zeros96) == 1); | |
442 | ||
443 | /* Fails if the resulting keypair was (sk=0, pk=infinity) */ | |
444 | for (i = 0; i < count; i++) { | |
445 | secp256k1_scalar scalar_tweak; | |
446 | secp256k1_keypair keypair_tmp; | |
447 | secp256k1_rand256(sk); | |
448 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
449 | memcpy(&keypair_tmp, &keypair, sizeof(keypair)); | |
450 | /* Because sk may be negated before adding, we need to try with tweak = | |
451 | * sk as well as tweak = -sk. */ | |
452 | secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); | |
453 | secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); | |
454 | secp256k1_scalar_get_b32(tweak, &scalar_tweak); | |
455 | CHECK((secp256k1_keypair_xonly_tweak_add(ctx, &keypair, sk) == 0) | |
456 | || (secp256k1_keypair_xonly_tweak_add(ctx, &keypair_tmp, tweak) == 0)); | |
457 | CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0 | |
458 | || memcmp(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0); | |
459 | } | |
460 | ||
461 | /* Invalid keypair with a valid tweak */ | |
462 | memset(&keypair, 0, sizeof(keypair)); | |
463 | secp256k1_rand256(tweak); | |
464 | ecount = 0; | |
465 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); | |
466 | CHECK(ecount == 1); | |
467 | CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0); | |
468 | /* Only seckey part of keypair invalid */ | |
469 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
470 | memset(&keypair, 0, 32); | |
471 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); | |
472 | CHECK(ecount == 2); | |
473 | /* Only pubkey part of keypair invalid */ | |
474 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
475 | memset(&keypair.data[32], 0, 64); | |
476 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); | |
477 | CHECK(ecount == 3); | |
478 | ||
479 | /* Check that the keypair_tweak_add implementation is correct */ | |
480 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
481 | for (i = 0; i < count; i++) { | |
482 | secp256k1_xonly_pubkey internal_pk; | |
483 | secp256k1_xonly_pubkey output_pk; | |
484 | secp256k1_pubkey output_pk_xy; | |
485 | secp256k1_pubkey output_pk_expected; | |
486 | unsigned char pk32[32]; | |
487 | int pk_parity; | |
488 | ||
489 | secp256k1_rand256(tweak); | |
490 | CHECK(secp256k1_keypair_xonly_pub(ctx, &internal_pk, NULL, &keypair) == 1); | |
491 | CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1); | |
492 | CHECK(secp256k1_keypair_xonly_pub(ctx, &output_pk, &pk_parity, &keypair) == 1); | |
493 | ||
494 | /* Check that it passes xonly_pubkey_tweak_add_check */ | |
495 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk32, &output_pk) == 1); | |
496 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk32, pk_parity, &internal_pk, tweak) == 1); | |
497 | ||
498 | /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */ | |
499 | CHECK(secp256k1_keypair_pub(ctx, &output_pk_xy, &keypair) == 1); | |
500 | CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk_expected, &internal_pk, tweak) == 1); | |
501 | CHECK(memcmp(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); | |
502 | ||
503 | /* Check that the secret key in the keypair is tweaked correctly */ | |
504 | CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, &keypair.data[0]) == 1); | |
505 | CHECK(memcmp(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); | |
506 | } | |
507 | secp256k1_context_destroy(none); | |
508 | secp256k1_context_destroy(sign); | |
509 | secp256k1_context_destroy(verify); | |
510 | } | |
511 | ||
47e6618e | 512 | void run_extrakeys_tests(void) { |
4cd2ee47 JN |
513 | /* xonly key test cases */ |
514 | test_xonly_pubkey(); | |
910d9c28 JN |
515 | test_xonly_pubkey_tweak(); |
516 | test_xonly_pubkey_tweak_check(); | |
517 | test_xonly_pubkey_tweak_recursive(); | |
58254463 JN |
518 | |
519 | /* keypair tests */ | |
520 | test_keypair(); | |
6fcb5b84 | 521 | test_keypair_add(); |
47e6618e JN |
522 | } |
523 | ||
524 | #endif |