Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1/*************************************************************************2* Written in 2020-2022 by Elichai Turkel *3* To the extent possible under law, the author(s) have dedicated all *4* copyright and related and neighboring rights to the software in this *5* file to the public domain worldwide. This software is distributed *6* without any warranty. For the CC0 Public Domain Dedication, see *7* EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 *8*************************************************************************/10#include <stdio.h>11#include <stdlib.h>12#include <assert.h>13#include <string.h>15#include <secp256k1.h>16#include <secp256k1_ecdh.h>18#include "examples_util.h"20int main(void) {21unsigned char seckey1[32];22unsigned char seckey2[32];23unsigned char compressed_pubkey1[33];24unsigned char compressed_pubkey2[33];25unsigned char shared_secret1[32];26unsigned char shared_secret2[32];27unsigned char randomize[32];28int return_val;29size_t len;30secp256k1_pubkey pubkey1;31secp256k1_pubkey pubkey2;33/* Before we can call actual API functions, we need to create a "context". */34secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);35if (!fill_random(randomize, sizeof(randomize))) {36printf("Failed to generate randomness\n");37return EXIT_FAILURE;38}39/* Randomizing the context is recommended to protect against side-channel40* leakage See `secp256k1_context_randomize` in secp256k1.h for more41* information about it. This should never fail. */42return_val = secp256k1_context_randomize(ctx, randomize);43assert(return_val);45/*** Key Generation ***/46if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) {47printf("Failed to generate randomness\n");48return EXIT_FAILURE;49}50/* If the secret key is zero or out of range (greater than secp256k1's51* order), we fail. Note that the probability of this occurring is negligible52* with a properly functioning random number generator. */53if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) {54printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n");55return EXIT_FAILURE;56}58/* Public key creation using a valid context with a verified secret key should never fail */59return_val = secp256k1_ec_pubkey_create(ctx, &pubkey1, seckey1);60assert(return_val);61return_val = secp256k1_ec_pubkey_create(ctx, &pubkey2, seckey2);62assert(return_val);64/* Serialize pubkey1 in a compressed form (33 bytes), should always return 1 */65len = sizeof(compressed_pubkey1);66return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey1, &len, &pubkey1, SECP256K1_EC_COMPRESSED);67assert(return_val);68/* Should be the same size as the size of the output, because we passed a 33 byte array. */69assert(len == sizeof(compressed_pubkey1));71/* Serialize pubkey2 in a compressed form (33 bytes) */72len = sizeof(compressed_pubkey2);73return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey2, &len, &pubkey2, SECP256K1_EC_COMPRESSED);74assert(return_val);75/* Should be the same size as the size of the output, because we passed a 33 byte array. */76assert(len == sizeof(compressed_pubkey2));78/*** Creating the shared secret ***/80/* Perform ECDH with seckey1 and pubkey2. Should never fail with a verified81* seckey and valid pubkey */82return_val = secp256k1_ecdh(ctx, shared_secret1, &pubkey2, seckey1, NULL, NULL);83assert(return_val);85/* Perform ECDH with seckey2 and pubkey1. Should never fail with a verified86* seckey and valid pubkey */87return_val = secp256k1_ecdh(ctx, shared_secret2, &pubkey1, seckey2, NULL, NULL);88assert(return_val);90/* Both parties should end up with the same shared secret */91return_val = memcmp(shared_secret1, shared_secret2, sizeof(shared_secret1));92assert(return_val == 0);94printf("Secret Key1: ");95print_hex(seckey1, sizeof(seckey1));96printf("Compressed Pubkey1: ");97print_hex(compressed_pubkey1, sizeof(compressed_pubkey1));98printf("\nSecret Key2: ");99print_hex(seckey2, sizeof(seckey2));100printf("Compressed Pubkey2: ");101print_hex(compressed_pubkey2, sizeof(compressed_pubkey2));102printf("\nShared Secret: ");103print_hex(shared_secret1, sizeof(shared_secret1));105/* This will clear everything from the context and free the memory */106secp256k1_context_destroy(ctx);108/* It's best practice to try to clear secrets from memory after using them.109* This is done because some bugs can allow an attacker to leak memory, for110* example through "out of bounds" array access (see Heartbleed), or the OS111* swapping them to disk. Hence, we overwrite the secret key buffer with zeros.112*113* Here we are preventing these writes from being optimized out, as any good compiler114* will remove any writes that aren't used. */115secure_erase(seckey1, sizeof(seckey1));116secure_erase(seckey2, sizeof(seckey2));117secure_erase(shared_secret1, sizeof(shared_secret1));118secure_erase(shared_secret2, sizeof(shared_secret2));120return EXIT_SUCCESS;121}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.