DIY Bitcoin Hardware
/
secp256k1_example
Simple example of secp256k1 library
main.cpp@2:6b892a0b43e5, 2019-09-16 (annotated)
- Committer:
- diybitcoinhardware
- Date:
- Mon Sep 16 12:17:13 2019 +0000
- Revision:
- 2:6b892a0b43e5
- Parent:
- 0:23d71aa111c7
increase stack size for RTOS
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
diybitcoinhardware | 0:23d71aa111c7 | 1 | #include "mbed.h" |
diybitcoinhardware | 0:23d71aa111c7 | 2 | |
diybitcoinhardware | 0:23d71aa111c7 | 3 | #include "secp256k1.h" |
diybitcoinhardware | 0:23d71aa111c7 | 4 | #include "secp256k1_preallocated.h" |
diybitcoinhardware | 0:23d71aa111c7 | 5 | |
diybitcoinhardware | 0:23d71aa111c7 | 6 | RawSerial pc(SERIAL_TX, SERIAL_RX, 115200); |
diybitcoinhardware | 0:23d71aa111c7 | 7 | |
diybitcoinhardware | 0:23d71aa111c7 | 8 | // small helper functions that prints |
diybitcoinhardware | 0:23d71aa111c7 | 9 | // data in hex to the serial port |
diybitcoinhardware | 0:23d71aa111c7 | 10 | void print_hex(const uint8_t * data, size_t data_len){ |
diybitcoinhardware | 0:23d71aa111c7 | 11 | for(int i=0; i<data_len; i++){ |
diybitcoinhardware | 0:23d71aa111c7 | 12 | printf("%02x", data[i]); |
diybitcoinhardware | 0:23d71aa111c7 | 13 | } |
diybitcoinhardware | 0:23d71aa111c7 | 14 | } |
diybitcoinhardware | 0:23d71aa111c7 | 15 | // just adds a new line to the end of the data |
diybitcoinhardware | 0:23d71aa111c7 | 16 | void println_hex(const uint8_t * data, size_t data_len){ |
diybitcoinhardware | 0:23d71aa111c7 | 17 | print_hex(data, data_len); |
diybitcoinhardware | 0:23d71aa111c7 | 18 | printf("\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 19 | } |
diybitcoinhardware | 0:23d71aa111c7 | 20 | // prints error and hangs forever |
diybitcoinhardware | 0:23d71aa111c7 | 21 | void err(const char * message, void * data = NULL){ |
diybitcoinhardware | 0:23d71aa111c7 | 22 | printf("ERROR: %s\r\n", message); |
diybitcoinhardware | 0:23d71aa111c7 | 23 | while(1){ |
diybitcoinhardware | 0:23d71aa111c7 | 24 | wait(1); |
diybitcoinhardware | 0:23d71aa111c7 | 25 | } |
diybitcoinhardware | 0:23d71aa111c7 | 26 | } |
diybitcoinhardware | 0:23d71aa111c7 | 27 | |
diybitcoinhardware | 0:23d71aa111c7 | 28 | void secp_example(){ |
diybitcoinhardware | 0:23d71aa111c7 | 29 | // secp256k1 context |
diybitcoinhardware | 0:23d71aa111c7 | 30 | secp256k1_context *ctx = NULL; |
diybitcoinhardware | 0:23d71aa111c7 | 31 | |
diybitcoinhardware | 0:23d71aa111c7 | 32 | int res; // to store results of function calls |
diybitcoinhardware | 0:23d71aa111c7 | 33 | size_t len; // to store serialization lengths |
diybitcoinhardware | 0:23d71aa111c7 | 34 | |
diybitcoinhardware | 0:23d71aa111c7 | 35 | printf("=== secp256k1 context ===\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 36 | |
diybitcoinhardware | 0:23d71aa111c7 | 37 | // first we need to create the context |
diybitcoinhardware | 0:23d71aa111c7 | 38 | // this is the size of memory to be allocated |
diybitcoinhardware | 0:23d71aa111c7 | 39 | size_t context_size = secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); |
diybitcoinhardware | 0:23d71aa111c7 | 40 | printf("Context size: %u bytes\r\n", context_size); |
diybitcoinhardware | 0:23d71aa111c7 | 41 | |
diybitcoinhardware | 0:23d71aa111c7 | 42 | // creating the context |
diybitcoinhardware | 0:23d71aa111c7 | 43 | ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); |
diybitcoinhardware | 0:23d71aa111c7 | 44 | printf("Context created\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 45 | |
diybitcoinhardware | 0:23d71aa111c7 | 46 | printf("=== Secret key ===\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 47 | // some random secret key |
diybitcoinhardware | 0:23d71aa111c7 | 48 | uint8_t secret[] = { |
diybitcoinhardware | 0:23d71aa111c7 | 49 | 0xbd, 0xb5, 0x1a, 0x16, 0xeb, 0x64, 0x60, 0xec, |
diybitcoinhardware | 0:23d71aa111c7 | 50 | 0x16, 0xf8, 0x4d, 0x7b, 0x6f, 0x19, 0xe2, 0x0d, |
diybitcoinhardware | 0:23d71aa111c7 | 51 | 0x9b, 0x9a, 0xb5, 0x58, 0xfa, 0x0e, 0x9a, 0xe4, |
diybitcoinhardware | 0:23d71aa111c7 | 52 | 0xbb, 0x49, 0x3e, 0xf7, 0x79, 0xf1, 0x40, 0x55 |
diybitcoinhardware | 0:23d71aa111c7 | 53 | }; |
diybitcoinhardware | 0:23d71aa111c7 | 54 | printf("Secret key: "); |
diybitcoinhardware | 0:23d71aa111c7 | 55 | println_hex(secret, sizeof(secret)); |
diybitcoinhardware | 0:23d71aa111c7 | 56 | |
diybitcoinhardware | 0:23d71aa111c7 | 57 | // Makes sense to check if secret key is valid. |
diybitcoinhardware | 0:23d71aa111c7 | 58 | // It will be ok in most cases, only if secret > N it will be invalid |
diybitcoinhardware | 0:23d71aa111c7 | 59 | res = secp256k1_ec_seckey_verify(ctx, secret); |
diybitcoinhardware | 0:23d71aa111c7 | 60 | if(!res){ err("Secret key is invalid"); } |
diybitcoinhardware | 0:23d71aa111c7 | 61 | |
diybitcoinhardware | 0:23d71aa111c7 | 62 | /**************** Public key ******************/ |
diybitcoinhardware | 0:23d71aa111c7 | 63 | |
diybitcoinhardware | 0:23d71aa111c7 | 64 | printf("=== Public key ===\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 65 | // computing corresponding pubkey |
diybitcoinhardware | 0:23d71aa111c7 | 66 | secp256k1_pubkey pubkey; |
diybitcoinhardware | 0:23d71aa111c7 | 67 | res = secp256k1_ec_pubkey_create(ctx, &pubkey, secret); |
diybitcoinhardware | 0:23d71aa111c7 | 68 | if(!res){ err("Pubkey computation failed"); } |
diybitcoinhardware | 0:23d71aa111c7 | 69 | |
diybitcoinhardware | 0:23d71aa111c7 | 70 | // serialize the pubkey in compressed format |
diybitcoinhardware | 0:23d71aa111c7 | 71 | uint8_t pub[33]; |
diybitcoinhardware | 0:23d71aa111c7 | 72 | len = sizeof(pub); |
diybitcoinhardware | 0:23d71aa111c7 | 73 | secp256k1_ec_pubkey_serialize(ctx, pub, &len, &pubkey, SECP256K1_EC_COMPRESSED); |
diybitcoinhardware | 0:23d71aa111c7 | 74 | printf("Public key: "); |
diybitcoinhardware | 0:23d71aa111c7 | 75 | println_hex(pub, len); |
diybitcoinhardware | 0:23d71aa111c7 | 76 | |
diybitcoinhardware | 0:23d71aa111c7 | 77 | // this is how you parse the pubkey |
diybitcoinhardware | 0:23d71aa111c7 | 78 | res = secp256k1_ec_pubkey_parse(ctx, &pubkey, pub, 33); |
diybitcoinhardware | 0:23d71aa111c7 | 79 | if(res){ |
diybitcoinhardware | 0:23d71aa111c7 | 80 | printf("Key is valid\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 81 | }else{ |
diybitcoinhardware | 0:23d71aa111c7 | 82 | printf("Invalid key\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 83 | } |
diybitcoinhardware | 0:23d71aa111c7 | 84 | |
diybitcoinhardware | 0:23d71aa111c7 | 85 | /**************** Signature stuff ******************/ |
diybitcoinhardware | 0:23d71aa111c7 | 86 | |
diybitcoinhardware | 0:23d71aa111c7 | 87 | printf("=== Signature generation ===\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 88 | |
diybitcoinhardware | 0:23d71aa111c7 | 89 | // hash of the string "hello" |
diybitcoinhardware | 0:23d71aa111c7 | 90 | uint8_t hash[32] = { |
diybitcoinhardware | 0:23d71aa111c7 | 91 | 0x2c, 0xf2, 0x4d, 0xba, 0x5f, 0xb0, 0xa3, 0x0e, |
diybitcoinhardware | 0:23d71aa111c7 | 92 | 0x26, 0xe8, 0x3b, 0x2a, 0xc5, 0xb9, 0xe2, 0x9e, |
diybitcoinhardware | 0:23d71aa111c7 | 93 | 0x1b, 0x16, 0x1e, 0x5c, 0x1f, 0xa7, 0x42, 0x5e, |
diybitcoinhardware | 0:23d71aa111c7 | 94 | 0x73, 0x04, 0x33, 0x62, 0x93, 0x8b, 0x98, 0x24 |
diybitcoinhardware | 0:23d71aa111c7 | 95 | }; |
diybitcoinhardware | 0:23d71aa111c7 | 96 | // signing |
diybitcoinhardware | 0:23d71aa111c7 | 97 | secp256k1_ecdsa_signature sig; |
diybitcoinhardware | 0:23d71aa111c7 | 98 | res = secp256k1_ecdsa_sign(ctx, &sig, hash, secret, NULL, NULL); |
diybitcoinhardware | 0:23d71aa111c7 | 99 | if(!res){ err("Can't sign"); } |
diybitcoinhardware | 0:23d71aa111c7 | 100 | |
diybitcoinhardware | 0:23d71aa111c7 | 101 | // serialization |
diybitcoinhardware | 0:23d71aa111c7 | 102 | uint8_t der[72]; |
diybitcoinhardware | 0:23d71aa111c7 | 103 | len = sizeof(der); |
diybitcoinhardware | 0:23d71aa111c7 | 104 | res = secp256k1_ecdsa_signature_serialize_der(ctx, der, &len, &sig); |
diybitcoinhardware | 0:23d71aa111c7 | 105 | if(!res){ err("Can't serialize the signature"); } |
diybitcoinhardware | 0:23d71aa111c7 | 106 | printf("Signature: "); |
diybitcoinhardware | 0:23d71aa111c7 | 107 | println_hex(der, len); |
diybitcoinhardware | 0:23d71aa111c7 | 108 | |
diybitcoinhardware | 0:23d71aa111c7 | 109 | // verification |
diybitcoinhardware | 0:23d71aa111c7 | 110 | printf("=== Signature verification ===\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 111 | res = secp256k1_ecdsa_verify(ctx, &sig, hash, &pubkey); |
diybitcoinhardware | 0:23d71aa111c7 | 112 | if(res){ |
diybitcoinhardware | 0:23d71aa111c7 | 113 | printf("Signature is valid\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 114 | }else{ |
diybitcoinhardware | 0:23d71aa111c7 | 115 | printf("Invalid signature\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 116 | } |
diybitcoinhardware | 0:23d71aa111c7 | 117 | |
diybitcoinhardware | 0:23d71aa111c7 | 118 | secp256k1_context_destroy(ctx); |
diybitcoinhardware | 0:23d71aa111c7 | 119 | } |
diybitcoinhardware | 0:23d71aa111c7 | 120 | |
diybitcoinhardware | 0:23d71aa111c7 | 121 | int main(){ |
diybitcoinhardware | 0:23d71aa111c7 | 122 | printf("Press any key to continue\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 123 | pc.getc(); |
diybitcoinhardware | 0:23d71aa111c7 | 124 | printf("Ready to go!\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 125 | |
diybitcoinhardware | 0:23d71aa111c7 | 126 | printf("=== Running example for secp256k1 ===\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 127 | secp_example(); |
diybitcoinhardware | 0:23d71aa111c7 | 128 | |
diybitcoinhardware | 0:23d71aa111c7 | 129 | |
diybitcoinhardware | 0:23d71aa111c7 | 130 | printf("\r\n=== Done ===\r\n"); |
diybitcoinhardware | 0:23d71aa111c7 | 131 | |
diybitcoinhardware | 0:23d71aa111c7 | 132 | } |