Skip to content
Fork of the secp256k1 library working in Arduino and Mbed
C C++ M4 Other
Branch: master
Clone or download
Pull request Compare This branch is 3 commits ahead, 9 commits behind bitcoin-core:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
contrib
examples/basic_example
src
.gitignore
.travis.yml
COPYING
Makefile.am
README.md
TODO
autogen.sh
configure.ac
keywords.txt
library.properties
libsecp256k1.pc.in

README.md

libsecp256k1 for microcontrollers

About this fork

This fork includes minimal changes in the source files of the original libsecp256k1 library by Bitcoin Core.

It moves around files and changes some #include paths such that Arduino and Mbed IDEs can understand it.

Config file and precomputed table for 32-bit microcontrollers are also included.

Tested on ESP32 (M5Stack) and STM32F469I-Discovery (Mbed OS - bare metal, no RTOS).

Installation

For Arduino:

Clone this repo to the Arduino/libraries/ folder (or download zip file and select Sketch->Include Library->Add .ZIP Library. Check out the example to see it in action.

For Mbed:

Clone this repo to the project folder, for Mbed-CLI use mbed add https://github.com/diybitcoinhardware/secp256k1.git, for online IDE do Import Library and put there a link to this repo.

You can also import this project and start from it.

Usage

A very basic example:

// secp256k1 context
secp256k1_context *ctx = NULL;

int res;    // to store results of function calls
size_t len; // to store serialization lengths

// first we need to create the context
// this is the size of memory to be allocated
size_t context_size = secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);

// creating the context
ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);

// some random secret key
uint8_t secret[] = {
	0xbd, 0xb5, 0x1a, 0x16, 0xeb, 0x64, 0x60, 0xec, 
	0x16, 0xf8, 0x4d, 0x7b, 0x6f, 0x19, 0xe2, 0x0d, 
	0x9b, 0x9a, 0xb5, 0x58, 0xfa, 0x0e, 0x9a, 0xe4, 
	0xbb, 0x49, 0x3e, 0xf7, 0x79, 0xf1, 0x40, 0x55
};

// Makes sense to check if secret key is valid.
// It will be ok in most cases, only if secret > N it will be invalid
res = secp256k1_ec_seckey_verify(ctx, secret);
if(!res){ return; /* handle error here */ }

/**************** Public key ******************/

// computing corresponding pubkey
secp256k1_pubkey pubkey;
res = secp256k1_ec_pubkey_create(ctx, &pubkey, secret);
if(!res){ return; /* handle error here */ }

// serialize the pubkey in compressed format
uint8_t pub[33];
len = sizeof(pub);
secp256k1_ec_pubkey_serialize(ctx, pub, &len, &pubkey, SECP256K1_EC_COMPRESSED);

// this is how you parse the pubkey
res = secp256k1_ec_pubkey_parse(ctx, &pubkey, pub, 33);
if(res){
	// Key is valid
}else{
	// Invalid pubkey
}

/**************** Signature stuff ******************/

// hash of the string "hello"
uint8_t hash[32] = { 
	0x2c, 0xf2, 0x4d, 0xba, 0x5f, 0xb0, 0xa3, 0x0e, 
	0x26, 0xe8, 0x3b, 0x2a, 0xc5, 0xb9, 0xe2, 0x9e, 
	0x1b, 0x16, 0x1e, 0x5c, 0x1f, 0xa7, 0x42, 0x5e, 
	0x73, 0x04, 0x33, 0x62, 0x93, 0x8b, 0x98, 0x24 
};
// signing
secp256k1_ecdsa_signature sig;
res = secp256k1_ecdsa_sign(ctx, &sig, hash, secret, NULL, NULL);
if(!res){ return; /* handle error here */ }

// serialization
uint8_t der[72];
len = sizeof(der);
res = secp256k1_ecdsa_signature_serialize_der(ctx, der, &len, &sig);
if(!res){ return; /* handle error here */ }

// verification
res = secp256k1_ecdsa_verify(ctx, &sig, hash, &pubkey);
if(res){
	// Signature is valid
}else{
	// Invalid signature
}

secp256k1_context_destroy(ctx);
You can’t perform that action at this time.