]>
Commit | Line | Data |
---|---|---|
07aa4c70 DA |
1 | /*********************************************************************** |
2 | * Copyright (c) 2020 Jonas Nick * | |
3 | * Distributed under the MIT software license, see the accompanying * | |
4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* | |
5 | ***********************************************************************/ | |
47e6618e | 6 | |
fb390c52 RC |
7 | #ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_H |
8 | #define SECP256K1_MODULE_EXTRAKEYS_TESTS_H | |
47e6618e JN |
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 | ||
a45c1fa6 | 38 | secp256k1_testrand256(sk); |
4cd2ee47 | 39 | memset(ones32, 0xFF, 32); |
a45c1fa6 | 40 | secp256k1_testrand256(xy_sk); |
4cd2ee47 JN |
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); | |
6173839c | 63 | CHECK(secp256k1_memcmp_var(&pk, &xonly_pk, sizeof(pk)) == 0); |
4cd2ee47 JN |
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); | |
6173839c | 71 | CHECK(secp256k1_memcmp_var(&xonly_pk, &pk, sizeof(xonly_pk)) != 0); |
4cd2ee47 JN |
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); | |
6173839c | 84 | CHECK(secp256k1_memcmp_var(buf32, zeros64, 32) == 0); |
4cd2ee47 JN |
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); | |
6173839c | 107 | CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0); |
4cd2ee47 JN |
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); | |
6173839c | 113 | CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); |
4cd2ee47 JN |
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); | |
6173839c | 117 | CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); |
4cd2ee47 JN |
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]; | |
a45c1fa6 | 123 | secp256k1_testrand256(&rand33[1]); |
4cd2ee47 JN |
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); | |
6173839c | 128 | CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); |
4cd2ee47 JN |
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 | ||
6eceec6d AP |
140 | void test_xonly_pubkey_comparison(void) { |
141 | unsigned char pk1_ser[32] = { | |
142 | 0x58, 0x84, 0xb3, 0xa2, 0x4b, 0x97, 0x37, 0x88, 0x92, 0x38, 0xa6, 0x26, 0x62, 0x52, 0x35, 0x11, | |
143 | 0xd0, 0x9a, 0xa1, 0x1b, 0x80, 0x0b, 0x5e, 0x93, 0x80, 0x26, 0x11, 0xef, 0x67, 0x4b, 0xd9, 0x23 | |
144 | }; | |
145 | const unsigned char pk2_ser[32] = { | |
146 | 0xde, 0x36, 0x0e, 0x87, 0x59, 0x8f, 0x3c, 0x01, 0x36, 0x2a, 0x2a, 0xb8, 0xc6, 0xf4, 0x5e, 0x4d, | |
147 | 0xb2, 0xc2, 0xd5, 0x03, 0xa7, 0xf9, 0xf1, 0x4f, 0xa8, 0xfa, 0x95, 0xa8, 0xe9, 0x69, 0x76, 0x1c | |
148 | }; | |
149 | secp256k1_xonly_pubkey pk1; | |
150 | secp256k1_xonly_pubkey pk2; | |
151 | int ecount = 0; | |
152 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
153 | ||
154 | CHECK(secp256k1_xonly_pubkey_parse(none, &pk1, pk1_ser) == 1); | |
155 | CHECK(secp256k1_xonly_pubkey_parse(none, &pk2, pk2_ser) == 1); | |
156 | ||
157 | CHECK(secp256k1_xonly_pubkey_cmp(none, NULL, &pk2) < 0); | |
158 | CHECK(ecount == 1); | |
159 | CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, NULL) > 0); | |
160 | CHECK(ecount == 2); | |
161 | CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk2) < 0); | |
162 | CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk1) > 0); | |
163 | CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk1) == 0); | |
164 | CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk2) == 0); | |
165 | CHECK(ecount == 2); | |
166 | memset(&pk1, 0, sizeof(pk1)); /* illegal pubkey */ | |
167 | CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk2) < 0); | |
168 | CHECK(ecount == 3); | |
169 | CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk1) == 0); | |
170 | CHECK(ecount == 5); | |
171 | CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk1) > 0); | |
172 | CHECK(ecount == 6); | |
173 | ||
174 | secp256k1_context_destroy(none); | |
175 | } | |
176 | ||
910d9c28 JN |
177 | void test_xonly_pubkey_tweak(void) { |
178 | unsigned char zeros64[64] = { 0 }; | |
179 | unsigned char overflows[32]; | |
180 | unsigned char sk[32]; | |
181 | secp256k1_pubkey internal_pk; | |
182 | secp256k1_xonly_pubkey internal_xonly_pk; | |
183 | secp256k1_pubkey output_pk; | |
184 | int pk_parity; | |
185 | unsigned char tweak[32]; | |
186 | int i; | |
187 | ||
188 | int ecount; | |
189 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
190 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
191 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
192 | ||
193 | memset(overflows, 0xff, sizeof(overflows)); | |
a45c1fa6 PW |
194 | secp256k1_testrand256(tweak); |
195 | secp256k1_testrand256(sk); | |
910d9c28 JN |
196 | CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1); |
197 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); | |
198 | ||
199 | ecount = 0; | |
200 | CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 0); | |
201 | CHECK(ecount == 1); | |
202 | CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 0); | |
203 | CHECK(ecount == 2); | |
204 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); | |
205 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0); | |
206 | CHECK(ecount == 3); | |
207 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0); | |
208 | CHECK(ecount == 4); | |
209 | /* NULL internal_xonly_pk zeroes the output_pk */ | |
6173839c | 210 | CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); |
910d9c28 JN |
211 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0); |
212 | CHECK(ecount == 5); | |
213 | /* NULL tweak zeroes the output_pk */ | |
6173839c | 214 | CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); |
910d9c28 JN |
215 | |
216 | /* Invalid tweak zeroes the output_pk */ | |
217 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0); | |
6173839c | 218 | CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); |
910d9c28 JN |
219 | |
220 | /* A zero tweak is fine */ | |
221 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1); | |
222 | ||
223 | /* Fails if the resulting key was infinity */ | |
224 | for (i = 0; i < count; i++) { | |
225 | secp256k1_scalar scalar_tweak; | |
226 | /* Because sk may be negated before adding, we need to try with tweak = | |
227 | * sk as well as tweak = -sk. */ | |
228 | secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); | |
229 | secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); | |
230 | secp256k1_scalar_get_b32(tweak, &scalar_tweak); | |
231 | CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0) | |
232 | || (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0)); | |
6173839c | 233 | CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); |
910d9c28 JN |
234 | } |
235 | ||
236 | /* Invalid pk with a valid tweak */ | |
237 | memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk)); | |
a45c1fa6 | 238 | secp256k1_testrand256(tweak); |
910d9c28 JN |
239 | ecount = 0; |
240 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0); | |
241 | CHECK(ecount == 1); | |
6173839c | 242 | CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); |
910d9c28 JN |
243 | |
244 | secp256k1_context_destroy(none); | |
245 | secp256k1_context_destroy(sign); | |
246 | secp256k1_context_destroy(verify); | |
247 | } | |
248 | ||
249 | void test_xonly_pubkey_tweak_check(void) { | |
250 | unsigned char zeros64[64] = { 0 }; | |
251 | unsigned char overflows[32]; | |
252 | unsigned char sk[32]; | |
253 | secp256k1_pubkey internal_pk; | |
254 | secp256k1_xonly_pubkey internal_xonly_pk; | |
255 | secp256k1_pubkey output_pk; | |
256 | secp256k1_xonly_pubkey output_xonly_pk; | |
257 | unsigned char output_pk32[32]; | |
258 | unsigned char buf32[32]; | |
259 | int pk_parity; | |
260 | unsigned char tweak[32]; | |
261 | ||
262 | int ecount; | |
263 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
264 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
265 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
266 | ||
267 | memset(overflows, 0xff, sizeof(overflows)); | |
a45c1fa6 PW |
268 | secp256k1_testrand256(tweak); |
269 | secp256k1_testrand256(sk); | |
910d9c28 JN |
270 | CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1); |
271 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); | |
272 | ||
273 | ecount = 0; | |
274 | CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); | |
275 | CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1); | |
276 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1); | |
277 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); | |
278 | CHECK(ecount == 1); | |
279 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); | |
280 | CHECK(ecount == 2); | |
281 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); | |
282 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0); | |
283 | CHECK(ecount == 3); | |
284 | /* invalid pk_parity value */ | |
285 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0); | |
286 | CHECK(ecount == 3); | |
287 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0); | |
288 | CHECK(ecount == 4); | |
289 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0); | |
290 | CHECK(ecount == 5); | |
291 | ||
292 | memset(tweak, 1, sizeof(tweak)); | |
293 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1); | |
294 | CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1); | |
295 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &output_xonly_pk, &pk_parity, &output_pk) == 1); | |
296 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk32, &output_xonly_pk) == 1); | |
297 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, tweak) == 1); | |
298 | ||
299 | /* Wrong pk_parity */ | |
300 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, !pk_parity, &internal_xonly_pk, tweak) == 0); | |
301 | /* Wrong public key */ | |
302 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &internal_xonly_pk) == 1); | |
303 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); | |
304 | ||
305 | /* Overflowing tweak not allowed */ | |
306 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); | |
307 | CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0); | |
6173839c | 308 | CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); |
910d9c28 JN |
309 | CHECK(ecount == 5); |
310 | ||
311 | secp256k1_context_destroy(none); | |
312 | secp256k1_context_destroy(sign); | |
313 | secp256k1_context_destroy(verify); | |
314 | } | |
315 | ||
316 | /* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1 | |
317 | * additional pubkeys by calling tweak_add. Then verifies every tweak starting | |
318 | * from the last pubkey. */ | |
319 | #define N_PUBKEYS 32 | |
320 | void test_xonly_pubkey_tweak_recursive(void) { | |
321 | unsigned char sk[32]; | |
322 | secp256k1_pubkey pk[N_PUBKEYS]; | |
323 | unsigned char pk_serialized[32]; | |
324 | unsigned char tweak[N_PUBKEYS - 1][32]; | |
325 | int i; | |
326 | ||
a45c1fa6 | 327 | secp256k1_testrand256(sk); |
910d9c28 JN |
328 | CHECK(secp256k1_ec_pubkey_create(ctx, &pk[0], sk) == 1); |
329 | /* Add tweaks */ | |
330 | for (i = 0; i < N_PUBKEYS - 1; i++) { | |
331 | secp256k1_xonly_pubkey xonly_pk; | |
332 | memset(tweak[i], i + 1, sizeof(tweak[i])); | |
333 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i]) == 1); | |
334 | CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &pk[i + 1], &xonly_pk, tweak[i]) == 1); | |
335 | } | |
336 | ||
337 | /* Verify tweaks */ | |
338 | for (i = N_PUBKEYS - 1; i > 0; i--) { | |
339 | secp256k1_xonly_pubkey xonly_pk; | |
340 | int pk_parity; | |
341 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk[i]) == 1); | |
342 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk_serialized, &xonly_pk) == 1); | |
343 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i - 1]) == 1); | |
344 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk_serialized, pk_parity, &xonly_pk, tweak[i - 1]) == 1); | |
345 | } | |
346 | } | |
347 | #undef N_PUBKEYS | |
348 | ||
58254463 JN |
349 | void test_keypair(void) { |
350 | unsigned char sk[32]; | |
36d9dc1e | 351 | unsigned char sk_tmp[32]; |
58254463 JN |
352 | unsigned char zeros96[96] = { 0 }; |
353 | unsigned char overflows[32]; | |
354 | secp256k1_keypair keypair; | |
355 | secp256k1_pubkey pk, pk_tmp; | |
356 | secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; | |
357 | int pk_parity, pk_parity_tmp; | |
358 | int ecount; | |
359 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
360 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
361 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
362 | ||
363 | CHECK(sizeof(zeros96) == sizeof(keypair)); | |
364 | memset(overflows, 0xFF, sizeof(overflows)); | |
365 | ||
366 | /* Test keypair_create */ | |
367 | ecount = 0; | |
a45c1fa6 | 368 | secp256k1_testrand256(sk); |
58254463 | 369 | CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0); |
6173839c | 370 | CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); |
58254463 JN |
371 | CHECK(ecount == 1); |
372 | CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0); | |
6173839c | 373 | CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); |
58254463 JN |
374 | CHECK(ecount == 2); |
375 | CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); | |
376 | CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0); | |
377 | CHECK(ecount == 3); | |
378 | CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0); | |
6173839c | 379 | CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); |
58254463 JN |
380 | CHECK(ecount == 4); |
381 | ||
382 | /* Invalid secret key */ | |
383 | CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0); | |
6173839c | 384 | CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); |
58254463 | 385 | CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0); |
6173839c | 386 | CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); |
58254463 JN |
387 | |
388 | /* Test keypair_pub */ | |
389 | ecount = 0; | |
a45c1fa6 | 390 | secp256k1_testrand256(sk); |
58254463 JN |
391 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); |
392 | CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); | |
393 | CHECK(secp256k1_keypair_pub(none, NULL, &keypair) == 0); | |
394 | CHECK(ecount == 1); | |
395 | CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0); | |
396 | CHECK(ecount == 2); | |
6173839c | 397 | CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); |
58254463 JN |
398 | |
399 | /* Using an invalid keypair is fine for keypair_pub */ | |
400 | memset(&keypair, 0, sizeof(keypair)); | |
401 | CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); | |
6173839c | 402 | CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); |
58254463 JN |
403 | |
404 | /* keypair holds the same pubkey as pubkey_create */ | |
405 | CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); | |
406 | CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); | |
407 | CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1); | |
6173839c | 408 | CHECK(secp256k1_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0); |
58254463 JN |
409 | |
410 | /** Test keypair_xonly_pub **/ | |
411 | ecount = 0; | |
a45c1fa6 | 412 | secp256k1_testrand256(sk); |
58254463 JN |
413 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); |
414 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); | |
415 | CHECK(secp256k1_keypair_xonly_pub(none, NULL, &pk_parity, &keypair) == 0); | |
416 | CHECK(ecount == 1); | |
417 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1); | |
418 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0); | |
419 | CHECK(ecount == 2); | |
6173839c | 420 | CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); |
58254463 JN |
421 | /* Using an invalid keypair will set the xonly_pk to 0 (first reset |
422 | * xonly_pk). */ | |
423 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); | |
424 | memset(&keypair, 0, sizeof(keypair)); | |
425 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0); | |
6173839c | 426 | CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); |
58254463 JN |
427 | CHECK(ecount == 3); |
428 | ||
429 | /** keypair holds the same xonly pubkey as pubkey_create **/ | |
430 | CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); | |
431 | CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); | |
432 | CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); | |
433 | CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1); | |
6173839c | 434 | CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0); |
58254463 JN |
435 | CHECK(pk_parity == pk_parity_tmp); |
436 | ||
36d9dc1e ET |
437 | /* Test keypair_seckey */ |
438 | ecount = 0; | |
439 | secp256k1_testrand256(sk); | |
440 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
441 | CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1); | |
442 | CHECK(secp256k1_keypair_sec(none, NULL, &keypair) == 0); | |
443 | CHECK(ecount == 1); | |
444 | CHECK(secp256k1_keypair_sec(none, sk_tmp, NULL) == 0); | |
445 | CHECK(ecount == 2); | |
446 | CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); | |
447 | ||
448 | /* keypair returns the same seckey it got */ | |
449 | CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); | |
450 | CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1); | |
451 | CHECK(secp256k1_memcmp_var(sk, sk_tmp, sizeof(sk_tmp)) == 0); | |
452 | ||
453 | ||
454 | /* Using an invalid keypair is fine for keypair_seckey */ | |
455 | memset(&keypair, 0, sizeof(keypair)); | |
456 | CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1); | |
457 | CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); | |
458 | ||
58254463 JN |
459 | secp256k1_context_destroy(none); |
460 | secp256k1_context_destroy(sign); | |
461 | secp256k1_context_destroy(verify); | |
462 | } | |
463 | ||
6fcb5b84 JN |
464 | void test_keypair_add(void) { |
465 | unsigned char sk[32]; | |
466 | secp256k1_keypair keypair; | |
467 | unsigned char overflows[32]; | |
468 | unsigned char zeros96[96] = { 0 }; | |
469 | unsigned char tweak[32]; | |
470 | int i; | |
471 | int ecount = 0; | |
472 | secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); | |
473 | secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); | |
474 | secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); | |
475 | ||
476 | CHECK(sizeof(zeros96) == sizeof(keypair)); | |
a45c1fa6 PW |
477 | secp256k1_testrand256(sk); |
478 | secp256k1_testrand256(tweak); | |
6fcb5b84 JN |
479 | memset(overflows, 0xFF, 32); |
480 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
481 | ||
482 | CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 0); | |
483 | CHECK(ecount == 1); | |
484 | CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 0); | |
485 | CHECK(ecount == 2); | |
486 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1); | |
487 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0); | |
488 | CHECK(ecount == 3); | |
489 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0); | |
490 | CHECK(ecount == 4); | |
491 | /* This does not set the keypair to zeroes */ | |
6173839c | 492 | CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0); |
6fcb5b84 JN |
493 | |
494 | /* Invalid tweak zeroes the keypair */ | |
495 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
496 | CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, overflows) == 0); | |
6173839c | 497 | CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); |
6fcb5b84 JN |
498 | |
499 | /* A zero tweak is fine */ | |
500 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
501 | CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, zeros96) == 1); | |
502 | ||
503 | /* Fails if the resulting keypair was (sk=0, pk=infinity) */ | |
504 | for (i = 0; i < count; i++) { | |
505 | secp256k1_scalar scalar_tweak; | |
506 | secp256k1_keypair keypair_tmp; | |
a45c1fa6 | 507 | secp256k1_testrand256(sk); |
6fcb5b84 JN |
508 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); |
509 | memcpy(&keypair_tmp, &keypair, sizeof(keypair)); | |
510 | /* Because sk may be negated before adding, we need to try with tweak = | |
511 | * sk as well as tweak = -sk. */ | |
512 | secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); | |
513 | secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); | |
514 | secp256k1_scalar_get_b32(tweak, &scalar_tweak); | |
515 | CHECK((secp256k1_keypair_xonly_tweak_add(ctx, &keypair, sk) == 0) | |
516 | || (secp256k1_keypair_xonly_tweak_add(ctx, &keypair_tmp, tweak) == 0)); | |
6173839c TR |
517 | CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0 |
518 | || secp256k1_memcmp_var(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0); | |
6fcb5b84 JN |
519 | } |
520 | ||
521 | /* Invalid keypair with a valid tweak */ | |
522 | memset(&keypair, 0, sizeof(keypair)); | |
a45c1fa6 | 523 | secp256k1_testrand256(tweak); |
6fcb5b84 JN |
524 | ecount = 0; |
525 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); | |
526 | CHECK(ecount == 1); | |
6173839c | 527 | CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); |
6fcb5b84 JN |
528 | /* Only seckey part of keypair invalid */ |
529 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
530 | memset(&keypair, 0, 32); | |
531 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); | |
532 | CHECK(ecount == 2); | |
533 | /* Only pubkey part of keypair invalid */ | |
534 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
535 | memset(&keypair.data[32], 0, 64); | |
536 | CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); | |
537 | CHECK(ecount == 3); | |
538 | ||
539 | /* Check that the keypair_tweak_add implementation is correct */ | |
540 | CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); | |
541 | for (i = 0; i < count; i++) { | |
542 | secp256k1_xonly_pubkey internal_pk; | |
543 | secp256k1_xonly_pubkey output_pk; | |
544 | secp256k1_pubkey output_pk_xy; | |
545 | secp256k1_pubkey output_pk_expected; | |
546 | unsigned char pk32[32]; | |
36d9dc1e | 547 | unsigned char sk32[32]; |
6fcb5b84 JN |
548 | int pk_parity; |
549 | ||
a45c1fa6 | 550 | secp256k1_testrand256(tweak); |
6fcb5b84 JN |
551 | CHECK(secp256k1_keypair_xonly_pub(ctx, &internal_pk, NULL, &keypair) == 1); |
552 | CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1); | |
553 | CHECK(secp256k1_keypair_xonly_pub(ctx, &output_pk, &pk_parity, &keypair) == 1); | |
554 | ||
555 | /* Check that it passes xonly_pubkey_tweak_add_check */ | |
556 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk32, &output_pk) == 1); | |
557 | CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk32, pk_parity, &internal_pk, tweak) == 1); | |
558 | ||
559 | /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */ | |
560 | CHECK(secp256k1_keypair_pub(ctx, &output_pk_xy, &keypair) == 1); | |
561 | CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk_expected, &internal_pk, tweak) == 1); | |
6173839c | 562 | CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); |
6fcb5b84 JN |
563 | |
564 | /* Check that the secret key in the keypair is tweaked correctly */ | |
36d9dc1e ET |
565 | CHECK(secp256k1_keypair_sec(none, sk32, &keypair) == 1); |
566 | CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, sk32) == 1); | |
6173839c | 567 | CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); |
6fcb5b84 JN |
568 | } |
569 | secp256k1_context_destroy(none); | |
570 | secp256k1_context_destroy(sign); | |
571 | secp256k1_context_destroy(verify); | |
572 | } | |
573 | ||
47e6618e | 574 | void run_extrakeys_tests(void) { |
4cd2ee47 JN |
575 | /* xonly key test cases */ |
576 | test_xonly_pubkey(); | |
910d9c28 JN |
577 | test_xonly_pubkey_tweak(); |
578 | test_xonly_pubkey_tweak_check(); | |
579 | test_xonly_pubkey_tweak_recursive(); | |
6eceec6d | 580 | test_xonly_pubkey_comparison(); |
58254463 JN |
581 | |
582 | /* keypair tests */ | |
583 | test_keypair(); | |
6fcb5b84 | 584 | test_keypair_add(); |
47e6618e JN |
585 | } |
586 | ||
587 | #endif |