@@ -15,6 +15,13 @@ static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned ch
15
15
return 0 ;
16
16
}
17
17
18
+ static int ecdh_xonly_hash_function_test_fail (unsigned char * output , const unsigned char * x , void * data ) {
19
+ (void )output ;
20
+ (void )x ;
21
+ (void )data ;
22
+ return 0 ;
23
+ }
24
+
18
25
static int ecdh_hash_function_custom (unsigned char * output , const unsigned char * x , const unsigned char * y , void * data ) {
19
26
(void )data ;
20
27
/* Save x and y as uncompressed public key */
@@ -24,11 +31,19 @@ static int ecdh_hash_function_custom(unsigned char *output, const unsigned char
24
31
return 1 ;
25
32
}
26
33
34
+ static int ecdh_xonly_hash_function_custom (unsigned char * output , const unsigned char * x , void * data ) {
35
+ (void )data ;
36
+ /* Output X coordinate. */
37
+ memcpy (output , x , 32 );
38
+ return 1 ;
39
+ }
40
+
27
41
static void test_ecdh_api (void ) {
28
42
/* Setup context that just counts errors */
29
43
secp256k1_context * tctx = secp256k1_context_create (SECP256K1_CONTEXT_NONE );
30
44
secp256k1_pubkey point ;
31
45
unsigned char res [32 ];
46
+ unsigned char x32 [32 ];
32
47
unsigned char s_one [32 ] = { 0 };
33
48
int32_t ecount = 0 ;
34
49
s_one [31 ] = 1 ;
@@ -37,7 +52,7 @@ static void test_ecdh_api(void) {
37
52
secp256k1_context_set_illegal_callback (tctx , counting_illegal_callback_fn , & ecount );
38
53
CHECK (secp256k1_ec_pubkey_create (tctx , & point , s_one ) == 1 );
39
54
40
- /* Check all NULLs are detected */
55
+ /* Check all NULLs are detected by secp256k1_ecdh. */
41
56
CHECK (secp256k1_ecdh (tctx , res , & point , s_one , NULL , NULL ) == 1 );
42
57
CHECK (ecount == 0 );
43
58
CHECK (secp256k1_ecdh (tctx , NULL , & point , s_one , NULL , NULL ) == 0 );
@@ -49,16 +64,36 @@ static void test_ecdh_api(void) {
49
64
CHECK (secp256k1_ecdh (tctx , res , & point , s_one , NULL , NULL ) == 1 );
50
65
CHECK (ecount == 3 );
51
66
67
+ /* And the same for secp256k1_ecdh_xonly. */
68
+ memset (x32 , 131 , 32 ); /* sum(131*256^j, j=0..31) is a valid x coordinate. */
69
+ CHECK (secp256k1_ecdh_xonly (tctx , res , x32 , s_one , NULL , NULL ) == 1 );
70
+ CHECK (ecount == 3 );
71
+ CHECK (secp256k1_ecdh_xonly (tctx , NULL , x32 , s_one , NULL , NULL ) == 0 );
72
+ CHECK (ecount == 4 );
73
+ CHECK (secp256k1_ecdh_xonly (tctx , res , NULL , s_one , NULL , NULL ) == 0 );
74
+ CHECK (ecount == 5 );
75
+ CHECK (secp256k1_ecdh_xonly (tctx , res , x32 , NULL , NULL , NULL ) == 0 );
76
+ CHECK (ecount == 6 );
77
+ CHECK (secp256k1_ecdh_xonly (tctx , res , x32 , s_one , NULL , NULL ) == 1 );
78
+ CHECK (ecount == 6 );
79
+ memset (x32 , 205 , 32 ); /* sum(205*256^j, j=0..31) is not a valid x coordinate. */
80
+ CHECK (secp256k1_ecdh_xonly (tctx , res , x32 , s_one , NULL , NULL ) == 0 );
81
+ CHECK (ecount == 6 );
82
+
52
83
/* Cleanup */
53
84
secp256k1_context_destroy (tctx );
54
85
}
55
86
56
87
static void test_ecdh_generator_basepoint (void ) {
57
88
unsigned char s_one [32 ] = { 0 };
89
+ unsigned char x32_g [32 ];
58
90
secp256k1_pubkey point [2 ];
59
91
int i ;
60
92
61
93
s_one [31 ] = 1 ;
94
+ CHECK (secp256k1_ec_pubkey_create (CTX , & point [0 ], s_one ) == 1 );
95
+ secp256k1_fe_get_b32 (x32_g , & secp256k1_ge_const_g .x );
96
+
62
97
/* Check against pubkey creation when the basepoint is the generator */
63
98
for (i = 0 ; i < 2 * COUNT ; ++ i ) {
64
99
secp256k1_sha256 sha ;
@@ -72,7 +107,6 @@ static void test_ecdh_generator_basepoint(void) {
72
107
random_scalar_order (& s );
73
108
secp256k1_scalar_get_b32 (s_b32 , & s );
74
109
75
- CHECK (secp256k1_ec_pubkey_create (CTX , & point [0 ], s_one ) == 1 );
76
110
CHECK (secp256k1_ec_pubkey_create (CTX , & point [1 ], s_b32 ) == 1 );
77
111
78
112
/* compute using ECDH function with custom hash function */
@@ -82,6 +116,11 @@ static void test_ecdh_generator_basepoint(void) {
82
116
/* compare */
83
117
CHECK (secp256k1_memcmp_var (output_ecdh , point_ser , 65 ) == 0 );
84
118
119
+ /* Do the same with x-only ECDH. */
120
+ CHECK (secp256k1_ecdh_xonly (CTX , output_ecdh , x32_g , s_b32 , ecdh_xonly_hash_function_custom , NULL ) == 1 );
121
+ /* compare */
122
+ CHECK (secp256k1_memcmp_var (output_ecdh , point_ser + 1 , 32 ) == 0 );
123
+
85
124
/* compute using ECDH function with default hash function */
86
125
CHECK (secp256k1_ecdh (CTX , output_ecdh , & point [0 ], s_b32 , NULL , NULL ) == 1 );
87
126
/* compute "explicitly" */
@@ -91,6 +130,15 @@ static void test_ecdh_generator_basepoint(void) {
91
130
secp256k1_sha256_finalize (& sha , output_ser );
92
131
/* compare */
93
132
CHECK (secp256k1_memcmp_var (output_ecdh , output_ser , 32 ) == 0 );
133
+
134
+ /* And the same with x-only ECDH. */
135
+ CHECK (secp256k1_ecdh_xonly (CTX , output_ecdh , x32_g , s_b32 , NULL , NULL ) == 1 );
136
+ /* compute "explicitly" */
137
+ secp256k1_sha256_initialize (& sha );
138
+ secp256k1_sha256_write (& sha , point_ser + 1 , 32 );
139
+ secp256k1_sha256_finalize (& sha , output_ser );
140
+ /* compare */
141
+ CHECK (secp256k1_memcmp_var (output_ecdh , output_ser , 32 ) == 0 );
94
142
}
95
143
}
96
144
@@ -104,13 +152,16 @@ static void test_bad_scalar(void) {
104
152
};
105
153
unsigned char s_rand [32 ] = { 0 };
106
154
unsigned char output [32 ];
155
+ unsigned char point_ser [33 ];
107
156
secp256k1_scalar rand ;
108
157
secp256k1_pubkey point ;
158
+ size_t point_ser_len = sizeof (point_ser );
109
159
110
160
/* Create random point */
111
161
random_scalar_order (& rand );
112
162
secp256k1_scalar_get_b32 (s_rand , & rand );
113
163
CHECK (secp256k1_ec_pubkey_create (CTX , & point , s_rand ) == 1 );
164
+ CHECK (secp256k1_ec_pubkey_serialize (CTX , point_ser , & point_ser_len , & point , SECP256K1_EC_COMPRESSED ) == 1 );
114
165
115
166
/* Try to multiply it by bad values */
116
167
CHECK (secp256k1_ecdh (CTX , output , & point , s_zero , NULL , NULL ) == 0 );
@@ -119,39 +170,63 @@ static void test_bad_scalar(void) {
119
170
s_overflow [31 ] -= 1 ;
120
171
CHECK (secp256k1_ecdh (CTX , output , & point , s_overflow , NULL , NULL ) == 1 );
121
172
173
+ /* And repeat for x-only. */
174
+ s_overflow [31 ] += 1 ;
175
+ CHECK (secp256k1_ecdh_xonly (CTX , output , point_ser + 1 , s_zero , NULL , NULL ) == 0 );
176
+ CHECK (secp256k1_ecdh_xonly (CTX , output , point_ser + 1 , s_overflow , NULL , NULL ) == 0 );
177
+ s_overflow [31 ] -= 1 ;
178
+ CHECK (secp256k1_ecdh_xonly (CTX , output , point_ser + 1 , s_overflow , NULL , NULL ) == 1 );
179
+
122
180
/* Hash function failure results in ecdh failure */
123
181
CHECK (secp256k1_ecdh (CTX , output , & point , s_overflow , ecdh_hash_function_test_fail , NULL ) == 0 );
182
+ CHECK (secp256k1_ecdh_xonly (CTX , output , point_ser , s_overflow , ecdh_xonly_hash_function_test_fail , NULL ) == 0 );
124
183
}
125
184
126
185
/** Test that ECDH(sG, 1/s) == ECDH((1/s)G, s) == ECDH(G, 1) for a few random s. */
127
186
static void test_result_basepoint (void ) {
128
187
secp256k1_pubkey point ;
129
188
secp256k1_scalar rand ;
189
+ unsigned char point_ser [33 ];
190
+ unsigned char x32_g [32 ];
130
191
unsigned char s [32 ];
131
192
unsigned char s_inv [32 ];
132
193
unsigned char out [32 ];
133
194
unsigned char out_inv [32 ];
134
195
unsigned char out_base [32 ];
196
+ unsigned char out_base_xonly [32 ];
197
+ size_t point_ser_len ;
135
198
int i ;
136
199
137
200
unsigned char s_one [32 ] = { 0 };
138
201
s_one [31 ] = 1 ;
202
+ secp256k1_fe_get_b32 (x32_g , & secp256k1_ge_const_g .x );
139
203
CHECK (secp256k1_ec_pubkey_create (CTX , & point , s_one ) == 1 );
140
204
CHECK (secp256k1_ecdh (CTX , out_base , & point , s_one , NULL , NULL ) == 1 );
205
+ CHECK (secp256k1_ecdh_xonly (CTX , out_base_xonly , x32_g , s_one , NULL , NULL ) == 1 );
141
206
142
207
for (i = 0 ; i < 2 * COUNT ; i ++ ) {
143
208
random_scalar_order (& rand );
144
209
secp256k1_scalar_get_b32 (s , & rand );
145
- secp256k1_scalar_inverse (& rand , & rand );
210
+ secp256k1_scalar_inverse_var (& rand , & rand );
146
211
secp256k1_scalar_get_b32 (s_inv , & rand );
147
212
148
213
CHECK (secp256k1_ec_pubkey_create (CTX , & point , s ) == 1 );
214
+ point_ser_len = sizeof (point_ser );
215
+ CHECK (secp256k1_ec_pubkey_serialize (CTX , point_ser , & point_ser_len , & point , SECP256K1_EC_COMPRESSED ));
216
+
149
217
CHECK (secp256k1_ecdh (CTX , out , & point , s_inv , NULL , NULL ) == 1 );
150
218
CHECK (secp256k1_memcmp_var (out , out_base , 32 ) == 0 );
219
+ CHECK (secp256k1_ecdh_xonly (CTX , out , point_ser + 1 , s_inv , NULL , NULL ) == 1 );
220
+ CHECK (secp256k1_memcmp_var (out , out_base_xonly , 32 ) == 0 );
151
221
152
222
CHECK (secp256k1_ec_pubkey_create (CTX , & point , s_inv ) == 1 );
153
223
CHECK (secp256k1_ecdh (CTX , out_inv , & point , s , NULL , NULL ) == 1 );
224
+ point_ser_len = sizeof (point_ser );
225
+ CHECK (secp256k1_ec_pubkey_serialize (CTX , point_ser , & point_ser_len , & point , SECP256K1_EC_COMPRESSED ));
226
+
154
227
CHECK (secp256k1_memcmp_var (out_inv , out_base , 32 ) == 0 );
228
+ CHECK (secp256k1_ecdh_xonly (CTX , out_inv , point_ser + 1 , s , NULL , NULL ) == 1 );
229
+ CHECK (secp256k1_memcmp_var (out_inv , out_base_xonly , 32 ) == 0 );
155
230
}
156
231
}
157
232
0 commit comments