1717
1818#include "examples_util.h"
1919
20- /* Identity hash function for ECDH, returns x coordinate directly */
21- int ecdh_hash (unsigned char * output , const unsigned char * x32 , const unsigned char * y32 , void * data ) {
22- (void )y32 ;
23- (void )data ;
24- memcpy (output , x32 , 32 );
20+ int extract_x_coordinate (const secp256k1_context * ctx , const secp256k1_pubkey * pubkey , unsigned char x [32 ]) {
21+ unsigned char serialized [33 ];
22+ size_t len = sizeof (serialized );
23+
24+ if (!secp256k1_ec_pubkey_serialize (ctx , serialized , & len , pubkey , SECP256K1_EC_COMPRESSED ))
25+ return 0 ;
26+
27+ memcpy (x , serialized + 1 , 32 );
2528 return 1 ;
2629}
2730
@@ -32,6 +35,7 @@ int main(void) {
3235 unsigned char compressed_pubkey2 [33 ];
3336 unsigned char shared_secret1 [32 ];
3437 unsigned char shared_secret2 [32 ];
38+ unsigned char x1 [32 ], x2 [32 ];
3539 unsigned char randomize [32 ];
3640 int return_val ;
3741 size_t len ;
@@ -55,71 +59,59 @@ int main(void) {
5559 printf ("Failed to generate randomness\n" );
5660 return EXIT_FAILURE ;
5761 }
58- /* If the secret key is zero or out of range (greater than secp256k1's
59- * order), we fail. Note that the probability of this occurring is negligible
60- * with a properly functioning random number generator. */
6162 if (!secp256k1_ec_seckey_verify (ctx , seckey1 ) || !secp256k1_ec_seckey_verify (ctx , seckey2 )) {
6263 printf ("Generated secret key is invalid. This indicates an issue with the random number generator.\n" );
6364 return EXIT_FAILURE ;
6465 }
6566
66- /* Public key creation using a valid context with a verified secret key should never fail */
6767 return_val = secp256k1_ec_pubkey_create (ctx , & pubkey1 , seckey1 );
6868 assert (return_val );
6969 return_val = secp256k1_ec_pubkey_create (ctx , & pubkey2 , seckey2 );
7070 assert (return_val );
7171
72- /* Serialize pubkey1 in a compressed form (33 bytes), should always return 1 */
7372 len = sizeof (compressed_pubkey1 );
7473 return_val = secp256k1_ec_pubkey_serialize (ctx , compressed_pubkey1 , & len , & pubkey1 , SECP256K1_EC_COMPRESSED );
7574 assert (return_val );
76- /* Should be the same size as the size of the output, because we passed a 33 byte array. */
7775 assert (len == sizeof (compressed_pubkey1 ));
7876
79- /* Serialize pubkey2 in a compressed form (33 bytes) */
8077 len = sizeof (compressed_pubkey2 );
8178 return_val = secp256k1_ec_pubkey_serialize (ctx , compressed_pubkey2 , & len , & pubkey2 , SECP256K1_EC_COMPRESSED );
8279 assert (return_val );
83- /* Should be the same size as the size of the output, because we passed a 33 byte array. */
8480 assert (len == sizeof (compressed_pubkey2 ));
8581
8682 /*** Creating the shared secret ***/
87-
88- /* Perform ECDH with seckey1 and pubkey2. Should never fail with a verified
89- * seckey and valid pubkey */
90- return_val = secp256k1_ecdh (ctx , shared_secret1 , & pubkey2 , seckey1 , ecdh_hash , NULL );
83+ return_val = secp256k1_ecdh (ctx , shared_secret1 , & pubkey2 , seckey1 , NULL , NULL );
9184 assert (return_val );
9285
93- /* Perform ECDH with seckey2 and pubkey1. Should never fail with a verified
94- * seckey and valid pubkey */
95- return_val = secp256k1_ecdh (ctx , shared_secret2 , & pubkey1 , seckey2 , ecdh_hash , NULL );
86+ return_val = secp256k1_ecdh (ctx , shared_secret2 , & pubkey1 , seckey2 , NULL , NULL );
9687 assert (return_val );
9788
98- /* Both parties should end up with the same shared secret */
9989 return_val = memcmp (shared_secret1 , shared_secret2 , sizeof (shared_secret1 ));
10090 assert (return_val == 0 );
10191
92+ /* Извлекаем X-координату */
93+ assert (extract_x_coordinate (ctx , & pubkey1 , x1 ));
94+ assert (extract_x_coordinate (ctx , & pubkey2 , x2 ));
95+
10296 printf ("Secret Key1: " );
10397 print_hex (seckey1 , sizeof (seckey1 ));
10498 printf ("Compressed Pubkey1: " );
10599 print_hex (compressed_pubkey1 , sizeof (compressed_pubkey1 ));
100+ printf ("X-coordinate Pubkey1: " );
101+ print_hex (x1 , sizeof (x1 ));
102+
106103 printf ("\nSecret Key2: " );
107104 print_hex (seckey2 , sizeof (seckey2 ));
108105 printf ("Compressed Pubkey2: " );
109106 print_hex (compressed_pubkey2 , sizeof (compressed_pubkey2 ));
107+ printf ("X-coordinate Pubkey2: " );
108+ print_hex (x2 , sizeof (x2 ));
109+
110110 printf ("\nShared Secret: " );
111111 print_hex (shared_secret1 , sizeof (shared_secret1 ));
112112
113- /* This will clear everything from the context and free the memory */
114113 secp256k1_context_destroy (ctx );
115114
116- /* It's best practice to try to clear secrets from memory after using them.
117- * This is done because some bugs can allow an attacker to leak memory, for
118- * example through "out of bounds" array access (see Heartbleed), or the OS
119- * swapping them to disk. Hence, we overwrite the secret key buffer with zeros.
120- *
121- * Here we are preventing these writes from being optimized out, as any good compiler
122- * will remove any writes that aren't used. */
123115 secure_erase (seckey1 , sizeof (seckey1 ));
124116 secure_erase (seckey2 , sizeof (seckey2 ));
125117 secure_erase (shared_secret1 , sizeof (shared_secret1 ));
0 commit comments