]>
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 | ||
47e6618e | 140 | void run_extrakeys_tests(void) { |
4cd2ee47 JN |
141 | /* xonly key test cases */ |
142 | test_xonly_pubkey(); | |
47e6618e JN |
143 | } |
144 | ||
145 | #endif |