├── .gitmodules ├── .mbedignore ├── LICENSE ├── README.md ├── examples ├── basic_example │ └── basic_example.ino ├── mbed │ ├── main.cpp │ └── mbed_app.json └── secp256k1.py ├── keywords.txt ├── library.properties ├── micropython.mk ├── mpy ├── config │ ├── ecmult_static_context.h │ ├── ext_callbacks.c │ └── libsecp256k1-config.h └── libsecp256k1.c ├── secp256k1.lib └── src ├── ecmult_const_impl.h ├── ecmult_static_context.h ├── include ├── secp256k1.h ├── secp256k1_ecdh.h ├── secp256k1_preallocated.h └── secp256k1_recovery.h ├── libsecp256k1-config.h ├── secp256k1.h ├── secp256k1_bundle.c ├── secp256k1_ecdh.h ├── secp256k1_preallocated.h └── secp256k1_recovery.h /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "secp256k1"] 2 | path = secp256k1 3 | url = https://github.com/bitcoin-core/secp256k1.git 4 | -------------------------------------------------------------------------------- /.mbedignore: -------------------------------------------------------------------------------- 1 | secp256k1/* 2 | examples/* 3 | mpy/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 diybitcoinhardware 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # secp256k1 for embedded systems: Arduino, Mbed and MicroPython 2 | 3 | # About this repository 4 | 5 | [secp256k1](https://github.com/bitcoin-core/secp256k1/) is an elliptic curve library developed and maintained by Bitcoin Core community. 6 | 7 | **This repository** makes it easy to use the library with Arduino IDE, ARM Mbed and MicroPython. 8 | 9 | For Arduino and Mbed it introduces a few hacks to get around their recursive build system. For MicroPython it defines [bindings](./mpy/libsecp256k1.c) that makes the library accessible from MicroPython. 10 | 11 | Tested on ESP32 (M5Stack, TTGO) and STM32F469I-Discovery, but should work on any 32-bit MCU. 12 | 13 | # Installation 14 | 15 | ## MicroPython 16 | 17 | Clone with `--recursive` flag to the folder where you store user modules. 18 | 19 | Compile MicroPython for your board with user modules and `CFLAGS_EXTRA=-DMODULE_SECP256K1_ENABLED=1` flag. For example: 20 | 21 | ```sh 22 | make BOARD=STM32F469DISC USER_C_MODULES=../../../usermods CFLAGS_EXTRA=-DMODULE_SECP256K1_ENABLED=1 23 | ``` 24 | 25 | Here replace `STM32F469DISC` to your board name, `../../../usermods` to your path to usermods folder. 26 | 27 | Here is a usage example for MicroPython: [`examples/secp256k1.py`](examples/secp256k1.py) 28 | 29 | ## Arduino IDE 30 | 31 | Clone this repo with `--recursive` flag to the `Arduino/libraries/` folder (or download zip file and select `Sketch->Include Library->Add .ZIP Library`. 32 | 33 | Check out the [example](examples/basic_example/basic_example.ino) for Arduino to see it in action. 34 | 35 | ## ARM Mbed 36 | 37 | Clone this repo with `--recursive` flag to the project folder, or whatever folder you store libraries in. In the online IDE do `Import Library` and put there a link to this repository. 38 | 39 | Check out the [example](examples/mbed/main.cpp). You can also import [this project](https://os.mbed.com/users/diybitcoinhardware/code/secp256k1_example/) and start from there. 40 | 41 | **Important!** Library mostly uses stack, and mbed has pretty small default limitat for the stack size. You can increase the stack size in `mbed_app.json` file: 42 | 43 | ```json 44 | { 45 | "target_overrides": { 46 | "*": { 47 | "rtos.main-thread-stack-size": "8192" 48 | } 49 | } 50 | } 51 | ``` 52 | 53 | Or you can use bare-metal mbed version: 54 | 55 | ```json 56 | { 57 | "requires": ["bare-metal"] 58 | } 59 | ``` 60 | 61 | ## Usage 62 | 63 | A very basic example in C/C++: 64 | 65 | ```cpp 66 | // secp256k1 context 67 | secp256k1_context *ctx = NULL; 68 | 69 | int res; // to store results of function calls 70 | size_t len; // to store serialization lengths 71 | 72 | // first we need to create the context 73 | // this is the size of memory to be allocated 74 | size_t context_size = secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); 75 | 76 | // creating the context 77 | ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); 78 | 79 | // some random secret key 80 | uint8_t secret[] = { 81 | 0xbd, 0xb5, 0x1a, 0x16, 0xeb, 0x64, 0x60, 0xec, 82 | 0x16, 0xf8, 0x4d, 0x7b, 0x6f, 0x19, 0xe2, 0x0d, 83 | 0x9b, 0x9a, 0xb5, 0x58, 0xfa, 0x0e, 0x9a, 0xe4, 84 | 0xbb, 0x49, 0x3e, 0xf7, 0x79, 0xf1, 0x40, 0x55 85 | }; 86 | 87 | // Makes sense to check if secret key is valid. 88 | // It will be ok in most cases, only if secret > N it will be invalid 89 | res = secp256k1_ec_seckey_verify(ctx, secret); 90 | if(!res){ return; /* handle error here */ } 91 | 92 | /**************** Public key ******************/ 93 | 94 | // computing corresponding pubkey 95 | secp256k1_pubkey pubkey; 96 | res = secp256k1_ec_pubkey_create(ctx, &pubkey, secret); 97 | if(!res){ return; /* handle error here */ } 98 | 99 | // serialize the pubkey in compressed format 100 | uint8_t pub[33]; 101 | len = sizeof(pub); 102 | secp256k1_ec_pubkey_serialize(ctx, pub, &len, &pubkey, SECP256K1_EC_COMPRESSED); 103 | 104 | // this is how you parse the pubkey 105 | res = secp256k1_ec_pubkey_parse(ctx, &pubkey, pub, 33); 106 | if(res){ 107 | // Key is valid 108 | }else{ 109 | // Invalid pubkey 110 | } 111 | 112 | /**************** Signature stuff ******************/ 113 | 114 | // hash of the string "hello" 115 | uint8_t hash[32] = { 116 | 0x2c, 0xf2, 0x4d, 0xba, 0x5f, 0xb0, 0xa3, 0x0e, 117 | 0x26, 0xe8, 0x3b, 0x2a, 0xc5, 0xb9, 0xe2, 0x9e, 118 | 0x1b, 0x16, 0x1e, 0x5c, 0x1f, 0xa7, 0x42, 0x5e, 119 | 0x73, 0x04, 0x33, 0x62, 0x93, 0x8b, 0x98, 0x24 120 | }; 121 | // signing 122 | secp256k1_ecdsa_signature sig; 123 | res = secp256k1_ecdsa_sign(ctx, &sig, hash, secret, NULL, NULL); 124 | if(!res){ return; /* handle error here */ } 125 | 126 | // serialization 127 | uint8_t der[72]; 128 | len = sizeof(der); 129 | res = secp256k1_ecdsa_signature_serialize_der(ctx, der, &len, &sig); 130 | if(!res){ return; /* handle error here */ } 131 | 132 | // verification 133 | res = secp256k1_ecdsa_verify(ctx, &sig, hash, &pubkey); 134 | if(res){ 135 | // Signature is valid 136 | }else{ 137 | // Invalid signature 138 | } 139 | 140 | secp256k1_context_destroy(ctx); 141 | ``` -------------------------------------------------------------------------------- /examples/basic_example/basic_example.ino: -------------------------------------------------------------------------------- 1 | #include "secp256k1.h" 2 | #include "secp256k1_preallocated.h" 3 | 4 | // forward declaration 5 | void print_err(const char * message, void * data = NULL); 6 | 7 | void setup() { 8 | // put your setup code here, to run once: 9 | Serial.begin(115200); 10 | Serial.println("Press any key to continue."); 11 | while(!Serial.available()){ 12 | delay(100); 13 | } 14 | Serial.println("\nOk, let's rock!"); 15 | secp_example(); 16 | Serial.println("=== Done ==="); 17 | } 18 | 19 | void loop() { 20 | delay(1000); 21 | } 22 | 23 | void secp_example(){ 24 | // secp256k1 context 25 | secp256k1_context *ctx = NULL; 26 | 27 | int res; // to store results of function calls 28 | size_t len; // to store serialization lengths 29 | 30 | Serial.print("=== secp256k1 context ===\r\n"); 31 | 32 | // first we need to create the context 33 | // this is the size of memory to be allocated 34 | size_t context_size = secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); 35 | Serial.print("Context size: "); 36 | Serial.print(context_size); 37 | Serial.println(" bytes"); 38 | 39 | // creating the context 40 | // you can also preallocate it yourself and 41 | // pass to secp256k1_context_preallocated_create 42 | ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); 43 | Serial.print("Context created\r\n"); 44 | 45 | // if you have true random number generator 46 | // it makes sense to randomize context from time to time 47 | // to avoid sidechannel attacks: 48 | // secp256k1_context_randomize(ctx, byte[32] random_buf); 49 | 50 | Serial.print("=== Secret key ===\r\n"); 51 | // some random secret key 52 | uint8_t secret[] = { 53 | 0xbd, 0xb5, 0x1a, 0x16, 0xeb, 0x64, 0x60, 0xec, 54 | 0x16, 0xf8, 0x4d, 0x7b, 0x6f, 0x19, 0xe2, 0x0d, 55 | 0x9b, 0x9a, 0xb5, 0x58, 0xfa, 0x0e, 0x9a, 0xe4, 56 | 0xbb, 0x49, 0x3e, 0xf7, 0x79, 0xf1, 0x40, 0x55 57 | }; 58 | Serial.print("Secret key: "); 59 | println_hex(secret, sizeof(secret)); 60 | 61 | // Makes sense to check if secret key is valid. 62 | // It will be ok in most cases, only if secret > N it will be invalid 63 | res = secp256k1_ec_seckey_verify(ctx, secret); 64 | if(!res){ print_err("Secret key is invalid"); } 65 | 66 | /**************** Public key ******************/ 67 | 68 | Serial.print("=== Public key ===\r\n"); 69 | // computing corresponding pubkey 70 | secp256k1_pubkey pubkey; 71 | res = secp256k1_ec_pubkey_create(ctx, &pubkey, secret); 72 | if(!res){ print_err("Pubkey computation failed"); } 73 | 74 | // serialize the pubkey in compressed format 75 | uint8_t pub[33]; 76 | len = sizeof(pub); 77 | secp256k1_ec_pubkey_serialize(ctx, pub, &len, &pubkey, SECP256K1_EC_COMPRESSED); 78 | Serial.print("Public key: "); 79 | println_hex(pub, len); 80 | 81 | // this is how you parse the pubkey 82 | res = secp256k1_ec_pubkey_parse(ctx, &pubkey, pub, 33); 83 | if(res){ 84 | Serial.print("Key is valid\r\n"); 85 | }else{ 86 | Serial.print("Invalid key\r\n"); 87 | } 88 | 89 | /**************** Signature stuff ******************/ 90 | 91 | Serial.print("=== Signature generation ===\r\n"); 92 | 93 | // hash of the string "hello" 94 | uint8_t hash[32] = { 95 | 0x2c, 0xf2, 0x4d, 0xba, 0x5f, 0xb0, 0xa3, 0x0e, 96 | 0x26, 0xe8, 0x3b, 0x2a, 0xc5, 0xb9, 0xe2, 0x9e, 97 | 0x1b, 0x16, 0x1e, 0x5c, 0x1f, 0xa7, 0x42, 0x5e, 98 | 0x73, 0x04, 0x33, 0x62, 0x93, 0x8b, 0x98, 0x24 99 | }; 100 | // signing 101 | secp256k1_ecdsa_signature sig; 102 | res = secp256k1_ecdsa_sign(ctx, &sig, hash, secret, NULL, NULL); 103 | if(!res){ print_err("Can't sign"); } 104 | 105 | // serialization 106 | uint8_t der[72]; 107 | len = sizeof(der); 108 | res = secp256k1_ecdsa_signature_serialize_der(ctx, der, &len, &sig); 109 | if(!res){ print_err("Can't serialize the signature"); } 110 | Serial.print("Signature: "); 111 | println_hex(der, len); 112 | 113 | // signature verification 114 | Serial.print("=== Signature verification ===\r\n"); 115 | res = secp256k1_ecdsa_verify(ctx, &sig, hash, &pubkey); 116 | if(res){ 117 | Serial.print("Signature is valid\r\n"); 118 | }else{ 119 | Serial.print("Invalid signature\r\n"); 120 | } 121 | 122 | // clean up when context is not needed any more 123 | secp256k1_context_destroy(ctx); 124 | } 125 | 126 | void print_hex(const uint8_t * data, size_t data_len){ 127 | char arr[3]; 128 | for(int i=0; i N it will be invalid 59 | res = secp256k1_ec_seckey_verify(ctx, secret); 60 | if(!res){ err("Secret key is invalid"); } 61 | 62 | /**************** Public key ******************/ 63 | 64 | printf("=== Public key ===\r\n"); 65 | // computing corresponding pubkey 66 | secp256k1_pubkey pubkey; 67 | res = secp256k1_ec_pubkey_create(ctx, &pubkey, secret); 68 | if(!res){ err("Pubkey computation failed"); } 69 | 70 | // serialize the pubkey in compressed format 71 | uint8_t pub[33]; 72 | len = sizeof(pub); 73 | secp256k1_ec_pubkey_serialize(ctx, pub, &len, &pubkey, SECP256K1_EC_COMPRESSED); 74 | printf("Public key: "); 75 | println_hex(pub, len); 76 | 77 | // this is how you parse the pubkey 78 | res = secp256k1_ec_pubkey_parse(ctx, &pubkey, pub, 33); 79 | if(res){ 80 | printf("Key is valid\r\n"); 81 | }else{ 82 | printf("Invalid key\r\n"); 83 | } 84 | 85 | /**************** Signature stuff ******************/ 86 | 87 | printf("=== Signature generation ===\r\n"); 88 | 89 | // hash of the string "hello" 90 | uint8_t hash[32] = { 91 | 0x2c, 0xf2, 0x4d, 0xba, 0x5f, 0xb0, 0xa3, 0x0e, 92 | 0x26, 0xe8, 0x3b, 0x2a, 0xc5, 0xb9, 0xe2, 0x9e, 93 | 0x1b, 0x16, 0x1e, 0x5c, 0x1f, 0xa7, 0x42, 0x5e, 94 | 0x73, 0x04, 0x33, 0x62, 0x93, 0x8b, 0x98, 0x24 95 | }; 96 | // signing 97 | secp256k1_ecdsa_signature sig; 98 | res = secp256k1_ecdsa_sign(ctx, &sig, hash, secret, NULL, NULL); 99 | if(!res){ err("Can't sign"); } 100 | 101 | // serialization 102 | uint8_t der[72]; 103 | len = sizeof(der); 104 | res = secp256k1_ecdsa_signature_serialize_der(ctx, der, &len, &sig); 105 | if(!res){ err("Can't serialize the signature"); } 106 | printf("Signature: "); 107 | println_hex(der, len); 108 | 109 | // verification 110 | printf("=== Signature verification ===\r\n"); 111 | res = secp256k1_ecdsa_verify(ctx, &sig, hash, &pubkey); 112 | if(res){ 113 | printf("Signature is valid\r\n"); 114 | }else{ 115 | printf("Invalid signature\r\n"); 116 | } 117 | 118 | secp256k1_context_destroy(ctx); 119 | } 120 | 121 | int main(){ 122 | printf("Press any key to continue\r\n"); 123 | pc.getc(); 124 | printf("Ready to go!\r\n"); 125 | 126 | printf("=== Running example for secp256k1 ===\r\n"); 127 | secp_example(); 128 | 129 | 130 | printf("\r\n=== Done ===\r\n"); 131 | 132 | } -------------------------------------------------------------------------------- /examples/mbed/mbed_app.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_overrides": { 3 | "*": { 4 | "rtos.main-thread-stack-size": "8192" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/secp256k1.py: -------------------------------------------------------------------------------- 1 | import secp256k1 2 | import hashlib 3 | from binascii import hexlify 4 | 5 | def secp256k1_example(): 6 | """Usage example for secp256k1 usermodule""" 7 | 8 | # randomize context from time to time 9 | # - it helps against sidechannel attacks 10 | # secp256k1.context_randomize(os.urandom(32)) 11 | 12 | # some random secret key 13 | secret = hashlib.sha256(b"secret key").digest() 14 | 15 | print("Secret key:", hexlify(secret).decode()) 16 | 17 | # Makes sense to check if secret key is valid. 18 | # It will be ok in most cases, only if secret > N it will be invalid 19 | if not secp256k1.ec_seckey_verify(secret): 20 | raise ValueError("Secret key is invalid") 21 | 22 | # computing corresponding pubkey 23 | pubkey = secp256k1.ec_pubkey_create(secret) 24 | 25 | # serialize the pubkey in compressed format 26 | sec = secp256k1.ec_pubkey_serialize(pubkey, secp256k1.EC_COMPRESSED) 27 | print("Public key:", hexlify(sec).decode()) 28 | 29 | # this is how you parse the pubkey 30 | pubkey = secp256k1.ec_pubkey_parse(sec) 31 | 32 | # Signature generation: 33 | 34 | # hash of the string "hello" 35 | msg = hashlib.sha256(b"hello").digest() 36 | # signing 37 | sig = secp256k1.ecdsa_sign(msg, secret) 38 | 39 | # serialization 40 | der = secp256k1.ecdsa_signature_serialize_der(sig) 41 | 42 | print("Signature:", hexlify(der).decode()) 43 | 44 | # verification 45 | if secp256k1.ecdsa_verify(sig, msg, pubkey): 46 | print("Signature is valid") 47 | else: 48 | printf("Invalid signature") 49 | 50 | if __name__ == '__main__': 51 | secp256k1_example() -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | secp256k1_context KEYWORD1 10 | secp256k1_scratch_space KEYWORD1 11 | secp256k1_pubkey KEYWORD1 12 | secp256k1_ecdsa_signature KEYWORD1 13 | secp256k1_context_no_precomp KEYWORD1 14 | secp256k1_ecdsa_recoverable_signature KEYWORD1 15 | 16 | ####################################### 17 | # Methods and Functions (KEYWORD2) 18 | ####################################### 19 | 20 | secp256k1_context_create KEYWORD2 21 | secp256k1_context_clone KEYWORD2 22 | secp256k1_context_destroy KEYWORD2 23 | secp256k1_context_set_illegal_callback KEYWORD2 24 | secp256k1_context_set_error_callback KEYWORD2 25 | secp256k1_scratch_space_create KEYWORD2 26 | secp256k1_scratch_space_destroy KEYWORD2 27 | secp256k1_ec_pubkey_parse KEYWORD2 28 | secp256k1_ec_pubkey_serialize KEYWORD2 29 | secp256k1_ecdsa_signature_parse_compact KEYWORD2 30 | secp256k1_ecdsa_signature_parse_der KEYWORD2 31 | secp256k1_ecdsa_signature_serialize_der KEYWORD2 32 | secp256k1_ecdsa_signature_serialize_compact KEYWORD2 33 | secp256k1_ecdsa_verify KEYWORD2 34 | secp256k1_ecdsa_signature_normalize KEYWORD2 35 | secp256k1_ecdsa_sign KEYWORD2 36 | secp256k1_ec_seckey_verify KEYWORD2 37 | secp256k1_ec_pubkey_create KEYWORD2 38 | secp256k1_ec_privkey_negate KEYWORD2 39 | secp256k1_ec_pubkey_negate KEYWORD2 40 | secp256k1_ec_privkey_tweak_add KEYWORD2 41 | secp256k1_ec_pubkey_tweak_add KEYWORD2 42 | secp256k1_ec_privkey_tweak_mul KEYWORD2 43 | secp256k1_ec_pubkey_tweak_mul KEYWORD2 44 | secp256k1_context_randomize KEYWORD2 45 | secp256k1_ec_pubkey_combine KEYWORD2 46 | 47 | secp256k1_context_preallocated_size KEYWORD2 48 | secp256k1_context_preallocated_create KEYWORD2 49 | secp256k1_context_preallocated_clone_size KEYWORD2 50 | secp256k1_context_preallocated_clone KEYWORD2 51 | secp256k1_context_preallocated_destroy KEYWORD2 52 | secp256k1_ecdh KEYWORD2 53 | secp256k1_ecdsa_recoverable_signature_parse_compact KEYWORD2 54 | secp256k1_ecdsa_recoverable_signature_convert KEYWORD2 55 | secp256k1_ecdsa_recoverable_signature_serialize_compact KEYWORD2 56 | secp256k1_ecdsa_sign_recoverable KEYWORD2 57 | secp256k1_ecdsa_recover KEYWORD2 58 | 59 | secp256k1_nonce_function KEYWORD2 60 | secp256k1_nonce_function_rfc6979 KEYWORD2 61 | secp256k1_nonce_function_default KEYWORD2 62 | 63 | secp256k1_ecdh_hash_function_sha256 KEYWORD2 64 | secp256k1_ecdh_hash_function_default KEYWORD2 65 | 66 | ####################################### 67 | # Constants (LITERAL1) 68 | ####################################### 69 | 70 | SECP256K1_CONTEXT_VERIFY LITERAL1 71 | SECP256K1_CONTEXT_SIGN LITERAL1 72 | SECP256K1_CONTEXT_NONE LITERAL1 73 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=secp256k1 2 | version=1.0.0 3 | author=Bitcoin Core community 4 | maintainer= 5 | sentence=Bitcoin Core library for secp256k1 elliptic curve 6 | paragraph=Bitcoin Core library for secp256k1 elliptic curve 7 | category=Uncategorized 8 | url= 9 | architectures=* 10 | includes=secp256k1.h -------------------------------------------------------------------------------- /micropython.mk: -------------------------------------------------------------------------------- 1 | SECP256K1_MODULE_DIR := $(USERMOD_DIR) 2 | 3 | # Add all C files to SRC_USERMOD. 4 | SRC_USERMOD += $(SECP256K1_MODULE_DIR)/secp256k1/src/secp256k1.c 5 | SRC_USERMOD += $(SECP256K1_MODULE_DIR)/mpy/config/ext_callbacks.c 6 | SRC_USERMOD += $(SECP256K1_MODULE_DIR)/mpy/libsecp256k1.c 7 | 8 | # We can add our module folder to include paths if needed 9 | CFLAGS_USERMOD += -I$(SECP256K1_MODULE_DIR)/secp256k1 -I$(SECP256K1_MODULE_DIR)/secp256k1/src -I$(SECP256K1_MODULE_DIR)/mpy/config -DHAVE_CONFIG_H -Wno-unused-function -------------------------------------------------------------------------------- /mpy/config/ecmult_static_context.h: -------------------------------------------------------------------------------- 1 | #include "../../src/ecmult_static_context.h" -------------------------------------------------------------------------------- /mpy/config/ext_callbacks.c: -------------------------------------------------------------------------------- 1 | void secp256k1_default_illegal_callback_fn(const char* str, void* data){} 2 | void secp256k1_default_error_callback_fn(const char* str, void* data){} -------------------------------------------------------------------------------- /mpy/config/libsecp256k1-config.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_CONFIG_H 2 | #define SECP256K1_CONFIG_H 3 | 4 | #undef USE_ASM_X86_64 5 | #undef USE_ECMULT_STATIC_PRECOMPUTATION 6 | #undef USE_ENDOMORPHISM 7 | #undef USE_EXTERNAL_ASM 8 | #undef USE_EXTERNAL_DEFAULT_CALLBACKS 9 | #undef USE_FIELD_10X26 10 | #undef USE_FIELD_5X52 11 | #undef USE_FIELD_INV_BUILTIN 12 | #undef USE_FIELD_INV_NUM 13 | #undef USE_NUM_GMP 14 | #undef USE_NUM_NONE 15 | #undef USE_SCALAR_4X64 16 | #undef USE_SCALAR_8X32 17 | #undef USE_SCALAR_INV_BUILTIN 18 | #undef USE_SCALAR_INV_NUM 19 | #undef ECMULT_WINDOW_SIZE 20 | 21 | #define ENABLE_MODULE_ECDH 1 22 | #define ENABLE_MODULE_RECOVERY 1 23 | #define ENABLE_MODULE_EXTRAKEYS 1 24 | #define ENABLE_MODULE_SCHNORRSIG 1 25 | 26 | #define USE_NUM_NONE 1 27 | #define USE_FIELD_INV_BUILTIN 1 28 | #define USE_SCALAR_INV_BUILTIN 1 29 | #define USE_FIELD_10X26 1 30 | #define USE_SCALAR_8X32 1 31 | 32 | #define USE_ECMULT_STATIC_PRECOMPUTATION 1 33 | #define ECMULT_GEN_PREC_BITS 4 34 | #define ECMULT_WINDOW_SIZE 4 35 | 36 | #define HAVE_STDINT_H 1 37 | #define HAVE_STDLIB_H 1 38 | #define HAVE_STRING_H 1 39 | 40 | #define USE_EXTERNAL_DEFAULT_CALLBACKS 41 | 42 | // malloc and free in micropython 43 | #include 44 | #include 45 | #include 46 | 47 | #include "py/mpconfig.h" 48 | #include "py/misc.h" 49 | #include "py/mpstate.h" 50 | 51 | #if MICROPY_ENABLE_GC 52 | #include "py/gc.h" 53 | 54 | // We redirect standard alloc functions to GC heap - just for the rest of 55 | // this module. In the rest of MicroPython source, system malloc can be 56 | // freely accessed - for interfacing with system and 3rd-party libs for 57 | // example. On the other hand, some (e.g. bare-metal) ports may use GC 58 | // heap as system heap, so, to avoid warnings, we do undef's first. 59 | #undef malloc 60 | #undef free 61 | #undef realloc 62 | #define malloc(b) gc_alloc((b), false) 63 | #define malloc_with_finaliser(b) gc_alloc((b), true) 64 | #define free gc_free 65 | #define realloc(ptr, n) gc_realloc(ptr, n, true) 66 | #define realloc_ext(ptr, n, mv) gc_realloc(ptr, n, mv) 67 | #endif 68 | 69 | #endif /* SECP256K1_CONFIG_H */ 70 | -------------------------------------------------------------------------------- /mpy/libsecp256k1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "include/secp256k1.h" 5 | #include "include/secp256k1_preallocated.h" 6 | #include "include/secp256k1_extrakeys.h" 7 | #include "include/secp256k1_schnorrsig.h" 8 | #include "include/secp256k1_recovery.h" 9 | #include "py/obj.h" 10 | #include "py/runtime.h" 11 | #include "py/builtin.h" 12 | #include "py/gc.h" 13 | 14 | #define malloc(b) gc_alloc((b), false) 15 | #define free gc_free 16 | 17 | // newer versions of micropython require usage of MP_ERROR_TEXT 18 | // but older don't know about it 19 | #ifndef MP_ERROR_TEXT 20 | #define MP_ERROR_TEXT(x) (x) 21 | #endif 22 | 23 | // global context 24 | #define PREALLOCATED_CTX_SIZE 880 // 440 for 32-bit. FIXME: autodetect 25 | 26 | STATIC unsigned char preallocated_ctx[PREALLOCATED_CTX_SIZE]; 27 | STATIC secp256k1_context * ctx = NULL; 28 | 29 | void maybe_init_ctx(){ 30 | if(ctx != NULL){ 31 | return; 32 | } 33 | // ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); 34 | ctx = secp256k1_context_preallocated_create((void *)preallocated_ctx, SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); 35 | } 36 | 37 | // randomize context using 32-byte seed 38 | STATIC mp_obj_t usecp256k1_context_randomize(const mp_obj_t seed){ 39 | maybe_init_ctx(); 40 | mp_buffer_info_t seedbuf; 41 | mp_get_buffer_raise(seed, &seedbuf, MP_BUFFER_READ); 42 | if(seedbuf.len != 32){ 43 | mp_raise_ValueError(MP_ERROR_TEXT("Seed should be 32 bytes long")); 44 | return mp_const_none; 45 | } 46 | int res = secp256k1_context_randomize(ctx, seedbuf.buf); 47 | if(!res){ 48 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to randomize context")); 49 | return mp_const_none; 50 | } 51 | return mp_const_none; 52 | } 53 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_context_randomize_obj, usecp256k1_context_randomize); 54 | 55 | // create public key from private key 56 | STATIC mp_obj_t usecp256k1_ec_pubkey_create(const mp_obj_t arg){ 57 | maybe_init_ctx(); 58 | mp_buffer_info_t secretbuf; 59 | mp_get_buffer_raise(arg, &secretbuf, MP_BUFFER_READ); 60 | if(secretbuf.len != 32){ 61 | mp_raise_ValueError(MP_ERROR_TEXT("Private key should be 32 bytes long")); 62 | return mp_const_none; 63 | } 64 | secp256k1_pubkey pubkey; 65 | int res = secp256k1_ec_pubkey_create(ctx, &pubkey, secretbuf.buf); 66 | if(!res){ 67 | mp_raise_ValueError(MP_ERROR_TEXT("Invalid private key")); 68 | return mp_const_none; 69 | } 70 | vstr_t vstr; 71 | vstr_init_len(&vstr, 64); 72 | memcpy((byte*)vstr.buf, pubkey.data, 64); 73 | 74 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 75 | } 76 | 77 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ec_pubkey_create_obj, usecp256k1_ec_pubkey_create); 78 | 79 | // parse sec-encoded public key 80 | STATIC mp_obj_t usecp256k1_ec_pubkey_parse(const mp_obj_t arg){ 81 | maybe_init_ctx(); 82 | mp_buffer_info_t secbuf; 83 | mp_get_buffer_raise(arg, &secbuf, MP_BUFFER_READ); 84 | if(secbuf.len != 33 && secbuf.len != 65){ 85 | mp_raise_ValueError(MP_ERROR_TEXT("Serialized pubkey should be 33 or 65 bytes long")); 86 | return mp_const_none; 87 | } 88 | byte * buf = (byte*)secbuf.buf; 89 | switch(secbuf.len){ 90 | case 33: 91 | if(buf[0] != 0x02 && buf[0] != 0x03){ 92 | mp_raise_ValueError(MP_ERROR_TEXT("Compressed pubkey should start with 0x02 or 0x03")); 93 | return mp_const_none; 94 | } 95 | break; 96 | case 65: 97 | if(buf[0] != 0x04){ 98 | mp_raise_ValueError(MP_ERROR_TEXT("Uncompressed pubkey should start with 0x04")); 99 | return mp_const_none; 100 | } 101 | break; 102 | } 103 | secp256k1_pubkey pubkey; 104 | int res = secp256k1_ec_pubkey_parse(ctx, &pubkey, secbuf.buf, secbuf.len); 105 | if(!res){ 106 | mp_raise_ValueError(MP_ERROR_TEXT("Failed parsing public key")); 107 | return mp_const_none; 108 | } 109 | vstr_t vstr; 110 | vstr_init_len(&vstr, 64); 111 | memcpy((byte*)vstr.buf, pubkey.data, 64); 112 | 113 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 114 | } 115 | 116 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ec_pubkey_parse_obj, usecp256k1_ec_pubkey_parse); 117 | 118 | // serialize public key 119 | STATIC mp_obj_t usecp256k1_ec_pubkey_serialize(mp_uint_t n_args, const mp_obj_t *args){ 120 | maybe_init_ctx(); 121 | mp_buffer_info_t pubbuf; 122 | mp_get_buffer_raise(args[0], &pubbuf, MP_BUFFER_READ); 123 | if(pubbuf.len != 64){ 124 | mp_raise_ValueError(MP_ERROR_TEXT("Pubkey should be 64 bytes long")); 125 | return mp_const_none; 126 | } 127 | secp256k1_pubkey pubkey; 128 | memcpy(pubkey.data, pubbuf.buf, 64); 129 | mp_int_t flag = SECP256K1_EC_COMPRESSED; 130 | if(n_args > 1){ 131 | flag = mp_obj_get_int(args[1]); 132 | } 133 | byte out[65]; 134 | size_t len = 65; 135 | int res = secp256k1_ec_pubkey_serialize(ctx, out, &len, &pubkey, flag); 136 | if(!res){ 137 | mp_raise_ValueError(MP_ERROR_TEXT("Failed serializing public key")); 138 | return mp_const_none; 139 | } 140 | vstr_t vstr; 141 | vstr_init_len(&vstr, len); 142 | memcpy((byte*)vstr.buf, out, len); 143 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 144 | } 145 | 146 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(usecp256k1_ec_pubkey_serialize_obj, 1, usecp256k1_ec_pubkey_serialize); 147 | 148 | // parse compact ecdsa signature 149 | STATIC mp_obj_t usecp256k1_ecdsa_signature_parse_compact(const mp_obj_t arg){ 150 | maybe_init_ctx(); 151 | mp_buffer_info_t buf; 152 | mp_get_buffer_raise(arg, &buf, MP_BUFFER_READ); 153 | if(buf.len != 64){ 154 | mp_raise_ValueError(MP_ERROR_TEXT("Compact signature should be 64 bytes long")); 155 | return mp_const_none; 156 | } 157 | secp256k1_ecdsa_signature sig; 158 | int res = secp256k1_ecdsa_signature_parse_compact(ctx, &sig, buf.buf); 159 | if(!res){ 160 | mp_raise_ValueError(MP_ERROR_TEXT("Failed parsing compact signature")); 161 | return mp_const_none; 162 | } 163 | vstr_t vstr; 164 | vstr_init_len(&vstr, 64); 165 | memcpy((byte*)vstr.buf, sig.data, 64); 166 | 167 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 168 | } 169 | 170 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ecdsa_signature_parse_compact_obj, usecp256k1_ecdsa_signature_parse_compact); 171 | 172 | // parse der ecdsa signature 173 | STATIC mp_obj_t usecp256k1_ecdsa_signature_parse_der(const mp_obj_t arg){ 174 | maybe_init_ctx(); 175 | mp_buffer_info_t buf; 176 | mp_get_buffer_raise(arg, &buf, MP_BUFFER_READ); 177 | secp256k1_ecdsa_signature sig; 178 | int res = secp256k1_ecdsa_signature_parse_der(ctx, &sig, buf.buf, buf.len); 179 | if(!res){ 180 | mp_raise_ValueError(MP_ERROR_TEXT("Failed parsing der signature")); 181 | return mp_const_none; 182 | } 183 | vstr_t vstr; 184 | vstr_init_len(&vstr, 64); 185 | memcpy((byte*)vstr.buf, sig.data, 64); 186 | 187 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 188 | } 189 | 190 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ecdsa_signature_parse_der_obj, usecp256k1_ecdsa_signature_parse_der); 191 | 192 | // serialize der ecdsa signature 193 | STATIC mp_obj_t usecp256k1_ecdsa_signature_serialize_der(const mp_obj_t arg){ 194 | maybe_init_ctx(); 195 | mp_buffer_info_t buf; 196 | mp_get_buffer_raise(arg, &buf, MP_BUFFER_READ); 197 | if(buf.len != 64){ 198 | mp_raise_ValueError(MP_ERROR_TEXT("Signature should be 64 bytes long")); 199 | return mp_const_none; 200 | } 201 | secp256k1_ecdsa_signature sig; 202 | memcpy(sig.data, buf.buf, 64); 203 | byte out[78]; 204 | size_t len = 78; 205 | int res = secp256k1_ecdsa_signature_serialize_der(ctx, out, &len, &sig); 206 | if(!res){ 207 | mp_raise_ValueError(MP_ERROR_TEXT("Failed serializing der signature")); 208 | return mp_const_none; 209 | } 210 | vstr_t vstr; 211 | vstr_init_len(&vstr, len); 212 | memcpy((byte*)vstr.buf, out, len); 213 | 214 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 215 | } 216 | 217 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ecdsa_signature_serialize_der_obj, usecp256k1_ecdsa_signature_serialize_der); 218 | 219 | // serialize compact ecdsa signature 220 | STATIC mp_obj_t usecp256k1_ecdsa_signature_serialize_compact(const mp_obj_t arg){ 221 | maybe_init_ctx(); 222 | mp_buffer_info_t buf; 223 | mp_get_buffer_raise(arg, &buf, MP_BUFFER_READ); 224 | if(buf.len != 64){ 225 | mp_raise_ValueError(MP_ERROR_TEXT("Signature should be 64 bytes long")); 226 | return mp_const_none; 227 | } 228 | secp256k1_ecdsa_signature sig; 229 | memcpy(sig.data, buf.buf, 64); 230 | vstr_t vstr; 231 | vstr_init_len(&vstr, 64); 232 | secp256k1_ecdsa_signature_serialize_compact(ctx, (byte*)vstr.buf, &sig); 233 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 234 | } 235 | 236 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ecdsa_signature_serialize_compact_obj, usecp256k1_ecdsa_signature_serialize_compact); 237 | 238 | // verify ecdsa signature 239 | STATIC mp_obj_t usecp256k1_ecdsa_verify(const mp_obj_t sigarg, const mp_obj_t msgarg, const mp_obj_t pubkeyarg){ 240 | maybe_init_ctx(); 241 | mp_buffer_info_t buf; 242 | mp_get_buffer_raise(sigarg, &buf, MP_BUFFER_READ); 243 | if(buf.len != 64){ 244 | mp_raise_ValueError(MP_ERROR_TEXT("Signature should be 64 bytes long")); 245 | return mp_const_none; 246 | } 247 | secp256k1_ecdsa_signature sig; 248 | memcpy(sig.data, buf.buf, 64); 249 | 250 | mp_get_buffer_raise(msgarg, &buf, MP_BUFFER_READ); 251 | if(buf.len != 32){ 252 | mp_raise_ValueError(MP_ERROR_TEXT("Message should be 32 bytes long")); 253 | return mp_const_none; 254 | } 255 | byte msg[32]; 256 | memcpy(msg, buf.buf, 32); 257 | 258 | mp_get_buffer_raise(pubkeyarg, &buf, MP_BUFFER_READ); 259 | if(buf.len != 64){ 260 | mp_raise_ValueError(MP_ERROR_TEXT("Public key should be 64 bytes long")); 261 | return mp_const_none; 262 | } 263 | secp256k1_pubkey pub; 264 | memcpy(pub.data, buf.buf, 64); 265 | 266 | int res = secp256k1_ecdsa_verify(ctx, &sig, msg, &pub); 267 | if(res){ 268 | return mp_const_true; 269 | } 270 | return mp_const_false; 271 | } 272 | 273 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(usecp256k1_ecdsa_verify_obj, usecp256k1_ecdsa_verify); 274 | 275 | // normalize ecdsa signature 276 | STATIC mp_obj_t usecp256k1_ecdsa_signature_normalize(const mp_obj_t arg){ 277 | maybe_init_ctx(); 278 | mp_buffer_info_t buf; 279 | mp_get_buffer_raise(arg, &buf, MP_BUFFER_READ); 280 | if(buf.len != 64){ 281 | mp_raise_ValueError(MP_ERROR_TEXT("Signature should be 64 bytes long")); 282 | return mp_const_none; 283 | } 284 | secp256k1_ecdsa_signature sig; 285 | secp256k1_ecdsa_signature sig2; 286 | memcpy(sig.data, buf.buf, 64); 287 | vstr_t vstr; 288 | vstr_init_len(&vstr, 64); 289 | secp256k1_ecdsa_signature_normalize(ctx, &sig2, &sig); 290 | memcpy(vstr.buf, sig2.data, 64); 291 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 292 | } 293 | 294 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ecdsa_signature_normalize_obj, usecp256k1_ecdsa_signature_normalize); 295 | 296 | // same as secp256k1_nonce_function_rfc6979 297 | STATIC mp_obj_t usecp256k1_nonce_function_default(mp_uint_t n_args, const mp_obj_t *args){ 298 | mp_buffer_info_t msgbuf; 299 | mp_get_buffer_raise(args[0], &msgbuf, MP_BUFFER_READ); 300 | if(msgbuf.len != 32){ 301 | mp_raise_ValueError(MP_ERROR_TEXT("Message should be 32 bytes long")); 302 | return mp_const_none; 303 | } 304 | mp_buffer_info_t secbuf; 305 | mp_get_buffer_raise(args[1], &secbuf, MP_BUFFER_READ); 306 | if(secbuf.len != 32){ 307 | mp_raise_ValueError(MP_ERROR_TEXT("Secret should be 32 bytes long")); 308 | return mp_const_none; 309 | } 310 | unsigned char *algo16 = NULL; 311 | void *data = NULL; 312 | int attempt = 0; 313 | // result 314 | vstr_t nonce; 315 | vstr_init_len(&nonce, 32); 316 | if(n_args > 2){ 317 | if(args[2] != mp_const_none){ 318 | mp_buffer_info_t algbuf; 319 | mp_get_buffer_raise(args[0], &algbuf, MP_BUFFER_READ); 320 | algo16 = algbuf.buf; 321 | } 322 | if(n_args > 3 && args[3]!=mp_const_none){ 323 | mp_buffer_info_t databuf; 324 | if (!mp_get_buffer(args[3], &databuf, MP_BUFFER_READ)) { 325 | data = (void*) args[3]; 326 | }else{ 327 | data = (void*) databuf.buf; 328 | } 329 | } 330 | if(n_args > 4){ 331 | attempt = mp_obj_get_int(args[4]); 332 | } 333 | } 334 | int res = secp256k1_nonce_function_default((unsigned char*)nonce.buf, msgbuf.buf, secbuf.buf, algo16, data, attempt); 335 | if(!res){ 336 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to calculate nonce")); 337 | return mp_const_none; 338 | } 339 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &nonce); 340 | } 341 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(usecp256k1_nonce_function_default_obj, 2, usecp256k1_nonce_function_default); 342 | 343 | STATIC mp_obj_t mp_nonce_callback = NULL; 344 | STATIC mp_obj_t mp_nonce_data = NULL; 345 | 346 | STATIC int usecp256k1_nonce_function( 347 | unsigned char *nonce32, 348 | const unsigned char *msg32, 349 | const unsigned char *key32, 350 | const unsigned char *algo16, 351 | void *data, 352 | unsigned int attempt 353 | ){ 354 | 355 | return secp256k1_nonce_function_default(nonce32, msg32, key32, algo16, data, attempt); 356 | // TODO: make nonce function compatible with ctypes 357 | // if(!mp_obj_is_callable(mp_nonce_callback)){ 358 | // mp_raise_ValueError(MP_ERROR_TEXT("Nonce callback should be callable...")); 359 | // return mp_const_none; 360 | // } 361 | 362 | // if(attempt > 100){ 363 | // mp_raise_ValueError(MP_ERROR_TEXT("Too many attempts... Invalid function?")); 364 | // // not sure it will ever get here, but just in case 365 | // return secp256k1_nonce_function_default(nonce32, msg32, key32, algo16, data, attempt); 366 | // } 367 | // mp_obj_t mp_args[5]; 368 | // mp_args[0] = mp_obj_new_bytes(msg32, 32); 369 | // mp_args[1] = mp_obj_new_bytes(key32, 32); 370 | // if(algo16!=NULL){ 371 | // mp_args[2] = mp_obj_new_bytes(key32, 16); 372 | // }else{ 373 | // mp_args[2] = mp_const_none; 374 | // } 375 | // if(mp_nonce_data!=NULL){ 376 | // mp_args[3] = mp_nonce_data; 377 | // }else{ 378 | // mp_args[3] = mp_const_none; 379 | // } 380 | // mp_args[4] = mp_obj_new_int_from_uint(attempt); 381 | 382 | // mp_obj_t mp_res = mp_call_function_n_kw(mp_nonce_callback , 5, 0, mp_args); 383 | // if(mp_res == mp_const_none){ 384 | // return 0; 385 | // } 386 | // mp_buffer_info_t buffer_info; 387 | // if (!mp_get_buffer(mp_res, &buffer_info, MP_BUFFER_READ)) { 388 | // return 0; 389 | // } 390 | // if(buffer_info.len < 32){ 391 | // mp_raise_ValueError(MP_ERROR_TEXT("Returned nonce is less than 32 bytes")); 392 | // return 0; 393 | // } 394 | // memcpy(nonce32, (byte*)buffer_info.buf, 32); 395 | // return 1; 396 | } 397 | 398 | // msg, secret, [callback, data] 399 | STATIC mp_obj_t usecp256k1_ecdsa_sign(mp_uint_t n_args, const mp_obj_t *args){ 400 | maybe_init_ctx(); 401 | mp_nonce_data = NULL; 402 | if(n_args < 2){ 403 | mp_raise_ValueError(MP_ERROR_TEXT("Function requires at least two arguments: message and private key")); 404 | return mp_const_none; 405 | } 406 | mp_buffer_info_t msgbuf; 407 | mp_get_buffer_raise(args[0], &msgbuf, MP_BUFFER_READ); 408 | if(msgbuf.len != 32){ 409 | mp_raise_ValueError(MP_ERROR_TEXT("Message should be 32 bytes long")); 410 | return mp_const_none; 411 | } 412 | 413 | mp_buffer_info_t secbuf; 414 | mp_get_buffer_raise(args[1], &secbuf, MP_BUFFER_READ); 415 | if(secbuf.len != 32){ 416 | mp_raise_ValueError(MP_ERROR_TEXT("Secret key should be 32 bytes long")); 417 | return mp_const_none; 418 | } 419 | secp256k1_ecdsa_signature sig; 420 | 421 | mp_buffer_info_t databuf; 422 | void * data = NULL; 423 | 424 | int res=0; 425 | if(n_args == 2){ 426 | res = secp256k1_ecdsa_sign(ctx, &sig, msgbuf.buf, secbuf.buf, NULL, NULL); 427 | }else if(n_args >= 3){ 428 | mp_nonce_callback = args[2]; 429 | if(n_args > 3){ 430 | mp_get_buffer_raise(args[3], &databuf, MP_BUFFER_READ); 431 | if(databuf.len != 32){ 432 | mp_raise_ValueError(MP_ERROR_TEXT("Data should be 32 bytes long")); 433 | return mp_const_none; 434 | } 435 | data = databuf.buf; 436 | } 437 | res = secp256k1_ecdsa_sign(ctx, &sig, msgbuf.buf, secbuf.buf, usecp256k1_nonce_function, data); 438 | } 439 | if(!res){ 440 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to sign")); 441 | return mp_const_none; 442 | } 443 | 444 | vstr_t vstr; 445 | vstr_init_len(&vstr, 64); 446 | memcpy((byte*)vstr.buf, sig.data, 64); 447 | 448 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 449 | } 450 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(usecp256k1_ecdsa_sign_obj, 2, usecp256k1_ecdsa_sign); 451 | 452 | // verify secret key 453 | STATIC mp_obj_t usecp256k1_ec_seckey_verify(const mp_obj_t arg){ 454 | maybe_init_ctx(); 455 | mp_buffer_info_t buf; 456 | mp_get_buffer_raise(arg, &buf, MP_BUFFER_READ); 457 | if(buf.len != 32){ 458 | mp_raise_ValueError(MP_ERROR_TEXT("Private key should be 32 bytes long")); 459 | return mp_const_none; 460 | } 461 | 462 | int res = secp256k1_ec_seckey_verify(ctx, buf.buf); 463 | if(res){ 464 | return mp_const_true; 465 | } 466 | return mp_const_false; 467 | } 468 | 469 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ec_seckey_verify_obj, usecp256k1_ec_seckey_verify); 470 | 471 | // return N - secret key 472 | STATIC mp_obj_t usecp256k1_ec_privkey_negate(mp_obj_t arg){ 473 | maybe_init_ctx(); 474 | mp_buffer_info_t buf; 475 | mp_get_buffer_raise(arg, &buf, MP_BUFFER_READ); 476 | if(buf.len != 32){ 477 | mp_raise_ValueError(MP_ERROR_TEXT("Private key should be 32 bytes long")); 478 | return mp_const_none; 479 | } 480 | 481 | vstr_t vstr; 482 | vstr_init_len(&vstr, 32); 483 | memcpy((byte*)vstr.buf, buf.buf, 32); 484 | 485 | int res = secp256k1_ec_privkey_negate(ctx, (unsigned char *)vstr.buf); 486 | if(!res){ // never happens according to the API 487 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to negate the private key")); 488 | return mp_const_none; 489 | } 490 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 491 | } 492 | 493 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ec_privkey_negate_obj, usecp256k1_ec_privkey_negate); 494 | 495 | // return neg of pubkey 496 | STATIC mp_obj_t usecp256k1_ec_pubkey_negate(mp_obj_t arg){ 497 | maybe_init_ctx(); 498 | mp_buffer_info_t buf; 499 | mp_get_buffer_raise(arg, &buf, MP_BUFFER_READ); 500 | if(buf.len != 64){ 501 | mp_raise_ValueError(MP_ERROR_TEXT("Publick key should be 64 bytes long")); 502 | return mp_const_none; 503 | } 504 | 505 | vstr_t vstr; 506 | vstr_init_len(&vstr, 64); 507 | memcpy((byte*)vstr.buf, buf.buf, 64); 508 | 509 | int res = secp256k1_ec_pubkey_negate(ctx, (secp256k1_pubkey *)vstr.buf); 510 | if(!res){ // never happens according to the API 511 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to negate the public key")); 512 | return mp_const_none; 513 | } 514 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 515 | } 516 | 517 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(usecp256k1_ec_pubkey_negate_obj, usecp256k1_ec_pubkey_negate); 518 | 519 | // tweak private key in place 520 | STATIC mp_obj_t usecp256k1_ec_privkey_tweak_add(mp_obj_t privarg, const mp_obj_t tweakarg){ 521 | maybe_init_ctx(); 522 | mp_buffer_info_t privbuf; 523 | mp_get_buffer_raise(privarg, &privbuf, MP_BUFFER_READ); 524 | if(privbuf.len != 32){ 525 | mp_raise_ValueError(MP_ERROR_TEXT("Private key should be 32 bytes long")); 526 | return mp_const_none; 527 | } 528 | 529 | mp_buffer_info_t tweakbuf; 530 | mp_get_buffer_raise(tweakarg, &tweakbuf, MP_BUFFER_READ); 531 | if(tweakbuf.len != 32){ 532 | mp_raise_ValueError(MP_ERROR_TEXT("Tweak should be 32 bytes long")); 533 | return mp_const_none; 534 | } 535 | 536 | int res = secp256k1_ec_privkey_tweak_add(ctx, privbuf.buf, tweakbuf.buf); 537 | if(!res){ // never happens according to the API 538 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to tweak the private key")); 539 | return mp_const_none; 540 | } 541 | return mp_const_none; 542 | } 543 | 544 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(usecp256k1_ec_privkey_tweak_add_obj, usecp256k1_ec_privkey_tweak_add); 545 | 546 | // add private key 547 | STATIC mp_obj_t usecp256k1_ec_privkey_add(mp_obj_t privarg, const mp_obj_t tweakarg){ 548 | maybe_init_ctx(); 549 | mp_buffer_info_t privbuf; 550 | mp_get_buffer_raise(privarg, &privbuf, MP_BUFFER_READ); 551 | if(privbuf.len != 32){ 552 | mp_raise_ValueError("Private key should be 32 bytes long"); 553 | return mp_const_none; 554 | } 555 | 556 | mp_buffer_info_t tweakbuf; 557 | mp_get_buffer_raise(tweakarg, &tweakbuf, MP_BUFFER_READ); 558 | if(tweakbuf.len != 32){ 559 | mp_raise_ValueError("Tweak should be 32 bytes long"); 560 | return mp_const_none; 561 | } 562 | 563 | vstr_t priv2; 564 | vstr_init_len(&priv2, 32); 565 | memcpy((byte*)priv2.buf, privbuf.buf, 32); 566 | 567 | int res = secp256k1_ec_privkey_tweak_add(ctx, priv2.buf, tweakbuf.buf); 568 | if(!res){ // never happens according to the API 569 | mp_raise_ValueError("Failed to tweak the private key"); 570 | return mp_const_none; 571 | } 572 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &priv2); 573 | } 574 | 575 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(usecp256k1_ec_privkey_add_obj, usecp256k1_ec_privkey_add); 576 | 577 | // tweak public key in place (add tweak * Generator) 578 | STATIC mp_obj_t usecp256k1_ec_pubkey_tweak_add(mp_obj_t pubarg, const mp_obj_t tweakarg){ 579 | maybe_init_ctx(); 580 | mp_buffer_info_t pubbuf; 581 | mp_get_buffer_raise(pubarg, &pubbuf, MP_BUFFER_READ); 582 | if(pubbuf.len != 64){ 583 | mp_raise_ValueError(MP_ERROR_TEXT("Public key should be 64 bytes long")); 584 | return mp_const_none; 585 | } 586 | secp256k1_pubkey pub; 587 | memcpy(pub.data, pubbuf.buf, 64); 588 | 589 | mp_buffer_info_t tweakbuf; 590 | mp_get_buffer_raise(tweakarg, &tweakbuf, MP_BUFFER_READ); 591 | if(tweakbuf.len != 32){ 592 | mp_raise_ValueError(MP_ERROR_TEXT("Tweak should be 32 bytes long")); 593 | return mp_const_none; 594 | } 595 | 596 | int res = secp256k1_ec_pubkey_tweak_add(ctx, &pub, tweakbuf.buf); 597 | if(!res){ // never happens according to the API 598 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to tweak the public key")); 599 | return mp_const_none; 600 | } 601 | memcpy(pubbuf.buf, pub.data, 64); 602 | return mp_const_none; 603 | } 604 | 605 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(usecp256k1_ec_pubkey_tweak_add_obj, usecp256k1_ec_pubkey_tweak_add); 606 | 607 | // add tweak * Generator 608 | STATIC mp_obj_t usecp256k1_ec_pubkey_add(mp_obj_t pubarg, const mp_obj_t tweakarg){ 609 | maybe_init_ctx(); 610 | mp_buffer_info_t pubbuf; 611 | mp_get_buffer_raise(pubarg, &pubbuf, MP_BUFFER_READ); 612 | if(pubbuf.len != 64){ 613 | mp_raise_ValueError("Public key should be 64 bytes long"); 614 | return mp_const_none; 615 | } 616 | secp256k1_pubkey pub; 617 | memcpy(pub.data, pubbuf.buf, 64); 618 | 619 | mp_buffer_info_t tweakbuf; 620 | mp_get_buffer_raise(tweakarg, &tweakbuf, MP_BUFFER_READ); 621 | if(tweakbuf.len != 32){ 622 | mp_raise_ValueError("Tweak should be 32 bytes long"); 623 | return mp_const_none; 624 | } 625 | 626 | int res = secp256k1_ec_pubkey_tweak_add(ctx, &pub, tweakbuf.buf); 627 | if(!res){ // never happens according to the API 628 | mp_raise_ValueError("Failed to tweak the public key"); 629 | return mp_const_none; 630 | } 631 | 632 | vstr_t pubbuf2; 633 | vstr_init_len(&pubbuf2, 64); 634 | memcpy((byte*)pubbuf2.buf, pub.data, 64); 635 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &pubbuf2); 636 | } 637 | 638 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(usecp256k1_ec_pubkey_add_obj, usecp256k1_ec_pubkey_add); 639 | 640 | // tweak private key in place (multiply by tweak) 641 | STATIC mp_obj_t usecp256k1_ec_privkey_tweak_mul(mp_obj_t privarg, const mp_obj_t tweakarg){ 642 | maybe_init_ctx(); 643 | mp_buffer_info_t privbuf; 644 | mp_get_buffer_raise(privarg, &privbuf, MP_BUFFER_READ); 645 | if(privbuf.len != 32){ 646 | mp_raise_ValueError(MP_ERROR_TEXT("Private key should be 32 bytes long")); 647 | return mp_const_none; 648 | } 649 | 650 | mp_buffer_info_t tweakbuf; 651 | mp_get_buffer_raise(tweakarg, &tweakbuf, MP_BUFFER_READ); 652 | if(tweakbuf.len != 32){ 653 | mp_raise_ValueError(MP_ERROR_TEXT("Tweak should be 32 bytes long")); 654 | return mp_const_none; 655 | } 656 | 657 | int res = secp256k1_ec_privkey_tweak_mul(ctx, privbuf.buf, tweakbuf.buf); 658 | if(!res){ // never happens according to the API 659 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to tweak the public key")); 660 | return mp_const_none; 661 | } 662 | return mp_const_none; 663 | } 664 | 665 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(usecp256k1_ec_privkey_tweak_mul_obj, usecp256k1_ec_privkey_tweak_mul); 666 | 667 | // tweak public key in place (multiply by tweak) 668 | STATIC mp_obj_t usecp256k1_ec_pubkey_tweak_mul(mp_obj_t pubarg, const mp_obj_t tweakarg){ 669 | maybe_init_ctx(); 670 | mp_buffer_info_t pubbuf; 671 | mp_get_buffer_raise(pubarg, &pubbuf, MP_BUFFER_READ); 672 | if(pubbuf.len != 64){ 673 | mp_raise_ValueError(MP_ERROR_TEXT("Public key should be 64 bytes long")); 674 | return mp_const_none; 675 | } 676 | secp256k1_pubkey pub; 677 | memcpy(pub.data, pubbuf.buf, 64); 678 | 679 | mp_buffer_info_t tweakbuf; 680 | mp_get_buffer_raise(tweakarg, &tweakbuf, MP_BUFFER_READ); 681 | if(tweakbuf.len != 32){ 682 | mp_raise_ValueError(MP_ERROR_TEXT("Tweak should be 32 bytes long")); 683 | return mp_const_none; 684 | } 685 | 686 | int res = secp256k1_ec_pubkey_tweak_mul(ctx, &pub, tweakbuf.buf); 687 | if(!res){ // never happens according to the API 688 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to tweak the public key")); 689 | return mp_const_none; 690 | } 691 | memcpy(pubbuf.buf, pub.data, 64); 692 | return mp_const_none; 693 | } 694 | 695 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(usecp256k1_ec_pubkey_tweak_mul_obj, usecp256k1_ec_pubkey_tweak_mul); 696 | 697 | // adds public keys 698 | STATIC mp_obj_t usecp256k1_ec_pubkey_combine(mp_uint_t n_args, const mp_obj_t *args){ 699 | maybe_init_ctx(); 700 | secp256k1_pubkey pubkey; 701 | secp256k1_pubkey ** pubkeys; 702 | pubkeys = (secp256k1_pubkey **)malloc(sizeof(secp256k1_pubkey*)*n_args); 703 | mp_buffer_info_t pubbuf; 704 | for(unsigned int i=0; idata, pubbuf.buf, 64); 716 | } 717 | int res = secp256k1_ec_pubkey_combine(ctx, &pubkey, (const secp256k1_pubkey *const *)pubkeys, n_args); 718 | if(!res){ 719 | mp_raise_ValueError(MP_ERROR_TEXT("Failed combining public keys")); 720 | return mp_const_none; 721 | } 722 | vstr_t vstr; 723 | vstr_init_len(&vstr, 64); 724 | memcpy((byte*)vstr.buf, pubkey.data, 64); 725 | for(unsigned int i=0; i= 3){ 864 | mp_nonce_callback = args[2]; 865 | if(n_args > 3){ 866 | mp_get_buffer_raise(args[3], &databuf, MP_BUFFER_READ); 867 | if(databuf.len != 32){ 868 | mp_raise_ValueError(MP_ERROR_TEXT("Data should be 32 bytes long")); 869 | return mp_const_none; 870 | } 871 | data = databuf.buf; 872 | } 873 | res = secp256k1_schnorrsig_sign(ctx, sig, msgbuf.buf, (secp256k1_keypair *)keypair, data); 874 | } 875 | if(!res){ 876 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to sign")); 877 | return mp_const_none; 878 | } 879 | 880 | vstr_t vstr; 881 | vstr_init_len(&vstr, 64); 882 | memcpy((byte*)vstr.buf, sig, 64); 883 | 884 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 885 | } 886 | 887 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(usecp256k1_schnorrsig_sign_obj, 2, usecp256k1_schnorrsig_sign); 888 | 889 | /**************************** recoverable ***************************/ 890 | 891 | // msg, secret, [callback, data] 892 | STATIC mp_obj_t usecp256k1_ecdsa_sign_recoverable(mp_uint_t n_args, const mp_obj_t *args){ 893 | maybe_init_ctx(); 894 | mp_nonce_data = NULL; 895 | if(n_args < 2){ 896 | mp_raise_ValueError(MP_ERROR_TEXT("Function requires at least two arguments: message and private key")); 897 | return mp_const_none; 898 | } 899 | mp_buffer_info_t msgbuf; 900 | mp_get_buffer_raise(args[0], &msgbuf, MP_BUFFER_READ); 901 | if(msgbuf.len != 32){ 902 | mp_raise_ValueError(MP_ERROR_TEXT("Message should be 32 bytes long")); 903 | return mp_const_none; 904 | } 905 | 906 | mp_buffer_info_t secbuf; 907 | mp_get_buffer_raise(args[1], &secbuf, MP_BUFFER_READ); 908 | if(secbuf.len != 32){ 909 | mp_raise_ValueError(MP_ERROR_TEXT("Secret key should be 32 bytes long")); 910 | return mp_const_none; 911 | } 912 | secp256k1_ecdsa_recoverable_signature sig; 913 | int res=0; 914 | 915 | mp_buffer_info_t databuf; 916 | void * data = NULL; 917 | 918 | if(n_args == 2){ 919 | res = secp256k1_ecdsa_sign_recoverable(ctx, &sig, msgbuf.buf, secbuf.buf, NULL, NULL); 920 | }else if(n_args >= 3){ 921 | mp_nonce_callback = args[2]; 922 | if(n_args > 3){ 923 | mp_get_buffer_raise(args[3], &databuf, MP_BUFFER_READ); 924 | if(databuf.len != 32){ 925 | mp_raise_ValueError(MP_ERROR_TEXT("Data should be 32 bytes long")); 926 | return mp_const_none; 927 | } 928 | data = databuf.buf; 929 | } 930 | res = secp256k1_ecdsa_sign_recoverable(ctx, &sig, msgbuf.buf, secbuf.buf, usecp256k1_nonce_function, data); 931 | } 932 | if(!res){ 933 | mp_raise_ValueError(MP_ERROR_TEXT("Failed to sign")); 934 | return mp_const_none; 935 | } 936 | 937 | vstr_t vstr; 938 | vstr_init_len(&vstr, 65); 939 | memcpy((byte*)vstr.buf, sig.data, 65); 940 | 941 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 942 | } 943 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(usecp256k1_ecdsa_sign_recoverable_obj, 2, usecp256k1_ecdsa_sign_recoverable); 944 | 945 | /****************************** MODULE ******************************/ 946 | 947 | STATIC const mp_rom_map_elem_t secp256k1_module_globals_table[] = { 948 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_secp256k1) }, 949 | { MP_ROM_QSTR(MP_QSTR_context_randomize), MP_ROM_PTR(&usecp256k1_context_randomize_obj) }, 950 | { MP_ROM_QSTR(MP_QSTR_ec_pubkey_create), MP_ROM_PTR(&usecp256k1_ec_pubkey_create_obj) }, 951 | { MP_ROM_QSTR(MP_QSTR_ec_pubkey_parse), MP_ROM_PTR(&usecp256k1_ec_pubkey_parse_obj) }, 952 | { MP_ROM_QSTR(MP_QSTR_ec_pubkey_serialize), MP_ROM_PTR(&usecp256k1_ec_pubkey_serialize_obj) }, 953 | { MP_ROM_QSTR(MP_QSTR_ecdsa_signature_parse_compact), MP_ROM_PTR(&usecp256k1_ecdsa_signature_parse_compact_obj) }, 954 | { MP_ROM_QSTR(MP_QSTR_ecdsa_signature_parse_der), MP_ROM_PTR(&usecp256k1_ecdsa_signature_parse_der_obj) }, 955 | { MP_ROM_QSTR(MP_QSTR_ecdsa_signature_serialize_der), MP_ROM_PTR(&usecp256k1_ecdsa_signature_serialize_der_obj) }, 956 | { MP_ROM_QSTR(MP_QSTR_ecdsa_signature_serialize_compact), MP_ROM_PTR(&usecp256k1_ecdsa_signature_serialize_compact_obj) }, 957 | { MP_ROM_QSTR(MP_QSTR_ecdsa_signature_normalize), MP_ROM_PTR(&usecp256k1_ecdsa_signature_normalize_obj) }, 958 | { MP_ROM_QSTR(MP_QSTR_ecdsa_verify), MP_ROM_PTR(&usecp256k1_ecdsa_verify_obj) }, 959 | { MP_ROM_QSTR(MP_QSTR_ecdsa_sign), MP_ROM_PTR(&usecp256k1_ecdsa_sign_obj) }, 960 | // schnorrsig 961 | { MP_ROM_QSTR(MP_QSTR_xonly_pubkey_from_pubkey), MP_ROM_PTR(&usecp256k1_xonly_pubkey_from_pubkey_obj) }, 962 | { MP_ROM_QSTR(MP_QSTR_schnorrsig_verify), MP_ROM_PTR(&usecp256k1_schnorrsig_verify_obj) }, 963 | { MP_ROM_QSTR(MP_QSTR_keypair_create), MP_ROM_PTR(&usecp256k1_keypair_create_obj) }, 964 | { MP_ROM_QSTR(MP_QSTR_schnorrsig_sign), MP_ROM_PTR(&usecp256k1_schnorrsig_sign_obj) }, 965 | 966 | { MP_ROM_QSTR(MP_QSTR_ecdsa_sign_recoverable), MP_ROM_PTR(&usecp256k1_ecdsa_sign_recoverable_obj) }, 967 | 968 | { MP_ROM_QSTR(MP_QSTR_nonce_function_default), MP_ROM_PTR(&usecp256k1_nonce_function_default_obj) }, 969 | { MP_ROM_QSTR(MP_QSTR_nonce_function_rfc6979), MP_ROM_PTR(&usecp256k1_nonce_function_default_obj) }, 970 | 971 | { MP_ROM_QSTR(MP_QSTR_ec_seckey_verify), MP_ROM_PTR(&usecp256k1_ec_seckey_verify_obj) }, 972 | { MP_ROM_QSTR(MP_QSTR_ec_privkey_negate), MP_ROM_PTR(&usecp256k1_ec_privkey_negate_obj) }, 973 | { MP_ROM_QSTR(MP_QSTR_ec_pubkey_negate), MP_ROM_PTR(&usecp256k1_ec_pubkey_negate_obj) }, 974 | { MP_ROM_QSTR(MP_QSTR_ec_privkey_tweak_add), MP_ROM_PTR(&usecp256k1_ec_privkey_tweak_add_obj) }, 975 | { MP_ROM_QSTR(MP_QSTR_ec_privkey_add), MP_ROM_PTR(&usecp256k1_ec_privkey_add_obj) }, 976 | { MP_ROM_QSTR(MP_QSTR_ec_pubkey_tweak_add), MP_ROM_PTR(&usecp256k1_ec_pubkey_tweak_add_obj) }, 977 | { MP_ROM_QSTR(MP_QSTR_ec_pubkey_add), MP_ROM_PTR(&usecp256k1_ec_pubkey_add_obj) }, 978 | { MP_ROM_QSTR(MP_QSTR_ec_privkey_tweak_mul), MP_ROM_PTR(&usecp256k1_ec_privkey_tweak_mul_obj) }, 979 | { MP_ROM_QSTR(MP_QSTR_ec_pubkey_tweak_mul), MP_ROM_PTR(&usecp256k1_ec_pubkey_tweak_mul_obj) }, 980 | { MP_ROM_QSTR(MP_QSTR_ec_pubkey_combine), MP_ROM_PTR(&usecp256k1_ec_pubkey_combine_obj) }, 981 | { MP_ROM_QSTR(MP_QSTR_EC_COMPRESSED), MP_ROM_INT(SECP256K1_EC_COMPRESSED) }, 982 | { MP_ROM_QSTR(MP_QSTR_EC_UNCOMPRESSED), MP_ROM_INT(SECP256K1_EC_UNCOMPRESSED) }, 983 | }; 984 | STATIC MP_DEFINE_CONST_DICT(secp256k1_module_globals, secp256k1_module_globals_table); 985 | 986 | // Define module object. 987 | const mp_obj_module_t secp256k1_user_cmodule = { 988 | .base = { &mp_type_module }, 989 | .globals = (mp_obj_dict_t*)&secp256k1_module_globals, 990 | }; 991 | 992 | // Register the module to make it available in Python 993 | MP_REGISTER_MODULE(MP_QSTR_secp256k1, secp256k1_user_cmodule, MODULE_SECP256K1_ENABLED); 994 | -------------------------------------------------------------------------------- /secp256k1.lib: -------------------------------------------------------------------------------- 1 | https://github.com/bitcoin-core/secp256k1/#f39f99be0e6add959f534c03b93044cef066fe09 2 | -------------------------------------------------------------------------------- /src/ecmult_const_impl.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../secp256k1/src/ecmult_const_impl.h" -------------------------------------------------------------------------------- /src/include/secp256k1.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../../secp256k1/include/secp256k1.h" -------------------------------------------------------------------------------- /src/include/secp256k1_ecdh.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../../secp256k1/include/secp256k1_ecdh.h" -------------------------------------------------------------------------------- /src/include/secp256k1_preallocated.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../../secp256k1/include/secp256k1_preallocated.h" -------------------------------------------------------------------------------- /src/include/secp256k1_recovery.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../../secp256k1/include/secp256k1_recovery.h" -------------------------------------------------------------------------------- /src/libsecp256k1-config.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_CONFIG_H 2 | #define SECP256K1_CONFIG_H 3 | 4 | #undef USE_ASM_X86_64 5 | #undef USE_ECMULT_STATIC_PRECOMPUTATION 6 | #undef USE_ENDOMORPHISM 7 | #undef USE_EXTERNAL_ASM 8 | #undef USE_EXTERNAL_DEFAULT_CALLBACKS 9 | #undef USE_FIELD_10X26 10 | #undef USE_FIELD_5X52 11 | #undef USE_FIELD_INV_BUILTIN 12 | #undef USE_FIELD_INV_NUM 13 | #undef USE_NUM_GMP 14 | #undef USE_NUM_NONE 15 | #undef USE_SCALAR_4X64 16 | #undef USE_SCALAR_8X32 17 | #undef USE_SCALAR_INV_BUILTIN 18 | #undef USE_SCALAR_INV_NUM 19 | #undef ECMULT_WINDOW_SIZE 20 | 21 | #define ENABLE_MODULE_ECDH 1 22 | #define ENABLE_MODULE_RECOVERY 1 23 | 24 | #define USE_NUM_NONE 1 25 | #define USE_FIELD_INV_BUILTIN 1 26 | #define USE_SCALAR_INV_BUILTIN 1 27 | #define USE_FIELD_10X26 1 28 | #define USE_SCALAR_8X32 1 29 | 30 | #define USE_ECMULT_STATIC_PRECOMPUTATION 1 31 | #define ECMULT_GEN_PREC_BITS 4 32 | #define ECMULT_WINDOW_SIZE 4 33 | 34 | #define HAVE_STDINT_H 1 35 | #define HAVE_STDLIB_H 1 36 | #define HAVE_STRING_H 1 37 | 38 | #endif /* SECP256K1_CONFIG_H */ 39 | -------------------------------------------------------------------------------- /src/secp256k1.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../secp256k1/include/secp256k1.h" -------------------------------------------------------------------------------- /src/secp256k1_bundle.c: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "libsecp256k1-config.h" 3 | 4 | #include "../secp256k1/src/secp256k1.c" -------------------------------------------------------------------------------- /src/secp256k1_ecdh.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../secp256k1/include/secp256k1_ecdh.h" -------------------------------------------------------------------------------- /src/secp256k1_preallocated.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../secp256k1/include/secp256k1_preallocated.h" -------------------------------------------------------------------------------- /src/secp256k1_recovery.h: -------------------------------------------------------------------------------- 1 | // a hack for Arduino build system 2 | #include "../secp256k1/include/secp256k1_recovery.h" --------------------------------------------------------------------------------