├── .gitignore ├── .mbedignore ├── LICENSE ├── README.md ├── examples ├── cpp │ ├── Makefile │ ├── README.md │ └── main.cpp ├── ecdh │ └── ecdh.ino ├── hash │ └── hash.ino ├── mnemonic │ └── mnemonic.ino ├── multisig │ └── multisig.ino ├── psbt │ └── psbt.ino ├── schnorr │ └── schnorr.ino ├── tx │ └── tx.ino └── xpubs │ └── xpubs.ino ├── keywords.txt ├── library.json ├── library.properties ├── src ├── BaseClasses.cpp ├── BaseClasses.h ├── Bitcoin.cpp ├── Bitcoin.h ├── BitcoinCurve.cpp ├── BitcoinCurve.h ├── Conversion.cpp ├── Conversion.h ├── Electrum.cpp ├── Electrum.h ├── HDWallet.cpp ├── Hash.cpp ├── Hash.h ├── Networks.cpp ├── Networks.h ├── OpCodes.h ├── PSBT.cpp ├── PSBT.h ├── Script.cpp ├── Transaction.cpp ├── uBitcoin_conf.h └── utility │ ├── segwit_addr.c │ ├── segwit_addr.h │ └── trezor │ ├── address.c │ ├── address.h │ ├── base58.c │ ├── base58.h │ ├── bignum.c │ ├── bignum.h │ ├── bip32.h │ ├── bip39.c │ ├── bip39.h │ ├── bip39_english.h │ ├── ecdsa.c │ ├── ecdsa.h │ ├── hasher.c │ ├── hasher.h │ ├── hmac.c │ ├── hmac.h │ ├── memzero.c │ ├── memzero.h │ ├── options.h │ ├── pbkdf2.c │ ├── pbkdf2.h │ ├── rand.c │ ├── rand.h │ ├── rfc6979.c │ ├── rfc6979.h │ ├── ripemd160.c │ ├── ripemd160.h │ ├── secp256k1.c │ ├── secp256k1.h │ ├── secp256k1.table │ ├── sha2.c │ ├── sha2.h │ ├── sha3.c │ └── sha3.h └── tests ├── Makefile ├── minunit.h ├── sysrand.c ├── test_conversion.cpp ├── test_hash.cpp ├── test_mnemonic.cpp └── test_schnorr.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | build -------------------------------------------------------------------------------- /.mbedignore: -------------------------------------------------------------------------------- 1 | examples/* 2 | tests/* 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Stepan Snigirev 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 | # Micro-Bitcoin 2 | 3 | C++ Bitcoin library for 32-bit microcontrollers. The library supports [Arduino IDE](https://www.arduino.cc/), [ARM mbed](https://www.mbed.com/en/) and bare metal.
4 | It provides a collection of convenient classes for Bitcoin: private and public keys, HD wallets, generation of the recovery phrases, PSBT transaction formats, scripts — everything required for a hardware wallet or other bitcoin-powered device. 5 | 6 | The library should work on any decent 32-bit microcontroller, like esp32, riscV, stm32 series and others. It *doesn't work* on 8-bit microcontrollers like a classic Arduino as these microcontrollers are not powerful enough to run complicated crypto algorithms. 7 | 8 | We use elliptic curve implementation from [trezor-crypto](https://github.com/trezor/trezor-firmware/tree/master/crypto). API is inspired by [Jimmy Song's](https://github.com/jimmysong/) Porgramming Blockchain class and the [book](https://github.com/jimmysong/programmingbitcoin). 9 | 10 | ## Documentation 11 | 12 | Check out our [tutorial](https://micro-bitcoin.github.io/#/tutorial/README) where we write a minimal hardware wallet, or browse the [API docs](https://micro-bitcoin.github.io/#/api/README). We also have a collection of [recepies](https://micro-bitcoin.github.io/#/recepies/README) for some common use-cases. 13 | 14 | Telegram group: https://t.me/arduinoBitcoin 15 | 16 | ## Alternative libraries 17 | 18 | [DIY Bitcoin Hardware website](https://diybitcoinhardware.com/) has a nice collection of bitcoin-related projects, resources and libraries for makers. 19 | 20 | A few bitcoin libraries: 21 | 22 | - [secp256k1](https://github.com/bitcoin-core/secp256k1) — elliptic curve library from Bitcoin Core and a [version](https://github.com/diybitcoinhardware/secp256k1-embedded) working with Arduino IDE & Mbed out of the box. 23 | - [libwally](https://github.com/ElementsProject/libwally-core/) - bitcoin library from Blockstream and a [version](https://github.com/diybitcoinhardware/libwally-embedded) working with Arduino IDE. 24 | - [f469-disco](https://github.com/diybitcoinhardware/f469-disco) - micropython bitcoin bundle for STM Discovery board and other platforms. 25 | 26 | ## Installation 27 | 28 | The library is [available](https://www.arduino.cc/reference/en/libraries/ubitcoin/) in the Arduino Library manager, or you can download and install it manually. 29 | 30 | [Download](https://github.com/micro-bitcoin/uBitcoin/archive/master.zip) the zip file from our [repository](https://github.com/micro-bitcoin/uBitcoin/) and select in Arduino IDE `Sketch` → `Include library` → `Add .ZIP library...`. 31 | 32 | Or clone it into your `Documents/Arduino/libraries` folder: 33 | 34 | ```sh 35 | git clone https://github.com/micro-bitcoin/uBitcoin.git 36 | ``` 37 | 38 | When installed you will also see a few examples in `File` → `Examples` → `Bitcoin` menu. 39 | 40 | ## Basic usage example 41 | 42 | First, don't forget to include necessary headers: 43 | 44 | ```cpp 45 | // we use these two in our sketch: 46 | #include "Bitcoin.h" 47 | #include "PSBT.h" // if using PSBT functionality 48 | // other headers of the library 49 | #include "Conversion.h" // to get access to functions like toHex() or fromBase64() 50 | #include "Hash.h" // if using hashes in your code 51 | ``` 52 | 53 | Now we can write a simple example that does the following: 54 | 55 | 1. Creates a master private key from a recovery phrase and empty password 56 | 2. Derives account and prints master public key for a watch-only wallet (`zpub` in this case) 57 | 3. Derives and print first segwit address 58 | 4. Parses, signs and prints signed PSBT transaction 59 | 60 | ```cpp 61 | // derive master private key 62 | HDPrivateKey hd("add good charge eagle walk culture book inherit fan nature seek repair", ""); 63 | // derive native segwit account (bip-84) for tesnet 64 | HDPrivateKey account = hd.derive("m/84'/1'/0'/"); 65 | // print xpub: vpub5YkPqVJTA7gjK...AH2rXvcAe3p781G 66 | Serial.println(account.xpub()); 67 | // or change the account type to UNKNOWN_TYPE to get tpub 68 | HDPublicKey xpub = account.xpub(); 69 | xpub.type = UNKNOWN_TYPE; 70 | // this time prints tpubDCnYy4Ty...dL4fLKsBFjFQwz 71 | Serial.println(xpub); 72 | // set back correct type to get segwit addresses by default 73 | xpub.type = P2WPKH; 74 | Serial.println(hd.fingerprint()); 75 | 76 | // print first address: tb1q6c8m3whsag5zadgl32nmhuf9q0qmtklws25n6g 77 | Serial.println(xpub.derive("m/0/0").address()); 78 | 79 | PSBT tx; 80 | // parse unsigned transaction 81 | tx.parseBase64("cHNidP8BAHECAAAAAUQS8FqBzYocPDpeQmXBRBH7NwZHVJF39dYJDCXxq" 82 | "zf6AAAAAAD+////AqCGAQAAAAAAFgAUuP0WcSBmiAZYi91nX90hg/cZJ1U8AgMAAAAAABYAF" 83 | "C1RhUR+m/nFyQkPSlP0xmZVxlOqAAAAAAABAR/gkwQAAAAAABYAFNYPuLrw6igutR+Kp7vxJ" 84 | "QPBtdvuIgYDzkBZaAkSIz0P0BexiPYfzInxu9mMeuaOQa1fGEUXcWIYoyAeuFQAAIABAACAA" 85 | "AAAgAAAAAAAAAAAAAAiAgMxjOiFQofq7l9q42nsLA3Ta4zKpEs5eCnAvMnQaVeqsBijIB64V" 86 | "AAAgAEAAIAAAACAAQAAAAAAAAAA"); 87 | // sign with the root key 88 | tx.sign(hd); 89 | // print signed transaction 90 | Serial.println(tx.toBase64()); 91 | ``` 92 | 93 | Ready for more? Check out the [tutorial](https://micro-bitcoin.github.io/#/tutorial/README) and start writing your very own hardware wallet! 94 | -------------------------------------------------------------------------------- /examples/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET ?= main 2 | 3 | ifeq ($(OS),Windows_NT) 4 | EXT ?= .exe 5 | else 6 | EXT ?= 7 | endif 8 | 9 | TARGET_EXEC ?= $(TARGET)$(EXT) 10 | 11 | # Paths 12 | # to make sure addprefix to LIB_DIR doesn't go out from build directory 13 | BUILD_DIR = build 14 | SRC_DIR = . 15 | # uBitcoin library 16 | LIB_DIR = ../../src 17 | 18 | # Tools 19 | ifeq ($(OS),Windows_NT) 20 | TOOLCHAIN_PREFIX ?= x86_64-w64-mingw32- 21 | MKDIR_P = mkdir 22 | RM_R = rmdir /s /q 23 | else 24 | TOOLCHAIN_PREFIX ?= 25 | MKDIR_P = mkdir -p 26 | RM_R = rm -r 27 | endif 28 | 29 | # compilers 30 | CC := $(TOOLCHAIN_PREFIX)gcc 31 | CXX := $(TOOLCHAIN_PREFIX)g++ 32 | 33 | # main.cpp 34 | CXX_SOURCES = $(wildcard $(SRC_DIR)/*.cpp) 35 | C_SOURCES = 36 | 37 | # uBitcoin sources 38 | CXX_SOURCES += $(wildcard $(LIB_DIR)/*.cpp) 39 | C_SOURCES += $(wildcard $(LIB_DIR)/utility/trezor/*.c) \ 40 | $(wildcard $(LIB_DIR)/utility/*.c) \ 41 | $(wildcard $(LIB_DIR)/*.c) 42 | 43 | # include lib path, don't use mbed or arduino config (-DUSE_STDONLY), debug symbols, all warnings as errors 44 | FLAGS = -I$(LIB_DIR) -g -Wall -Werror -ldl 45 | CFLAGS = $(FLAGS) 46 | CPPFLAGS = $(FLAGS) -DUSE_STDONLY -DUBTC_EXAMPLE 47 | 48 | OBJS = $(patsubst $(SRC_DIR)/%, $(BUILD_DIR)/src/%.o, \ 49 | $(patsubst $(LIB_DIR)/%, $(BUILD_DIR)/lib/%.o, \ 50 | $(C_SOURCES) $(CXX_SOURCES))) 51 | 52 | vpath %.cpp $(SRC_DIR) 53 | vpath %.cpp $(LIB_DIR) 54 | vpath %.c $(LIB_DIR) 55 | 56 | .PHONY: clean all run 57 | 58 | all: $(BUILD_DIR)/$(TARGET_EXEC) 59 | 60 | run: $(BUILD_DIR)/$(TARGET_EXEC) 61 | $(BUILD_DIR)/$(TARGET_EXEC) 62 | 63 | $(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) 64 | $(CXX) $(OBJS) $(CPPFLAGS) -o $@ 65 | 66 | # lib c sources 67 | $(BUILD_DIR)/lib/%.c.o: %.c 68 | $(MKDIR_P) $(dir $@) 69 | $(CC) -c $(CFLAGS) $< -o $@ 70 | 71 | # lib cpp sources 72 | $(BUILD_DIR)/lib/%.cpp.o: %.cpp 73 | $(MKDIR_P) $(dir $@) 74 | $(CXX) -c $(CPPFLAGS) $< -o $@ 75 | 76 | # cpp sources 77 | $(BUILD_DIR)/src/%.cpp.o: %.cpp 78 | $(MKDIR_P) $(dir $@) 79 | $(CXX) -c $(CPPFLAGS) $< -o $@ 80 | 81 | clean: 82 | $(RM_R) $(BUILD_DIR) 83 | -------------------------------------------------------------------------------- /examples/cpp/README.md: -------------------------------------------------------------------------------- 1 | # C++ example 2 | 3 | run with `make run` 4 | -------------------------------------------------------------------------------- /examples/cpp/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * A simple example showing how to work with uBitcoin in c++ on a PC 3 | */ 4 | 5 | // only compile when UBTC_EXAMPLE flag is provided 6 | // to not clash with platformio's compile-everything approach 7 | #ifdef UBTC_EXAMPLE 8 | 9 | #include 10 | #include "Bitcoin.h" 11 | #include "PSBT.h" 12 | 13 | #include 14 | #include 15 | 16 | // You can define your random function to improve side-channel resistance 17 | extern "C" { 18 | 19 | // use system random function 20 | uint32_t random32(void){ 21 | return (uint32_t)rand(); 22 | } 23 | 24 | } 25 | 26 | using namespace std; 27 | 28 | char mnemonic[] = "flight canvas heart purse potato mixed offer tooth maple blue kitten salute almost staff physical remain coral clump midnight rotate innocent shield inch ski"; 29 | 30 | int main() { 31 | // convert mnemonic to xprv 32 | cout << "Your mnemonic: " << endl << mnemonic << endl; 33 | HDPrivateKey hd(mnemonic, ""); 34 | cout << "Your xprv: " << endl << string(hd) << endl; 35 | // derive account xpub 36 | char derivation[] = "m/84h/1h/0h"; 37 | HDPublicKey xpub = hd.derive(derivation).xpub(); 38 | // set network to regtest, otherwise default addresses will be for testnet 39 | xpub.network = &Regtest; 40 | cout << "Account xpub at path " << derivation << ":" << endl; 41 | cout << string(xpub) << endl; 42 | // print first 5 receiving addresses 43 | HDPublicKey recv_xpub = xpub.child(0); 44 | for (uint32_t i = 0; i < 5; i++) 45 | { 46 | cout << "Address #" << i << ": " << recv_xpub.child(i).address() << endl; 47 | } 48 | 49 | // signing PSBT transaction with 2 inputs 50 | PSBT psbt; 51 | psbt.parseBase64(string("cHNidP8BAJoCAAAAAqQW9JR6TFv46IXybtf9tKAy5WsYusr6O4rsfN8DIywEAQAAAAD9////9YKXV2aJad3wScN70cgZHMhQtwhTjw95loZfUB57+H4AAAAAAP3///8CwOHkAAAAAAAWABQzSSTq9G6AboazU3oS+BWVAw1zp21KTAAAAAAAFgAU2SSg4OQMonZrrLpdtTzcNes1MthDAQAAAAEAcQIAAAAB6GDWQUAnmq5s8Nm68qPp3fHnpARmx67Q5ZRHGj1rCjgBAAAAAP7///8CdIv2XwAAAAAWABRozVhYn14Pmv8XoAJePV7AQggf/4CWmAAAAAAAFgAUcOVKtnxrbE7ragGagzMqQ7kJsZkAAAAAAQEfgJaYAAAAAAAWABRw5Uq2fGtsTutqAZqDMypDuQmxmSIGA3s6OgE8GCKOcHDJe7XY0q/i/XSe6e933ErCDCCKR5WoGARkI4xUAACAAQAAgAAAAIAAAAAAAAAAAAABAHECAAAAAaH0XE8I0jQHvCDfdDTUbHrm9+oHbq1yt5ansxoaeeNjAQAAAAD+////AoCWmAAAAAAAFgAUQZD8n6hVi91tRSlWl4WkMwuBnoXsVTuMAAAAABYAFMbknFZNyqOzappeWfZi2+EP0asDAAAAAAEBH4CWmAAAAAAAFgAUQZD8n6hVi91tRSlWl4WkMwuBnoUiBgKNwymEX374HvJHU9FIT4YmCn8CuNteCOxtw7bJXGfscxgEZCOMVAAAgAEAAIAAAACAAAAAAAEAAAAAACICA9OwnpVPPgWAC/O7SuxHNPjX46Iz2Qv9dcI033AqEyv+GARkI4xUAACAAQAAgAAAAIABAAAAAAAAAAA=")); 52 | // check parsing is ok 53 | if(!psbt){ 54 | cout << "Failed parsing transaction" << endl; 55 | exit(EXIT_FAILURE); 56 | return EXIT_FAILURE; 57 | } 58 | cout << "Transactions details:" << endl; 59 | // going through all outputs 60 | cout << "Outputs:" << endl; 61 | for(unsigned int i = 0; i < psbt.tx.outputsNumber; i++){ 62 | // print addresses 63 | cout << psbt.tx.txOuts[i].address(&Regtest); 64 | if(psbt.txOutsMeta[i].derivationsLen > 0){ // there is derivation path 65 | // considering only single key for simplicity 66 | PSBTDerivation der = psbt.txOutsMeta[i].derivations[0]; 67 | HDPublicKey pub = hd.derive(der.derivation, der.derivationLen).xpub(); 68 | pub.network = &Regtest; 69 | if(pub.address() == psbt.tx.txOuts[i].address(&Regtest)){ 70 | cout << " (change) "; 71 | } 72 | } 73 | cout << " -> " << psbt.tx.txOuts[i].btcAmount()*1e3 << " mBTC" << endl; 74 | } 75 | cout << "Fee: " << psbt.fee() << " sat" << endl; 76 | 77 | // sign using our key 78 | psbt.sign(hd); 79 | cout << "Signed transaction:" << endl << psbt.toBase64() << endl; // now you can combine and finalize PSBTs in Bitcoin Core 80 | 81 | return 0; 82 | } 83 | 84 | #endif // UBTC_EXAMPLE 85 | -------------------------------------------------------------------------------- /examples/ecdh/ecdh.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example shows how to use ECDH algorithm 3 | * to get shared secret between two parties. 4 | * It is useful if you want to establish 5 | * secure communication with someone else. 6 | * You can use ECDH to create symmetric key 7 | * and then use AES in CBC mode to encrypt/decrypt data. 8 | */ 9 | #include 10 | #include 11 | 12 | void setup(){ 13 | Serial.begin(9600); 14 | while(!Serial){ 15 | ; // wait for serial port to open 16 | } 17 | // generate random private keys and corresponding pubkeys 18 | byte secret1[32]; 19 | byte secret2[32]; 20 | for(int i=0; i // all single-line hashing algorithms 2 | #include // to print byte arrays in hex format 3 | 4 | void setup() { 5 | Serial.begin(9600); 6 | while(!Serial){ 7 | ; // wait for serial port to open 8 | } 9 | String message = "Hello world!"; // message to hash 10 | byte hash[64] = { 0 }; // hash 11 | int hashLen = 0; 12 | 13 | // sha-256 14 | hashLen = sha256(message, hash); 15 | Serial.println("SHA-256: " + toHex(hash, hashLen)); 16 | Serial.println("Should be: c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a"); 17 | 18 | // you can also pass byte arrays to the hash function 19 | // and update piece by piece 20 | byte msg2[] = {1, 2, 3, 4, 5, 0xFA, 0xB0, 0x0B, 0x51}; 21 | // hash in one line 22 | sha256(msg2, sizeof(msg2), hash); 23 | // you can also create a class instance and use .write method 24 | SHA256 h; 25 | h.begin(); 26 | h.write(msg2, 5); // add first 5 bytes to hash 27 | h.write(msg2+5, 4); // add another 4 bytes 28 | h.end(hash); // result will be stored in the hash array 29 | 30 | // ripemd-160 31 | hashLen = rmd160(message, hash); 32 | Serial.println("RMD-160: " + toHex(hash, hashLen)); 33 | Serial.println("Should be: 7f772647d88750add82d8e1a7a3e5c0902a346a3"); 34 | 35 | // hash160(msg) = rmd160(sha256(message)) 36 | hashLen = hash160(message, hash); 37 | Serial.println("Hash160: " + toHex(hash, hashLen)); 38 | Serial.println("Should be: 621281c15fb62d5c6013ea29007491e8b174e1b9"); 39 | 40 | // sha256(sha256(message)) 41 | hashLen = doubleSha(message, hash); 42 | Serial.println("DoubleSha: " + toHex(hash, hashLen)); 43 | Serial.println("Should be: 7982970534e089b839957b7e174725ce1878731ed6d700766e59cb16f1c25e27"); 44 | 45 | // sha512 46 | hashLen = sha512(message, hash); 47 | Serial.println("Sha512: " + toHex(hash, hashLen)); 48 | Serial.println("Should be: f6cde2a0f819314cdde55fc227d8d7dae3d28cc556222a0a8ad66d91ccad4aad6094f517a2182360c9aacf6a3dc323162cb6fd8cdffedb0fe038f55e85ffb5b6"); 49 | 50 | // sha512-hmac 51 | // here we use more c-style approach 52 | char key[] = "Bitcoin seed"; 53 | hashLen = sha512Hmac((byte*)key, strlen(key), (byte*)message.c_str(), message.length(), hash); 54 | Serial.println("Sha512-HMAC: " + toHex(hash, hashLen)); 55 | Serial.println("Should be: f7fc496a2c17bd09a6328124dc6edebed987e7e93903deee0633a756f1ee81da0753334f6cfe226b5c712d893a68c547d3a5497cd73e1d010670c1e0e9d93a8a"); 56 | } 57 | 58 | void loop() { 59 | 60 | } 61 | -------------------------------------------------------------------------------- /examples/mnemonic/mnemonic.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example shows how to derive master private key from the recovery seed 3 | * Generate a random recovery seed i.e. on https://iancoleman.io/bip39/ 4 | * and check the master private key, account private key, account public key 5 | * and first address. 6 | */ 7 | #include "Bitcoin.h" 8 | 9 | void printHD(String mnemonic, String password = ""){ 10 | 11 | HDPrivateKey hd(mnemonic, password); 12 | 13 | if(!hd){ // check if it is valid 14 | Serial.println("Invalid xpub"); 15 | return; 16 | } 17 | Serial.println("Mnemonic:"); 18 | Serial.println(mnemonic); 19 | Serial.print("Password: \""); 20 | Serial.println(password+"\""); 21 | Serial.println("Root private key:"); 22 | Serial.println(hd); 23 | 24 | Serial.println("bip84 master private key:"); 25 | HDPrivateKey account = hd.derive("m/84'/0'/0'/"); 26 | Serial.println(account); 27 | 28 | Serial.println("bip84 master public key:"); 29 | Serial.println(account.xpub()); 30 | 31 | Serial.println("first address:"); 32 | Serial.println(account.derive("m/0/0/").address()); 33 | 34 | Serial.println("\n"); 35 | } 36 | 37 | void setup() { 38 | Serial.begin(115200); 39 | printHD("arch volcano urge cradle turn labor skin secret squeeze denial jacket vintage fix glad lemon", "my secret password"); 40 | 41 | // entropy bytes to mnemonic 42 | uint8_t arr[] = {'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'}; 43 | String mn = mnemonicFromEntropy(arr, sizeof(arr)); 44 | Serial.println(mn); 45 | uint8_t out[16]; 46 | size_t len = mnemonicToEntropy(mn, out, sizeof(out)); 47 | Serial.println(toHex(out, len)); 48 | 49 | } 50 | 51 | void loop() { 52 | delay(100); 53 | } 54 | -------------------------------------------------------------------------------- /examples/multisig/multisig.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * A simple example showing how to derive multisig addresses 3 | */ 4 | 5 | #include "Bitcoin.h" 6 | 7 | // 2 of 3 multisig 8 | #define NUM_KEYS 3 9 | #define THRESHOLD 2 10 | 11 | // cosigners 12 | HDPublicKey xpubs[] = { 13 | // [73c5da0a/48h/1h/0h/2h] abandon * 11 + about 14 | HDPublicKey("Vpub5n95dMZrDHj6SeBgJ1oz4Fae2N2eJNuWK3VTKDb2dzGpMFLUHLmtyDfen7AaQxwQ5mZnMyXdVrkEaoMLVTH8FmVBRVWPGFYWhmtDUGehGmq"), 15 | // [fb7c1f11/48h/1h/0h/2h] ability * 11 + acid 16 | HDPublicKey("Vpub5mpiGVPWYfDWqZAvCtJihfU559GdwhNC5gwCa9xjSBp4Bvr1DnqXYTtAogkjvWYN1LGTyKo5Yjhfz7mNAqVmw7KG66CM4mDd8vGH3zPQmBH"), 17 | // [47fc1ba1/48h/1h/0h/2h] able * 11 + acid 18 | HDPublicKey("Vpub5nRyr5ptHEvisEDuWRMY3rgQ99B1CU21wfkuXEekTi8jCshCWseGqBWWZ8U3Wgv4jDj2fizxBNZmpFjo56Ffu49Efpu4vAj5XErHyBEQoN9"), 19 | }; 20 | 21 | void setup() { 22 | Serial.begin(); 23 | 24 | // print first 5 addresses 25 | for(int idx = 0; idx < 5; idx++){ 26 | // get derivation path 27 | String derivation = String("m/0/")+String(idx); 28 | Serial.println(derivation); 29 | // generate individual public keys and put them into array 30 | PublicKey pubkeys[NUM_KEYS]; 31 | for(int i=0; i 0){ // there is derivation path 27 | // considering only single key for simplicity 28 | PSBTDerivation der = psbt.txOutsMeta[i].derivations[0]; 29 | HDPublicKey pub = hd.derive(der.derivation, der.derivationLen).xpub(); 30 | if(pub.address() == psbt.tx.txOuts[i].address()){ 31 | Serial.print(" (change) "); 32 | } 33 | } 34 | Serial.print(" -> "); 35 | Serial.print(psbt.tx.txOuts[i].btcAmount()*1e3); 36 | Serial.println(" mBTC"); 37 | } 38 | Serial.print("Fee: "); 39 | Serial.print(float(psbt.fee())/100); // Arduino can't print 64-bit ints 40 | Serial.println(" bits"); 41 | 42 | psbt.sign(hd); 43 | Serial.println(psbt.toBase64()); // now you can combine and finalize PSBTs in Bitcoin Core 44 | } 45 | 46 | void loop() { 47 | } 48 | -------------------------------------------------------------------------------- /examples/schnorr/schnorr.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * A simple example showing how to work with uBitcoin in c++ on a PC 3 | */ 4 | #include "Bitcoin.h" 5 | #include "Hash.h" 6 | 7 | char mnemonic[] = "flight canvas heart purse potato mixed offer tooth maple blue kitten salute almost staff physical remain coral clump midnight rotate innocent shield inch ski"; 8 | // convert mnemonic to xprv 9 | HDPrivateKey hd(mnemonic, ""); 10 | 11 | void setup() { 12 | Serial.begin(115200); 13 | 14 | Serial.println("Your mnemonic: "); 15 | Serial.println(mnemonic); 16 | 17 | // derive private key you want to use for schnorr 18 | PrivateKey prv = hd.derive("m/86h/0h/0h/0/1"); 19 | // print corresponding public key - schnorr keys are x-only 32-byte keys 20 | PublicKey pub = prv.publicKey(); 21 | Serial.print("Private key: "); 22 | Serial.println(prv); 23 | Serial.print("X-only public key: "); 24 | Serial.println(pub.x()); 25 | // sign message 26 | uint8_t msg[32]; 27 | sha256("hello world!", msg); 28 | // sign using Schnorr algorithm 29 | SchnorrSignature sig = prv.schnorr_sign(msg); 30 | // Unlike ECDSA, Schnorr signature is always 64-bytes long 31 | Serial.println("Signature for message 'hello world!':"); 32 | Serial.println(sig); 33 | // verify signatures 34 | if(pub.schnorr_verify(sig, msg)){ 35 | Serial.println("All good, signature is valid"); 36 | }else{ 37 | Serial.println("Something is wrong! Signature is invalid."); 38 | } 39 | } 40 | 41 | void loop() { 42 | } 43 | -------------------------------------------------------------------------------- /examples/tx/tx.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Bitcoin.h" 3 | 4 | void setup() { 5 | Serial.begin(9600); 6 | while(!Serial){ 7 | ; 8 | } 9 | 10 | // Single private key for testnet 11 | PrivateKey privateKey("cQwxqQwCwGoirnTkVnNt4XqJuEv24HYBvVWCTLtL5g1kx9Q1AEhE"); 12 | Serial.println(privateKey.address()); 13 | 14 | TxIn txIn("fbeae5f43d76fc3035cb4190baaf8cc123dd04f11c98c8f19a8b12cb4ce90db0", 0); 15 | 16 | // addresses to send bitcoins 17 | char destination[] = "n3DN9cswq5jnXXUmLP3bXtR89yfDNWrie9"; 18 | String change = privateKey.address(); 19 | 20 | // amounts to send 21 | // unsigned long can store up to 4294967295 satoshi (42.9 BTC) 22 | // for larger amounts use uint64_t 23 | unsigned long availableAmount = 2000000; // 58 mBTC 24 | unsigned long fee = 1500; 25 | unsigned long sendAmount = 1000000; // 20 mBTC 26 | unsigned long changeAmount = availableAmount - sendAmount - fee; 27 | 28 | TxOut txOutDestination(sendAmount, destination); 29 | TxOut txOutChange(changeAmount, change.c_str()); 30 | 31 | Serial.println(txOutDestination); 32 | 33 | // constructing actual transaction 34 | Tx tx; 35 | tx.addInput(txIn); 36 | tx.addOutput(txOutDestination); 37 | tx.addOutput(txOutChange); 38 | 39 | // Printing transaction information 40 | Serial.print("Tx length: "); 41 | Serial.println(tx.length()); 42 | 43 | Serial.print("Version: "); 44 | Serial.println(tx.version); 45 | Serial.print("Inputs: "); 46 | Serial.println(tx.inputsNumber); 47 | for(int i=0; i< tx.inputsNumber; i++){ 48 | TxIn txin = tx.txIns[i]; 49 | Serial.print("\tHash: "); 50 | Serial.println(toHex(txin.hash, 32)); 51 | Serial.print("\tOutput index: "); 52 | Serial.println(txin.outputIndex); 53 | Serial.print("\tScript length: "); 54 | Serial.println(txin.scriptSig.length()); 55 | Serial.print("\tScript: "); 56 | Serial.println(txin.scriptSig); 57 | Serial.print("\tSequence: "); 58 | Serial.println(txin.sequence); 59 | if(tx.isSegwit()){ 60 | Serial.println("\tSEGWIT!"); 61 | } 62 | } 63 | Serial.print("Outputs: "); 64 | Serial.println(tx.outputsNumber); 65 | 66 | for(int i=0; i< tx.outputsNumber; i++){ 67 | Serial.print(tx.txOuts[i].address()); 68 | Serial.print(": "); 69 | Serial.print(((float)tx.txOuts[i].amount)/100000); 70 | Serial.println(" mBTC"); 71 | } 72 | 73 | Serial.println("Unsigned transaction:"); 74 | Serial.println(tx); 75 | 76 | // signing transaction 77 | Serial.println("Signing transaction..."); 78 | Signature sig = tx.signInput(0, privateKey); 79 | Serial.println(sig); 80 | 81 | Serial.println("Signed transaction:"); 82 | Serial.println(tx); 83 | 84 | Serial.println("Transaction id:"); 85 | Serial.println(tx.txid()); 86 | 87 | Serial.println("Done"); 88 | } 89 | 90 | void loop() { 91 | // put your main code here, to run repeatedly: 92 | delay(100); 93 | } 94 | -------------------------------------------------------------------------------- /examples/xpubs/xpubs.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example shows how to derive bitcoin addresses from the master public key (bip32) 3 | * Enter account master public key to the serial console and get the addresses 4 | * Use this tool to check: https://iancoleman.io/bip39/ 5 | */ 6 | #include "Bitcoin.h" 7 | 8 | void printAddresses(String pub){ 9 | 10 | HDPublicKey hd(pub); 11 | 12 | if(!hd){ // check if it is valid 13 | Serial.println("Invalid xpub"); 14 | return; 15 | } 16 | 17 | Serial.println("Master public key:"); 18 | Serial.println(hd); 19 | 20 | Serial.println("First 5 receiving addresses:"); 21 | for(int i=0; i<5; i++){ 22 | String path = String("m/0/")+i; 23 | Serial.print("Path:"); 24 | Serial.println(path); 25 | Serial.print("Address: "); 26 | Serial.println(hd.derive(path).address()); 27 | // Serial.print("Legacy: "); 28 | // Serial.println(hd.derive(path).legacyAddress()); 29 | // Serial.print("Nested segwit: "); 30 | // Serial.println(hd.derive(path).nestedSegwitAddress()); 31 | // Serial.print("Native segwit: "); 32 | // Serial.println(hd.derive(path).segwitAddress()); 33 | } 34 | 35 | Serial.println("\n"); 36 | } 37 | 38 | void setup() { 39 | Serial.begin(115200); 40 | // bip 44 41 | printAddresses("xpub6BoiLSuHTDytgQejDauyXkBqQ4xTw2tSFKgkHfmZky7jDQQecUKwbFocxZXSJMCSp8gFNBbD9Squ3etZbJkE2qQqVBrypLjWJaWUNmHh3LT"); 42 | // bip 49 43 | printAddresses("ypub6XMsccDqTfZCUz5m4VjbRLebnjFTLDpeKTgRJuUtAxkpQicB7p4ZwHdmimRuMTcunPfdpzgpVt7DCDKRRffsgmWavWLXccumbyYazC3wh5N"); 44 | // bip 84 45 | printAddresses("zpub6rcGDMmj82CUJT1uV2mCcsN4EPTgBnJjciDWpYv12yCAPi9TEG5KLPF5iPtqzL6hNmaa5ZGfhJCHctoex7cGgqVxsyWcCDUNUDhjaYRQXzV"); 46 | Serial.println("Enter your master public key:"); 47 | } 48 | 49 | void loop() { 50 | if(Serial.available()){ 51 | String pub = Serial.readStringUntil('\n'); 52 | Serial.println(pub); 53 | if(pub.length() > 0){ 54 | printAddresses(pub); 55 | } 56 | } 57 | delay(100); 58 | } 59 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map 3 | ####################################### 4 | 5 | ####################################### 6 | # Hash.h Methods and Functions (KEYWORD2) 7 | ####################################### 8 | 9 | rmd160 KEYWORD2 10 | sha256 KEYWORD2 11 | hash160 KEYWORD2 12 | doubleSha KEYWORD2 13 | sha512 KEYWORD2 14 | sha512Hmac KEYWORD2 15 | 16 | ####################################### 17 | # Datatypes and classes (KEYWORD1) 18 | ####################################### 19 | 20 | Bitcoin KEYWORD1 21 | Hash KEYWORD1 22 | Conversion KEYWORD1 23 | OpCodes KEYWORD1 24 | 25 | Scalar KEYWORD1 26 | Point KEYWORD1 27 | PrivateKey KEYWORD1 28 | PublicKey KEYWORD1 29 | HDPrivateKey KEYWORD1 30 | HDPublicKey KEYWORD1 31 | Script KEYWORD1 32 | Signature KEYWORD1 33 | SchnorrSignature KEYWORD1 34 | Tx KEYWORD1 35 | TxIn KEYWORD1 36 | TxOut KEYWORD1 37 | ElectrumTx KEYWORD1 38 | PSBT KEYWORD1 39 | 40 | ####################################### 41 | # Methods and Functions (KEYWORD2) 42 | ####################################### 43 | 44 | parse KEYWORD2 45 | parseHex KEYWORD2 46 | parseBase64 KEYWORD2 47 | toBase64 KEYWORD2 48 | serialize KEYWORD2 49 | bin KEYWORD2 50 | der KEYWORD2 51 | 52 | type KEYWORD2 53 | length KEYWORD2 54 | scriptLength KEYWORD2 55 | serializeScript KEYWORD2 56 | push KEYWORD2 57 | scriptPubkey KEYWORD2 58 | address KEYWORD2 59 | 60 | pow KEYWORD2 61 | sign KEYWORD2 62 | schnorr_sign KEYWORD2 63 | verify KEYWORD2 64 | schnorr_verify KEYWORD2 65 | fromSeed KEYWORD2 66 | fromMnemonic KEYWORD2 67 | xpub KEYWORD2 68 | xprv KEYWORD2 69 | child KEYWORD2 70 | hardenedChild KEYWORD2 71 | derive KEYWORD2 72 | legacyAddress KEYWORD2 73 | segwitAddress KEYWORD2 74 | nestedSegwitAddress KEYWORD2 75 | parse KEYWORD2 76 | fromWIF KEYWORD2 77 | publicKey KEYWORD2 78 | sec KEYWORD2 79 | fromHex KEYWORD2 80 | toHex KEYWORD2 81 | toString KEYWORD2 82 | generateMnemonic KEYWORD2 83 | checkMnemonic KEYWORD2 84 | 85 | littleEndianToInt KEYWORD2 86 | intToLittleEndian KEYWORD2 87 | bigEndianToInt KEYWORD2 88 | intToBigEndian KEYWORD2 89 | 90 | lenVarInt KEYWORD2 91 | readVarInt KEYWORD2 92 | readVarInt KEYWORD2 93 | writeVarInt KEYWORD2 94 | writeVarInt KEYWORD2 95 | 96 | addInput KEYWORD2 97 | addOutput KEYWORD2 98 | signInput KEYWORD2 99 | signSegwitInput KEYWORD2 100 | sigHash KEYWORD2 101 | 102 | ###################################### 103 | # Constants (LITERAL1) 104 | ####################################### 105 | 106 | PRIME LITERAL1 107 | 108 | P2PKH LITERAL1 109 | P2SH LITERAL1 110 | P2WPKH LITERAL1 111 | P2WSH LITERAL1 112 | P2SH_P2WPKH LITERAL1 113 | P2SH_P2WSH LITERAL1 114 | SIGHASH_ALL LITERAL1 115 | SIGHASH_NONE LITERAL1 116 | SIGHASH_SINGLE LITERAL1 117 | 118 | ###################################### 119 | # Opcodes (LITERAL1) 120 | ####################################### 121 | 122 | OP_0 LITERAL1 123 | OP_PUSHDATA1 LITERAL1 124 | OP_PUSHDATA2 LITERAL1 125 | OP_PUSHDATA4 LITERAL1 126 | OP_1NEGATE LITERAL1 127 | OP_RESERVED LITERAL1 128 | OP_1 LITERAL1 129 | OP_2 LITERAL1 130 | OP_3 LITERAL1 131 | OP_4 LITERAL1 132 | OP_5 LITERAL1 133 | OP_6 LITERAL1 134 | OP_7 LITERAL1 135 | OP_8 LITERAL1 136 | OP_9 LITERAL1 137 | OP_10 LITERAL1 138 | OP_11 LITERAL1 139 | OP_12 LITERAL1 140 | OP_13 LITERAL1 141 | OP_14 LITERAL1 142 | OP_15 LITERAL1 143 | OP_16 LITERAL1 144 | OP_NOP LITERAL1 145 | OP_VER LITERAL1 146 | OP_IF LITERAL1 147 | OP_NOTIF LITERAL1 148 | OP_VERIF LITERAL1 149 | OP_VERNOTIF LITERAL1 150 | OP_ELSE LITERAL1 151 | OP_ENDIF LITERAL1 152 | OP_VERIFY LITERAL1 153 | OP_RETURN LITERAL1 154 | OP_TOALTSTACK LITERAL1 155 | OP_FROMALTSTACK LITERAL1 156 | OP_2DROP LITERAL1 157 | OP_2DUP LITERAL1 158 | OP_3DUP LITERAL1 159 | OP_2OVER LITERAL1 160 | OP_2ROT LITERAL1 161 | OP_2SWAP LITERAL1 162 | OP_IFDUP LITERAL1 163 | OP_DEPTH LITERAL1 164 | OP_DROP LITERAL1 165 | OP_DUP LITERAL1 166 | OP_NIP LITERAL1 167 | OP_OVER LITERAL1 168 | OP_PICK LITERAL1 169 | OP_ROLL LITERAL1 170 | OP_ROT LITERAL1 171 | OP_SWAP LITERAL1 172 | OP_TUCK LITERAL1 173 | OP_CAT LITERAL1 174 | OP_SUBSTR LITERAL1 175 | OP_LEFT LITERAL1 176 | OP_RIGHT LITERAL1 177 | OP_SIZE LITERAL1 178 | OP_INVERT LITERAL1 179 | OP_AND LITERAL1 180 | OP_OR LITERAL1 181 | OP_XOR LITERAL1 182 | OP_EQUAL LITERAL1 183 | OP_EQUALVERIFY LITERAL1 184 | OP_RESERVED1 LITERAL1 185 | OP_RESERVED2 LITERAL1 186 | OP_1ADD LITERAL1 187 | OP_1SUB LITERAL1 188 | OP_2MUL LITERAL1 189 | OP_2DIV LITERAL1 190 | OP_NEGATE LITERAL1 191 | OP_ABS LITERAL1 192 | OP_NOT LITERAL1 193 | OP_0NOTEQUAL LITERAL1 194 | OP_ADD LITERAL1 195 | OP_SUB LITERAL1 196 | OP_MUL LITERAL1 197 | OP_DIV LITERAL1 198 | OP_MOD LITERAL1 199 | OP_LSHIFT LITERAL1 200 | OP_RSHIFT LITERAL1 201 | OP_BOOLAND LITERAL1 202 | OP_BOOLOR LITERAL1 203 | OP_NUMEQUAL LITERAL1 204 | OP_NUMEQUALVERIFY LITERAL1 205 | OP_NUMNOTEQUAL LITERAL1 206 | OP_LESSTHAN LITERAL1 207 | OP_GREATERTHAN LITERAL1 208 | OP_LESSTHANOREQUAL LITERAL1 209 | OP_GREATERTHANOREQUAL LITERAL1 210 | OP_MIN LITERAL1 211 | OP_MAX LITERAL1 212 | OP_WITHIN LITERAL1 213 | OP_RIPEMD160 LITERAL1 214 | OP_SHA1 LITERAL1 215 | OP_SHA256 LITERAL1 216 | OP_HASH160 LITERAL1 217 | OP_HASH256 LITERAL1 218 | OP_CODESEPARATOR LITERAL1 219 | OP_CHECKSIG LITERAL1 220 | OP_CHECKSIGVERIFY LITERAL1 221 | OP_CHECKMULTISIG LITERAL1 222 | OP_CHECKMULTISIGVERIFY LITERAL1 223 | OP_NOP1 LITERAL1 224 | OP_CHECKLOCKTIMEVERIFY LITERAL1 225 | OP_CHECKSEQUENCEVERIFY LITERAL1 226 | OP_NOP4 LITERAL1 227 | OP_NOP5 LITERAL1 228 | OP_NOP6 LITERAL1 229 | OP_NOP7 LITERAL1 230 | OP_NOP8 LITERAL1 231 | OP_NOP9 LITERAL1 232 | OP_NOP10 LITERAL1 233 | OP_NULLDATA LITERAL1 234 | OP_PUBKEYHASH LITERAL1 235 | OP_PUBKEY LITERAL1 236 | OP_INVALIDOPCODE LITERAL1 237 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uBitcoin", 3 | "version": "0.2.0", 4 | "description": "Brings Bitcoin to embedded devices. Write your own hardware wallet, vending machine or any other bitcoin-powered device. Supports public and private keys, HD wallets, transactions and scripts. Everything required to start working with Bitcoin on microcontrollers.", 5 | "keywords": "bitcoin, cryptography", 6 | "repository": 7 | { 8 | "type": "git", 9 | "url": "https://github.com/micro-bitcoin/uBitcoin.git" 10 | }, 11 | "authors": 12 | [ 13 | { 14 | "name": "Stepan Snigirev", 15 | "email": "snigirev.stepan@gmail.com", 16 | "url": "https://stepansnigirev.com" 17 | } 18 | ], 19 | "license": "MIT", 20 | "homepage": "https://micro-bitcoin.github.io", 21 | "dependencies": { 22 | }, 23 | "frameworks": "*", 24 | "platforms": "*" 25 | } 26 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=uBitcoin 2 | version=0.2.0 3 | author=Stepan Snigirev 4 | maintainer=Stepan Snigirev 5 | sentence=Brings Bitcoin to embedded devices 6 | paragraph=Write your own hardware wallet, vending machine or any other bitcoin-powered device. Supports public and private keys, HD wallets, transactions and scripts. Everything required to start working with Bitcoin on microcontrollers. 7 | category=Data Processing 8 | url=https://github.com/micro-bitcoin/uBitcoin 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/BaseClasses.cpp: -------------------------------------------------------------------------------- 1 | #include "uBitcoin_conf.h" 2 | #include "BaseClasses.h" 3 | #include 4 | 5 | #if USE_STD_STRING 6 | using std::string; 7 | #define String string 8 | #endif 9 | 10 | size_t SerializeStream::serialize(const Streamable * s, size_t offset){ 11 | return s->to_stream(this, offset); 12 | } 13 | 14 | size_t ParseStream::parse(Streamable * s){ 15 | return s->from_stream(this); 16 | } 17 | /************ Parse Byte Stream Class ************/ 18 | 19 | ParseByteStream::ParseByteStream(const uint8_t * arr, size_t length, encoding_format f){ 20 | last = -1; 21 | format = f; 22 | cursor = 0; 23 | len = (arr == NULL) ? 0 : length; 24 | buf = arr; 25 | } 26 | // TODO: call prev constructor 27 | ParseByteStream::ParseByteStream(const char * arr, encoding_format f){ 28 | last = -1; 29 | format = f; 30 | cursor = 0; 31 | len = (arr == NULL) ? 0 : strlen(arr); 32 | buf = (const uint8_t *) arr; 33 | } 34 | ParseByteStream::~ParseByteStream(){ 35 | buf = NULL; 36 | } 37 | size_t ParseByteStream::available(){ 38 | if(format == HEX_ENCODING){ 39 | return (len - cursor)/2; 40 | }else{ 41 | return len-cursor; 42 | } 43 | }; 44 | int ParseByteStream::read(){ 45 | if(format == HEX_ENCODING){ 46 | if(cursor < len-1){ 47 | uint8_t c1 = hexToVal(buf[cursor]); 48 | uint8_t c2 = hexToVal(buf[cursor+1]); 49 | if(c1 < 0x10 && c2 < 0x10){ 50 | cursor +=2; 51 | last = (c1<<4) + c2; 52 | return last; 53 | } 54 | } 55 | }else{ 56 | if(cursor < len){ 57 | uint8_t c = buf[cursor]; 58 | cursor ++; 59 | last = c; 60 | return c; 61 | } 62 | } 63 | return -1; 64 | } 65 | int ParseByteStream::getLast(){ 66 | return last; 67 | } 68 | size_t ParseByteStream::read(uint8_t *arr, size_t length){ 69 | size_t cc = 0; 70 | while(cc 0){ 101 | if(format == HEX_ENCODING){ 102 | buf[cursor] = ((b >> 4) & 0x0F) + '0'; 103 | if(buf[cursor] > '9'){ 104 | buf[cursor] += 'a'-'9'-1; 105 | } 106 | cursor++; 107 | buf[cursor] = (b & 0x0F) + '0'; 108 | if(buf[cursor] > '9'){ 109 | buf[cursor] += 'a'-'9'-1; 110 | } 111 | cursor++; 112 | }else{ 113 | buf[cursor] = b; 114 | cursor++; 115 | } 116 | return 1; 117 | } 118 | return 0; 119 | }; 120 | size_t SerializeByteStream::write(const uint8_t *arr, size_t length){ 121 | size_t l = 0; 122 | while(available()>0 && l < length){ 123 | write(arr[l]); 124 | l++; 125 | } 126 | return l; 127 | }; 128 | 129 | /************ Readable Class ************/ 130 | 131 | #ifdef ARDUINO 132 | size_t Readable::printTo(Print& p) const{ 133 | size_t len = this->stringLength()+1; 134 | char * arr = (char *)calloc(len, sizeof(char)); 135 | toString(arr, len); 136 | p.print(arr); 137 | free(arr); 138 | return len-1; 139 | } 140 | #endif 141 | #if USE_ARDUINO_STRING || USE_STD_STRING 142 | String Readable::toString() const{ 143 | size_t len = this->stringLength()+1; 144 | char * arr = (char *)calloc(len, sizeof(char)); 145 | toString(arr, len); 146 | String s = arr; 147 | free(arr); 148 | return s; 149 | }; 150 | #endif 151 | 152 | /************ Streamable Class ************/ 153 | 154 | #if USE_ARDUINO_STRING || USE_STD_STRING 155 | String Streamable::serialize(size_t offset, size_t len) const{ 156 | if(len == 0){ 157 | len = (length()-offset); 158 | } 159 | char * arr = (char *)calloc(2*len+1, sizeof(char)); 160 | serialize(arr, 2*len, offset, HEX_ENCODING); 161 | String s = arr; 162 | free(arr); 163 | return s; 164 | }; 165 | #endif 166 | 167 | size_t Streamable::serialize(uint8_t * arr, size_t len, size_t offset, encoding_format format) const{ 168 | SerializeByteStream s(arr, len, format); 169 | return to_stream(&s, offset); 170 | } 171 | 172 | -------------------------------------------------------------------------------- /src/BaseClasses.h: -------------------------------------------------------------------------------- 1 | #ifndef __BITCOIN_BASE_CLASSES_H__ 2 | #define __BITCOIN_BASE_CLASSES_H__ 3 | 4 | #include "uBitcoin_conf.h" 5 | #include "Conversion.h" 6 | 7 | #include 8 | #include 9 | 10 | enum encoding_format{ 11 | RAW = 0, 12 | HEX_ENCODING = 16 13 | // TODO: would be nice to have base64 encoding here 14 | }; 15 | 16 | enum parse_status{ 17 | PARSING_DONE = 0, 18 | PARSING_INCOMPLETE = 1, 19 | PARSING_FAILED = 2 20 | }; 21 | // error codes struct / class? 22 | 23 | class Streamable; 24 | 25 | class ParseStream{ 26 | public: 27 | virtual size_t available(){ return 0; }; 28 | virtual int read(){ return -1; }; 29 | virtual size_t read(uint8_t *arr, size_t length){ return 0; }; 30 | virtual int getLast(){ return -1; }; 31 | size_t parse(Streamable * s); 32 | }; 33 | 34 | // TODO: skip leading non-hex if it's hex format 35 | class ParseByteStream: public ParseStream{ 36 | private: 37 | const uint8_t * buf; 38 | size_t cursor; 39 | size_t len; 40 | encoding_format format; 41 | int last; 42 | public: 43 | ParseByteStream(const uint8_t * arr, size_t length, encoding_format f=RAW); 44 | ParseByteStream(const char * arr, encoding_format f=HEX_ENCODING); 45 | ~ParseByteStream(); 46 | size_t available(); 47 | int read(); 48 | size_t read(uint8_t *arr, size_t length); 49 | virtual int getLast(); 50 | }; 51 | 52 | class SerializeStream{ 53 | public: 54 | virtual size_t available(){ return 0; }; 55 | virtual size_t write(uint8_t b){ return 0; }; 56 | virtual size_t write(const uint8_t *arr, size_t len){ return 0; }; 57 | size_t serialize(const Streamable * s, size_t offset); 58 | }; 59 | 60 | class SerializeByteStream: public SerializeStream{ 61 | private: 62 | uint8_t * buf; 63 | size_t cursor; 64 | size_t len; 65 | encoding_format format; 66 | public: 67 | SerializeByteStream(uint8_t * arr, size_t length, encoding_format f=RAW); 68 | explicit SerializeByteStream(char * arr, size_t length, encoding_format f=HEX_ENCODING); 69 | size_t available(); 70 | size_t write(uint8_t b); 71 | size_t write(const uint8_t *arr, size_t length); 72 | }; 73 | 74 | /** Abstract Readable class that can be encoded as a string and displayed to the user 75 | * Can be converted to and from a string (char *, Arduino String and std::string) 76 | * In Arduino it can be directly printed to the serial port, display or other Print device 77 | */ 78 | #ifdef ARDUINO 79 | class Readable: public Printable{ 80 | #else 81 | class Readable{ 82 | #endif 83 | private: 84 | protected: 85 | /* override these functions in your class */ 86 | virtual size_t to_str(char * buf, size_t len) const = 0; 87 | virtual size_t from_str(const char * buf, size_t len) = 0; 88 | public: 89 | /* override these function in your class */ 90 | virtual size_t stringLength() const = 0; 91 | 92 | size_t toString(char * buf, size_t len) const{ return this->to_str(buf, len); }; 93 | size_t fromString(const char * buf, size_t len){ return this->from_str(buf, len); }; 94 | size_t fromString(const char * buf){ return this->from_str(buf, strlen(buf)); }; 95 | #ifdef ARDUINO 96 | size_t printTo(Print& p) const; 97 | #endif 98 | #if USE_ARDUINO_STRING 99 | String toString() const; 100 | operator String(){ return this->toString(); }; 101 | #endif 102 | #if USE_STD_STRING 103 | std::string toString() const; 104 | operator std::string(){ return this->toString(); }; 105 | #endif 106 | }; 107 | 108 | /** Abstract Streamable class that can be serialized to/from a sequence of bytes 109 | * and sent to Stream (File, Serial, Bluetooth) without allocating extra memory 110 | * Class can be parsed and serialized in raw and hex formats 111 | */ 112 | class Streamable: public Readable{ 113 | friend class SerializeStream; 114 | friend class ParseStream; 115 | private: 116 | protected: 117 | virtual size_t from_stream(ParseStream *s) = 0; 118 | virtual size_t to_stream(SerializeStream *s, size_t offset) const = 0; 119 | virtual size_t to_str(char * buf, size_t len) const{ 120 | return serialize(buf, len); 121 | } 122 | virtual size_t from_str(const char * buf, size_t len){ 123 | return parse(buf, len); 124 | } 125 | parse_status status; 126 | size_t bytes_parsed; 127 | public: 128 | Streamable() { status = PARSING_DONE; bytes_parsed = 0; }; 129 | virtual void reset(){ status = PARSING_DONE; bytes_parsed = 0; }; // used to reset parsing and mb object 130 | virtual size_t length() const = 0; 131 | virtual size_t stringLength() const{ return 2*length(); }; 132 | /** \brief Gets parsing status. 133 | * PARSING_DONE - everything is ok, 134 | * PARSING_INCOMPLETE - some data is still missing 135 | * PARSING_FAILED - something went wrong, the data is probably incorrect. 136 | */ 137 | parse_status getStatus(){ return status; }; 138 | /** \brief Sets parsing status. Should be used with care. */ 139 | void setStatus(parse_status s){ status = s; }; 140 | size_t parse(const uint8_t * arr, size_t len, encoding_format format=RAW){ 141 | ParseByteStream s(arr, len, format); 142 | return from_stream(&s); 143 | } 144 | #if USE_ARDUINO_STRING 145 | size_t parse(String arr, encoding_format format=HEX_ENCODING){ 146 | return parse(arr.c_str(), strlen(arr.c_str()), format); 147 | } 148 | #endif 149 | #if USE_STD_STRING 150 | size_t parse(std::string arr, encoding_format format=HEX_ENCODING){ 151 | return parse(arr.c_str(), strlen(arr.c_str()), format); 152 | } 153 | #endif 154 | #if !(USE_ARDUINO_STRING || USE_STD_STRING) 155 | size_t parse(const char * arr, encoding_format format=HEX_ENCODING){ 156 | return parse(arr, strlen(arr), format); 157 | } 158 | #endif 159 | size_t serialize(uint8_t * arr, size_t len, size_t offset = 0, encoding_format format=RAW) const; 160 | size_t parse(const char * arr, size_t len, encoding_format format=HEX_ENCODING){ 161 | return parse((const uint8_t *) arr, len, format); 162 | } 163 | size_t serialize(char * arr, size_t len, size_t offset = 0, encoding_format format=HEX_ENCODING) const{ 164 | return serialize((uint8_t *)arr, len, offset, format); 165 | } 166 | #if USE_ARDUINO_STRING 167 | String serialize(size_t offset=0, size_t len=0) const; 168 | #endif 169 | #if USE_STD_STRING 170 | std::string serialize(size_t offset=0, size_t len=0) const; 171 | std::string serialize(int offset, int len) const{ 172 | return serialize((size_t)offset, (size_t)len); 173 | }; 174 | std::string serialize(size_t offset, int len) const{ 175 | return serialize((size_t)offset, (size_t)len); 176 | }; 177 | #endif 178 | }; 179 | 180 | #endif // __BITCOIN_BASE_CLASSES_H__ 181 | -------------------------------------------------------------------------------- /src/BitcoinCurve.cpp: -------------------------------------------------------------------------------- 1 | #include "BitcoinCurve.h" 2 | #include "Conversion.h" 3 | #include "utility/trezor/rfc6979.h" 4 | #include "utility/trezor/ecdsa.h" 5 | #include "utility/trezor/secp256k1.h" 6 | 7 | const ECPoint InfinityPoint; 8 | const ECPoint GeneratorPoint("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"); 9 | 10 | size_t ECPoint::from_stream(ParseStream *s){ 11 | static uint8_t first_byte; 12 | if(status == PARSING_FAILED){ 13 | return 0; 14 | } 15 | if(status == PARSING_DONE){ 16 | bytes_parsed = 0; 17 | } 18 | status = PARSING_INCOMPLETE; 19 | size_t bytes_to_read = 33; 20 | size_t bytes_read = 0; 21 | if(bytes_parsed > 0){ // we already know if it's compressed or not 22 | bytes_to_read = ECPoint::length()-bytes_parsed; 23 | }else{ 24 | if(s->available()){ 25 | uint8_t c = s->read(); 26 | bytes_read++; bytes_to_read--; 27 | if(c < 0x02 || c > 0x04){ 28 | status = PARSING_FAILED; 29 | bytes_parsed += bytes_read; 30 | return bytes_read; 31 | } 32 | first_byte = c; 33 | if(c == 0x04){ // uncompressed 34 | bytes_to_read += 32; 35 | compressed = false; 36 | }else{ 37 | compressed = true; 38 | } 39 | } 40 | } 41 | while(s->available() && bytes_to_read > 0){ // actual data 42 | point[bytes_parsed+bytes_read-1] = s->read(); 43 | bytes_read++; bytes_to_read--; 44 | } 45 | if(bytes_to_read==0){ 46 | if(compressed){ 47 | uint8_t buf[33]; 48 | buf[0] = first_byte; 49 | memcpy(buf+1, point, 32); 50 | uint8_t arr[65]; 51 | ecdsa_uncompress_pubkey(&secp256k1, buf, arr); 52 | memcpy(point, arr+1, 64); 53 | } 54 | status = PARSING_DONE; 55 | if(!ECPoint::isValid()){ 56 | status = PARSING_FAILED; 57 | } 58 | } 59 | bytes_parsed += bytes_read; 60 | return bytes_read; 61 | } 62 | size_t ECPoint::to_stream(SerializeStream *s, size_t offset) const{ 63 | size_t bytes_written = 0; 64 | if(!s->available()){ 65 | return 0; 66 | } 67 | if(offset == 0){ 68 | if(compressed){ 69 | s->write(0x02 + (point[63] & 0x01)); 70 | }else{ 71 | s->write(0x04); 72 | } 73 | bytes_written ++; 74 | offset++; 75 | } 76 | while(s->available() > 0 && offset < ECPoint::length()){ 77 | s->write(point[offset-1]); 78 | offset++; bytes_written++; 79 | } 80 | return bytes_written; 81 | } 82 | size_t ECPoint::sec(uint8_t * arr, size_t len) const{ 83 | SerializeByteStream s(arr, len); 84 | return ECPoint::to_stream(&s); 85 | } 86 | size_t ECPoint::fromSec(const uint8_t * arr, size_t len){ 87 | ParseByteStream s(arr, len); 88 | return ECPoint::from_stream(&s); 89 | } 90 | 91 | ECPoint::ECPoint(const uint8_t pubkeyArr[64], bool use_compressed){ 92 | memcpy(point, pubkeyArr, 64); 93 | compressed = use_compressed; 94 | }; 95 | ECPoint::ECPoint(const uint8_t * secArr){ 96 | if(secArr[0] == 0x04){ 97 | ECPoint::fromSec(secArr, 65); 98 | }else{ 99 | ECPoint::fromSec(secArr, 33); 100 | } 101 | }; 102 | ECPoint::ECPoint(const char * arr){ 103 | reset(); 104 | ECPoint::parse(arr, strlen(arr)); 105 | }; 106 | 107 | // bool verify(const Signature sig, const uint8_t hash[32]) const; 108 | bool ECPoint::isValid() const{ 109 | if(status != PARSING_DONE){ 110 | return false; 111 | } 112 | curve_point pub; 113 | uint8_t buf[65]; 114 | sec(buf, 65); 115 | return ecdsa_read_pubkey(&secp256k1, buf, &pub); 116 | }; 117 | bool ECPoint::isEven() const{ 118 | return !bool(point[63] & 0x01); 119 | }; 120 | 121 | ECPoint ECPoint::operator+(const ECPoint& other) const{ 122 | if(*this == InfinityPoint){ 123 | return other; 124 | } 125 | if(other == InfinityPoint){ 126 | return *this; 127 | } 128 | curve_point p1, p2; 129 | uint8_t buf[65]; 130 | sec(buf, 65); 131 | ecdsa_read_pubkey(&secp256k1, buf, &p1); 132 | other.sec(buf, 65); 133 | ecdsa_read_pubkey(&secp256k1, buf, &p2); 134 | point_add(&secp256k1,&p1,&p2); 135 | ECPoint sum; 136 | bn_write_be(&p2.x, sum.point); 137 | bn_write_be(&p2.y, sum.point+32); 138 | return sum; 139 | }; 140 | ECPoint ECPoint::operator-() const{ 141 | if(*this == InfinityPoint){ 142 | return *this; 143 | } 144 | uint8_t buf[33]; 145 | x(buf+1, 32); 146 | if(isEven()){ 147 | buf[0] = 0x03; 148 | }else{ 149 | buf[0] = 0x02; 150 | } 151 | ECPoint a; 152 | a.fromSec(buf, 33); 153 | a.compressed = compressed; 154 | return a; 155 | } 156 | ECPoint ECPoint::operator-(const ECPoint& other) const{ 157 | ECPoint a = -other; 158 | return *this+a; 159 | } 160 | 161 | /*********** ECScalar ******************/ 162 | 163 | size_t ECScalar::from_stream(ParseStream *s){ 164 | if(status == PARSING_FAILED){ 165 | return 0; 166 | } 167 | if(status == PARSING_DONE){ 168 | bytes_parsed = 0; 169 | } 170 | status = PARSING_INCOMPLETE; 171 | size_t bytes_read = 0; 172 | while(s->available() > 0 && bytes_parsed+bytes_read < 32){ 173 | num[bytes_parsed+bytes_read] = s->read(); 174 | bytes_read++; 175 | } 176 | if(bytes_parsed+bytes_read == 32){ 177 | status = PARSING_DONE; 178 | uint8_t zero[32] = { 0 }; 179 | if(memcmp(num, zero, 32)==0){ // should we add something else here? 180 | status = PARSING_FAILED; 181 | } 182 | bignum256 n; 183 | bn_read_be(num, &n); 184 | bn_mod(&n, &secp256k1.order); 185 | bn_write_be(&n, num); 186 | } 187 | bytes_parsed += bytes_read; 188 | return bytes_read; 189 | } 190 | size_t ECScalar::to_stream(SerializeStream *s, size_t offset) const{ 191 | size_t bytes_written = 0; 192 | while(s->available() && offset+bytes_written < 32){ 193 | s->write(num[bytes_written+offset]); 194 | bytes_written++; 195 | } 196 | return bytes_written; 197 | } 198 | ECScalar ECScalar::operator+(const ECScalar& other) const{ 199 | bignum256 a, b; 200 | bn_read_be(this->num, &a); 201 | bn_read_be(other.num, &b); 202 | bn_addmod(&a, &b, &secp256k1.order); 203 | bn_mod(&a, &secp256k1.order); 204 | ECScalar sum; 205 | bn_write_be(&a, sum.num); 206 | return sum; 207 | } 208 | ECScalar ECScalar::operator+(const uint32_t& i) const{ 209 | bignum256 a; 210 | bn_read_be(this->num, &a); 211 | bn_addi(&a, i); 212 | bn_mod(&a, &secp256k1.order); 213 | ECScalar sum; 214 | bn_write_be(&a, sum.num); 215 | return sum; 216 | } 217 | ECScalar ECScalar::operator-() const{ 218 | bignum256 a, b; 219 | bn_read_be(this->num, &a); 220 | bn_subtract(&secp256k1.order, &a, &b); 221 | ECScalar neg; 222 | bn_write_be(&b, neg.num); 223 | return neg; 224 | } 225 | ECScalar ECScalar::operator-(const uint32_t& i) const{ 226 | bignum256 a; 227 | bn_read_be(this->num, &a); 228 | bn_subi(&a, i, &secp256k1.order); 229 | bn_mod(&a, &secp256k1.order); 230 | ECScalar sum; 231 | bn_write_be(&a, sum.num); 232 | return sum; 233 | } 234 | ECScalar ECScalar::operator-(const ECScalar& other) const{ 235 | return (*this+(-other)); 236 | } 237 | ECScalar ECScalar::operator*(const ECScalar& other) const{ 238 | bignum256 a, b; 239 | bn_read_be(this->num, &a); 240 | bn_read_be(other.num, &b); 241 | bn_multiply(&b, &a, &secp256k1.order); 242 | bn_mod(&a, &secp256k1.order); 243 | ECScalar mul; 244 | bn_write_be(&a, mul.num); 245 | return mul; 246 | } 247 | ECScalar ECScalar::operator/(const ECScalar& other) const{ 248 | bignum256 a, b; 249 | bn_read_be(this->num, &a); 250 | bn_read_be(other.num, &b); 251 | bn_inverse(&b, &secp256k1.order); 252 | bn_multiply(&b, &a, &secp256k1.order); 253 | bn_mod(&a, &secp256k1.order); 254 | ECScalar res; 255 | bn_write_be(&a, res.num); 256 | return res; 257 | } 258 | bool ECScalar::operator<(const ECScalar& other) const{ 259 | bignum256 a,b; 260 | bn_read_be(num, &a); 261 | bn_read_be(other.num, &b); 262 | return bn_is_less(&a, &b); 263 | } 264 | bool ECPoint::operator<(const ECPoint& other) const{ 265 | uint8_t sec1[65]; 266 | uint8_t sec2[65]; 267 | sec(sec1, sizeof(sec1)); 268 | other.sec(sec2, sizeof(sec2)); 269 | return memcmp(sec1, sec2, sizeof(sec1)) > 0; 270 | } 271 | ECPoint operator*(const ECScalar& scalar, const ECPoint& point){ 272 | ECPoint r; 273 | uint8_t num[32]; 274 | scalar.getSecret(num); 275 | if(point == GeneratorPoint){ 276 | uint8_t pubkey[65]; 277 | ecdsa_get_public_key65(&secp256k1, num, pubkey); 278 | r.parse(pubkey, 65); 279 | }else{ 280 | bignum256 d; 281 | bn_read_be(num, &d); 282 | curve_point p, res; 283 | bn_read_be(point.point, &p.x); 284 | bn_read_be(point.point+32, &p.y); 285 | point_multiply(&secp256k1, &d, &p, &res); 286 | bn_write_be(&res.x, r.point); 287 | bn_write_be(&res.y, r.point+32); 288 | } 289 | r.compressed = point.compressed; 290 | return r; 291 | } 292 | -------------------------------------------------------------------------------- /src/BitcoinCurve.h: -------------------------------------------------------------------------------- 1 | #ifndef __BITCOIN_CURVE_H__ 2 | #define __BITCOIN_CURVE_H__ 3 | 4 | #include "uBitcoin_conf.h" 5 | #include "BaseClasses.h" 6 | #include "utility/trezor/memzero.h" 7 | #include "Conversion.h" 8 | 9 | class ECPoint : public Streamable{ 10 | protected: 11 | virtual size_t from_stream(ParseStream *s); 12 | virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const; 13 | public: 14 | uint8_t point[64]; // point on curve: (x,y) 15 | bool compressed; 16 | 17 | virtual void reset(){ bytes_parsed = 0; status=PARSING_DONE; memset(point, 0, 64); compressed = true; }; 18 | virtual size_t length() const{ return 33 + 32*(1-compressed); }; 19 | virtual size_t stringLength() const{ return 2*ECPoint::length(); }; 20 | 21 | ECPoint(){ reset(); }; 22 | ECPoint(const uint8_t pubkeyArr[64], bool use_compressed); 23 | ECPoint(const uint8_t * secArr); 24 | explicit ECPoint(const char * secHex); 25 | 26 | size_t sec(uint8_t * arr, size_t len) const; 27 | size_t fromSec(const uint8_t * arr, size_t len); 28 | /** \brief fills array with x coordinate of the point */ 29 | size_t x(uint8_t * arr, size_t len) const{ 30 | if(len < 32){ 31 | return 0; 32 | } 33 | memcpy(arr, point, 32); 34 | return 32; 35 | }; 36 | /** \brief parses x-only pubkey, from two possible points selects one with even y */ 37 | size_t from_x(const uint8_t * arr, size_t len){ 38 | if(len < 32){ 39 | return 0; 40 | } 41 | uint8_t sec[33] = {0x02}; 42 | memcpy(sec+1, arr, 32); 43 | return fromSec(sec, sizeof(sec)); 44 | } 45 | #if USE_ARDUINO_STRING 46 | String sec() const{ 47 | char arr[65*2+1] = ""; 48 | SerializeByteStream stream(arr, sizeof(arr)); 49 | ECPoint::to_stream(&stream); 50 | if(compressed){ 51 | arr[33*2+1] = 0; 52 | } 53 | String s(arr); 54 | return s; 55 | }; 56 | String x() const{ 57 | uint8_t arr[32]; 58 | x(arr, sizeof(arr)); 59 | return toHex(arr, sizeof(arr)); 60 | }; 61 | #endif 62 | #if USE_STD_STRING 63 | std::string sec() const{ 64 | char arr[65*2+1] = ""; 65 | SerializeByteStream stream(arr, sizeof(arr)); 66 | ECPoint::to_stream(&stream); 67 | if(compressed){ 68 | arr[33*2+1] = 0; 69 | } 70 | std::string s(arr); 71 | return s; 72 | }; 73 | std::string x() const{ 74 | uint8_t arr[32]; 75 | x(arr, sizeof(arr)); 76 | return toHex(arr, sizeof(arr)); 77 | }; 78 | #endif 79 | // bool verify(const Signature sig, const uint8_t hash[32]) const; 80 | virtual bool isValid() const; 81 | /** \brief checks if pubkey has even Y coordinate */ 82 | bool isEven() const; 83 | explicit operator bool() const { return isValid(); }; 84 | bool operator==(const ECPoint& other) const{ return (memcmp(point, other.point, 64) == 0); }; 85 | bool operator!=(const ECPoint& other) const{ return !operator==(other); }; 86 | 87 | ECPoint operator+(const ECPoint& other) const; 88 | ECPoint operator-() const; 89 | ECPoint operator-(const ECPoint& other) const; 90 | ECPoint operator+=(const ECPoint& other){ *this = *this+other; return *this; }; 91 | ECPoint operator-=(const ECPoint& other){ *this = *this-other; return *this; }; 92 | 93 | // sec-hex-comparison for multisig sorting 94 | bool operator<(const ECPoint& other) const; 95 | bool operator>(const ECPoint& other) const{ return (other<*this); }; 96 | bool operator>=(const ECPoint& other) const{ return !(*thisother); }; 98 | }; 99 | 100 | extern const ECPoint InfinityPoint; 101 | extern const ECPoint GeneratorPoint; 102 | 103 | class ECScalar : public Streamable{ 104 | protected: 105 | virtual size_t from_stream(ParseStream *s); 106 | virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const; 107 | uint8_t num[32]; // scalar mod secp526k1.order 108 | virtual void init(){ bytes_parsed = 0; status=PARSING_DONE; memzero(num, 32); }; 109 | public: 110 | virtual void reset(){ bytes_parsed = 0; status=PARSING_DONE; memzero(num, 32); }; 111 | virtual size_t length() const{ return 32; }; 112 | 113 | ECScalar(){ init(); }; 114 | ECScalar(const uint8_t * arr, size_t len){ init(); parse(arr, len); }; 115 | explicit ECScalar(const char * arr){ init(); parse(arr, strlen(arr)); }; 116 | ECScalar(uint32_t i){ init(); intToBigEndian(i, num, 32); }; 117 | ~ECScalar(){ memzero(num, 32); }; 118 | 119 | /** \brief Populates array with the secret key */ 120 | virtual void setSecret(const uint8_t secret_arr[32]){ memcpy(num, secret_arr, 32); }; 121 | /** \brief Sets the secret key */ 122 | void getSecret(uint8_t buffer[32]) const{ memcpy(buffer, num, 32); }; 123 | 124 | ECScalar operator+(const ECScalar& other) const; 125 | ECScalar operator+(const uint32_t& i) const; 126 | ECScalar operator-() const; 127 | ECScalar operator-(const ECScalar& other) const; 128 | ECScalar operator-(const uint32_t& i) const; 129 | ECScalar operator+=(const ECScalar& other){ *this = *this+other; return *this; }; 130 | ECScalar operator-=(const ECScalar& other){ *this = *this-other; return *this; }; 131 | ECScalar operator+=(const uint32_t& i){ *this = *this+i; return *this; }; 132 | ECScalar operator-=(const uint32_t& i){ *this = *this-i; return *this; }; 133 | 134 | ECScalar operator*(const ECScalar& other) const; 135 | ECScalar operator/(const ECScalar& other) const; 136 | ECScalar operator*=(const ECScalar& other){ *this = *this*other; return *this; }; 137 | ECScalar operator/=(const ECScalar& other){ *this = *this/other; return *this; }; 138 | 139 | virtual bool isValid() const{ uint8_t arr[32] = { 0 }; return (memcmp(num, arr, 32) != 0); }; 140 | explicit operator bool() const { return isValid(); }; 141 | bool operator==(const ECScalar& other) const{ return (memcmp(num, other.num, 32) == 0); }; 142 | bool operator!=(const ECScalar& other) const{ return !operator==(other); }; 143 | bool operator<(const ECScalar& other) const; 144 | bool operator>(const ECScalar& other) const{ return (other<*this); }; 145 | bool operator>=(const ECScalar& other) const{ return !(*thisother); }; 147 | }; 148 | 149 | inline ECScalar operator/(uint32_t i, ECScalar& scalar){ return ECScalar(i) / scalar; }; 150 | inline ECScalar operator/(ECScalar& scalar, uint32_t i){ return scalar / ECScalar(i); }; 151 | inline ECScalar operator*(uint32_t i, ECScalar& scalar){ return ECScalar(i) * scalar; }; 152 | inline ECScalar operator*(ECScalar& scalar, uint32_t i){ return scalar * ECScalar(i); }; 153 | inline ECScalar operator+(uint32_t i, ECScalar& scalar){ return ECScalar(i) + scalar; }; 154 | inline ECScalar operator+(ECScalar& scalar, uint32_t i){ return scalar + ECScalar(i); }; 155 | inline ECScalar operator-(uint32_t i, ECScalar& scalar){ return ECScalar(i) - scalar; }; 156 | inline ECScalar operator-(ECScalar& scalar, uint32_t i){ return scalar - ECScalar(i); }; 157 | 158 | ECPoint operator*(const ECScalar& d, const ECPoint& p); 159 | inline ECPoint operator*(const ECPoint& p, const ECScalar& d){ return d*p; }; 160 | inline ECPoint operator/(const ECPoint& p, const ECScalar& d){ return (ECScalar(1)/d)*p; }; 161 | 162 | #endif // __BITCOIN_CURVE_H__ 163 | -------------------------------------------------------------------------------- /src/Conversion.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONVERSION_H__ 2 | #define __CONVERSION_H__ 3 | 4 | #include "uBitcoin_conf.h" 5 | 6 | #include 7 | #include 8 | #include "utility/segwit_addr.h" 9 | 10 | 11 | #define BASE64_STANDARD 0 12 | #define BASE64_NOPADDING 1 13 | #define BASE64_URLSAFE 2 14 | 15 | // TODO: get rid of these blahLength functions, they are redundant 16 | // just stop when array is full and return errorcode 17 | 18 | size_t toBase58Length(const uint8_t * array, size_t arraySize); 19 | size_t toBase58(const uint8_t * array, size_t arraySize, char * output, size_t outputSize); 20 | #if USE_ARDUINO_STRING 21 | String toBase58(const uint8_t * array, size_t arraySize); 22 | #endif 23 | #if USE_STD_STRING 24 | std::string toBase58(const uint8_t * array, size_t arraySize); 25 | #endif 26 | 27 | 28 | // base58 conversion with 4-byte checksum at the end (doubleSha) 29 | size_t toBase58Check(const uint8_t * array, size_t arraySize, char * output, size_t outputSize); 30 | #if USE_ARDUINO_STRING 31 | String toBase58Check(const uint8_t * array, size_t arraySize); 32 | #endif 33 | #if USE_STD_STRING 34 | std::string toBase58Check(const uint8_t * array, size_t arraySize); 35 | #endif 36 | 37 | size_t fromBase58Length(const char * array, size_t arraySize); 38 | size_t fromBase58(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize); 39 | size_t fromBase58Check(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize); 40 | #if !(USE_ARDUINO_STRING || USE_STD_STRING) 41 | size_t fromBase58(const char * encoded, uint8_t * array, size_t arraySize); 42 | size_t fromBase58Check(const char * encoded, uint8_t * array, size_t arraySize); 43 | #endif 44 | #if USE_ARDUINO_STRING 45 | size_t fromBase58(String encoded, uint8_t * output, size_t outputSize); 46 | size_t fromBase58Check(String encoded, uint8_t * output, size_t outputSize); 47 | #endif 48 | #if USE_STD_STRING 49 | size_t fromBase58(std::string encoded, uint8_t * output, size_t outputSize); 50 | size_t fromBase58Check(std::string encoded, uint8_t * output, size_t outputSize); 51 | #endif 52 | 53 | size_t toBase43Length(const uint8_t * array, size_t arraySize); 54 | size_t toBase43(const uint8_t * array, size_t arraySize, char * output, size_t outputSize); 55 | #if USE_ARDUINO_STRING 56 | String toBase43(const uint8_t * array, size_t arraySize); 57 | #endif 58 | #if USE_STD_STRING 59 | std::string toBase43(const uint8_t * array, size_t arraySize); 60 | #endif 61 | size_t fromBase43Length(const char * array, size_t arraySize); 62 | size_t fromBase43(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize); 63 | #if !(USE_ARDUINO_STRING || USE_STD_STRING) 64 | size_t fromBase43(const char * encoded, uint8_t * array, size_t arraySize); 65 | #endif 66 | #if USE_ARDUINO_STRING 67 | size_t fromBase43(String encoded, uint8_t * output, size_t outputSize); 68 | #endif 69 | #if USE_STD_STRING 70 | size_t fromBase43(std::string encoded, uint8_t * output, size_t outputSize); 71 | #endif 72 | 73 | size_t toHex(const uint8_t * array, size_t arraySize, char * output, size_t outputSize); 74 | #if USE_ARDUINO_STRING 75 | String toHex(const uint8_t * array, size_t arraySize); 76 | size_t toHex(uint8_t v, Print &s); // printing single hex value to Print 77 | size_t toHex(const uint8_t * array, size_t arraySize, Print &s); // TODO: pass pointer instead printing array in hex Print 78 | #endif 79 | #if USE_STD_STRING 80 | std::string toHex(const uint8_t * array, size_t arraySize); 81 | #endif 82 | size_t fromHex(const char * hex, size_t hexLen, uint8_t * array, size_t arraySize); 83 | uint8_t hexToVal(char c); 84 | #if !(USE_ARDUINO_STRING || USE_STD_STRING) 85 | size_t fromHex(const char * hex, uint8_t * array, size_t arraySize); 86 | #endif 87 | #if USE_ARDUINO_STRING 88 | size_t fromHex(String encoded, uint8_t * output, size_t outputSize); 89 | #endif 90 | #if USE_STD_STRING 91 | size_t fromHex(std::string encoded, uint8_t * output, size_t outputSize); 92 | #endif 93 | 94 | size_t toBin(const uint8_t * array, size_t arraySize, char * output, size_t outputSize); 95 | #if USE_ARDUINO_STRING 96 | String toBin(const uint8_t * array, size_t arraySize); 97 | size_t toBin(uint8_t v, Print &s); // printing single value to Print 98 | size_t toBin(const uint8_t * array, size_t arraySize, Print &s); 99 | #endif 100 | #if USE_STD_STRING 101 | std::string toBin(const uint8_t * array, size_t arraySize); 102 | #endif 103 | size_t fromBin(const char * bin, size_t binLen, uint8_t * array, size_t arraySize); 104 | #if !(USE_ARDUINO_STRING || USE_STD_STRING) 105 | size_t fromBin(const char * hex, uint8_t * array, size_t arraySize); 106 | #endif 107 | #if USE_ARDUINO_STRING 108 | size_t fromBin(String encoded, uint8_t * output, size_t outputSize); 109 | #endif 110 | #if USE_STD_STRING 111 | size_t fromBin(std::string encoded, uint8_t * output, size_t outputSize); 112 | #endif 113 | 114 | size_t toBase64Length(const uint8_t * array, size_t arraySize, uint8_t flags = BASE64_STANDARD); 115 | size_t toBase64(const uint8_t * array, size_t arraySize, char * output, size_t outputSize, uint8_t flags = BASE64_STANDARD); 116 | #if USE_ARDUINO_STRING 117 | String toBase64(const uint8_t * array, size_t arraySize, uint8_t flags = BASE64_STANDARD); 118 | #endif 119 | #if USE_STD_STRING 120 | std::string toBase64(const uint8_t * array, size_t arraySize, uint8_t flags = BASE64_STANDARD); 121 | #endif 122 | size_t fromBase64Length(const char * array, size_t arraySize, uint8_t flags = BASE64_STANDARD); 123 | size_t fromBase64(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize, uint8_t flags = BASE64_STANDARD); 124 | #if !(USE_ARDUINO_STRING || USE_STD_STRING) 125 | size_t fromBase64(const char * encoded, uint8_t * array, size_t arraySize, uint8_t flags = BASE64_STANDARD); 126 | #endif 127 | #if USE_ARDUINO_STRING 128 | size_t fromBase64(String encoded, uint8_t * output, size_t outputSize, uint8_t flags = BASE64_STANDARD); 129 | String base64ToHex(String b64, uint8_t flags = BASE64_STANDARD); 130 | String hexToBase64(String hex, uint8_t flags = BASE64_STANDARD); 131 | #endif 132 | #if USE_STD_STRING 133 | size_t fromBase64(std::string encoded, uint8_t * output, size_t outputSize, uint8_t flags = BASE64_STANDARD); 134 | std::string base64ToHex(std::string b64, uint8_t flags = BASE64_STANDARD); 135 | std::string hexToBase64(std::string hex, uint8_t flags = BASE64_STANDARD); 136 | #endif 137 | 138 | /* int conversion */ 139 | uint64_t littleEndianToInt(const uint8_t * array, size_t arraySize); 140 | void intToLittleEndian(uint64_t num, uint8_t * array, size_t arraySize); 141 | uint64_t bigEndianToInt(const uint8_t * array, size_t arraySize); 142 | void intToBigEndian(uint64_t num, uint8_t * array, size_t arraySize); 143 | 144 | /* varint */ 145 | uint8_t lenVarInt(uint64_t num); // returns length of the array required for varint encoding 146 | uint64_t readVarInt(const uint8_t * array, size_t arraySize); 147 | size_t writeVarInt(uint64_t num, uint8_t * array, size_t arraySize); 148 | 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /src/Electrum.cpp: -------------------------------------------------------------------------------- 1 | #include "Electrum.h" 2 | 3 | ElectrumTx::ElectrumTx(ElectrumTx const &other){ 4 | tx = other.tx; 5 | is_segwit = false; 6 | txInsMeta = new ElectrumInputMetadata[tx.inputsNumber]; 7 | for(unsigned int i=0; i 0){ 16 | delete [] txInsMeta; 17 | } 18 | tx = other.tx; 19 | txInsMeta = new ElectrumInputMetadata[tx.inputsNumber]; 20 | for(unsigned int i=0; i 0){ 34 | delete [] txInsMeta; 35 | } 36 | txInsMeta = NULL; 37 | tx = Tx(); 38 | bytes_parsed = 0; 39 | is_segwit = false; 40 | } 41 | status = PARSING_INCOMPLETE; 42 | size_t bytes_read = 0; 43 | uint8_t prefix[] = {0x45, 0x50, 0x54, 0x46, 0xFF, 0x00}; 44 | while(s->available() && bytes_read+bytes_parsed<6){ 45 | uint8_t c = s->read(); 46 | bytes_read++; 47 | if(c != prefix[bytes_read+bytes_parsed-1]){ 48 | status = PARSING_FAILED; 49 | bytes_parsed += bytes_read; 50 | return bytes_read; 51 | } 52 | } 53 | if(!is_segwit && s->available() && status == PARSING_INCOMPLETE && tx.getStatus() != PARSING_FAILED){ 54 | bytes_read += s->parse(&tx); 55 | if(tx.getStatus() == PARSING_DONE){ 56 | status = PARSING_DONE; 57 | is_segwit = false; 58 | txInsMeta = new ElectrumInputMetadata[tx.inputsNumber]; 59 | for(unsigned i=0; i 0 && tx.txIns[0].witness.getStatus() == PARSING_FAILED){ 82 | for(unsigned int i=0; iavailable() && bytes_parsed+bytes_read < start + 5){ 104 | s->read(); 105 | bytes_read++; 106 | } 107 | start += 5; 108 | while(s->available() && bytes_parsed+bytes_read < start + 8){ 109 | uint8_t c = s->read(); 110 | txInsMeta[i].amount += (((uint64_t)c) << (8*(bytes_read+bytes_parsed-start))); 111 | bytes_read++; 112 | } 113 | start += 8; 114 | while(s->available() && bytes_parsed+bytes_read < start + 7){ 115 | s->read(); 116 | bytes_read++; 117 | } 118 | start += 7; 119 | while(s->available() && bytes_parsed+bytes_read < start + 78){ 120 | bytes_read+=s->parse(&txInsMeta[i].hd); 121 | } 122 | start += 78; 123 | while(s->available() && bytes_parsed+bytes_read < start + 4){ 124 | uint8_t c = s->read(); 125 | size_t cur = bytes_parsed+bytes_read-start; 126 | txInsMeta[i].derivation[cur/2] += (c << (8 * (cur % 2))); 127 | bytes_read++; 128 | } 129 | start += 4; 130 | } 131 | while(s->available() && bytes_parsed+bytes_read < start + 4){ 132 | uint8_t c = s->read(); 133 | tx.locktime += (c << (8*(bytes_read+bytes_parsed-start))); 134 | bytes_read++; 135 | } 136 | start+=4; 137 | if(bytes_parsed+bytes_read == start){ 138 | status = PARSING_DONE; 139 | } 140 | } 141 | bytes_parsed+=bytes_read; 142 | return bytes_read; 143 | } 144 | ElectrumTx::~ElectrumTx(){ 145 | delete [] txInsMeta; 146 | } 147 | uint8_t ElectrumTx::sign(const HDPrivateKey account){ 148 | uint8_t res = 0; // number of signed inputs 149 | for(unsigned int i=0; i 17 | * WARNING: Only partial support is implemented! No multisig and single keys.
18 | * For now implements only single HD key transactions are supported (no multisig).
19 | * If you explain me how electrum encodes unsigned multisig I will make it. 20 | */ 21 | class ElectrumTx : public Streamable{ 22 | protected: 23 | virtual size_t from_stream(ParseStream *s); 24 | virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const{ return s->serialize(&tx, offset); }; 25 | bool is_segwit; 26 | public: 27 | ElectrumTx(){ txInsMeta = NULL; is_segwit = false; }; 28 | ElectrumTx(ElectrumTx const &other); 29 | ~ElectrumTx(); 30 | Tx tx; 31 | virtual size_t length() const{ return tx.length(); }; 32 | 33 | /** \bried metadata for inputs */ 34 | ElectrumInputMetadata * txInsMeta; 35 | 36 | /** \brief signs all inputs with matching hd pubkey with account HDPrivateKey. 37 | * Returns number of inputs signed. 38 | */ 39 | uint8_t sign(const HDPrivateKey account); 40 | /** \brief calculates fee if input amounts are known */ 41 | uint64_t fee() const; 42 | 43 | ElectrumTx &operator=(ElectrumTx const &other); 44 | 45 | bool isValid() const{ return status==PARSING_DONE; }; 46 | explicit operator bool() const{ return isValid(); }; 47 | }; 48 | 49 | #endif // __ELECTRUM_H__ 50 | -------------------------------------------------------------------------------- /src/Hash.cpp: -------------------------------------------------------------------------------- 1 | #include "Hash.h" 2 | #include "utility/trezor/hmac.h" 3 | #include "utility/trezor/ripemd160.h" 4 | 5 | #if USE_STD_STRING 6 | using std::string; 7 | #define String string 8 | #endif 9 | 10 | // generic funtcions for single line hash 11 | static size_t hashData(HashAlgorithm * algo, const uint8_t * data, size_t len, uint8_t * hash){ 12 | algo->begin(); 13 | algo->write(data, len); 14 | return algo->end(hash); 15 | } 16 | 17 | #if USE_ARDUINO_STRING || USE_STD_STRING 18 | static size_t hashString(HashAlgorithm * algo, const String s, uint8_t * hash){ 19 | return hashData(algo, (const uint8_t *)s.c_str(), s.length(), hash); 20 | } 21 | #endif 22 | 23 | /************************* RIPEMD-160 *************************/ 24 | 25 | int rmd160(const uint8_t * data, size_t len, uint8_t hash[20]){ 26 | RMD160 rmd; 27 | return hashData(&rmd, data, len, hash); 28 | } 29 | int rmd160(const char * data, size_t len, uint8_t hash[20]){ 30 | return rmd160((uint8_t*)data, len, hash); 31 | } 32 | #if USE_ARDUINO_STRING || USE_STD_STRING 33 | int rmd160(const String data, uint8_t hash[20]){ 34 | RMD160 rmd; 35 | return hashString(&rmd, data, hash); 36 | } 37 | #endif 38 | 39 | void RMD160::begin(){ 40 | ripemd160_Init(&ctx); 41 | }; 42 | size_t RMD160::write(const uint8_t * data, size_t len){ 43 | ripemd160_Update(&ctx, data, len); 44 | return len; 45 | } 46 | size_t RMD160::write(uint8_t b){ 47 | uint8_t arr[1] = { b }; 48 | ripemd160_Update(&ctx, arr, 1); 49 | return 1; 50 | } 51 | size_t RMD160::end(uint8_t hash[20]){ 52 | ripemd160_Final(&ctx, hash); 53 | return 20; 54 | } 55 | 56 | /************************** SHA-256 **************************/ 57 | 58 | int sha256(const uint8_t * data, size_t len, uint8_t hash[32]){ 59 | SHA256 sha; 60 | return hashData(&sha, data, len, hash); 61 | } 62 | int sha256(const char * data, size_t len, uint8_t hash[32]){ 63 | return sha256((uint8_t*)data, len, hash); 64 | } 65 | #if USE_ARDUINO_STRING || USE_STD_STRING 66 | int sha256(const String data, uint8_t hash[32]){ 67 | SHA256 sha; 68 | return hashString(&sha, data, hash); 69 | } 70 | #endif 71 | 72 | TaggedHash::TaggedHash(const char * tag){ 73 | begin(); 74 | uint8_t th[32]; 75 | sha256(tag, strlen(tag), th); 76 | write(th, 32); 77 | write(th, 32); 78 | } 79 | 80 | int tagged_hash(const char * tag, const uint8_t * data, size_t dataLen, uint8_t hash[32]){ 81 | TaggedHash th(tag); 82 | return hashData(&th, data, dataLen, hash); 83 | } 84 | int tagged_hash(const char * tag, const char * data, size_t len, uint8_t hash[32]){ 85 | return tagged_hash(tag, (uint8_t*)data, len, hash); 86 | } 87 | #if USE_ARDUINO_STRING || USE_STD_STRING 88 | int tagged_hash(const String tag, const String data, uint8_t hash[32]){ 89 | TaggedHash th(tag.c_str()); 90 | return hashString(&th, data, hash); 91 | } 92 | #endif 93 | 94 | int sha256Hmac(const uint8_t * key, size_t keyLen, const uint8_t * data, size_t dataLen, uint8_t hash[32]){ 95 | ubtc_hmac_sha256(key, keyLen, data, dataLen, hash); 96 | return 32; 97 | } 98 | 99 | void SHA256::begin(){ 100 | sha256_Init(&ctx.ctx); 101 | } 102 | void SHA256::beginHMAC(const uint8_t * key, size_t keySize){ 103 | ubtc_hmac_sha256_Init(&ctx, key, keySize); 104 | } 105 | size_t SHA256::write(const uint8_t * data, size_t len){ 106 | sha256_Update(&ctx.ctx, data, len); 107 | return len; 108 | } 109 | size_t SHA256::write(uint8_t b){ 110 | uint8_t arr[1] = { b }; 111 | sha256_Update(&ctx.ctx, arr, 1); 112 | return 1; 113 | } 114 | size_t SHA256::end(uint8_t hash[32]){ 115 | sha256_Final(&ctx.ctx, hash); 116 | return 32; 117 | } 118 | size_t SHA256::endHMAC(uint8_t hmac[32]){ 119 | ubtc_hmac_sha256_Final(&ctx, hmac); 120 | return 32; 121 | } 122 | 123 | /************************* Hash-160 **************************/ 124 | /******************** rmd160( sha256( m ) ) ******************/ 125 | 126 | int hash160(const uint8_t * data, size_t len, uint8_t hash[20]){ 127 | Hash160 h160; 128 | return hashData(&h160, data, len, hash); 129 | } 130 | int hash160(const char * data, size_t len, uint8_t hash[20]){ 131 | return hash160((uint8_t*)data, len, hash); 132 | } 133 | #if USE_ARDUINO_STRING || USE_STD_STRING 134 | int hash160(const String data, uint8_t hash[20]){ 135 | Hash160 h160; 136 | return hashString(&h160, data, hash); 137 | } 138 | #endif 139 | 140 | size_t Hash160::end(uint8_t hash[20]){ 141 | uint8_t h[32]; 142 | sha256_Final(&ctx.ctx, h); 143 | rmd160(h, 32, hash); 144 | return 20; 145 | } 146 | 147 | /********************** Double SHA-256 ***********************/ 148 | /******************** sha256( sha256( m ) ) ******************/ 149 | 150 | int doubleSha(const uint8_t * data, size_t len, uint8_t hash[32]){ 151 | DoubleSha sha; 152 | return hashData(&sha, data, len, hash); 153 | } 154 | int doubleSha(const char * data, size_t len, uint8_t hash[32]){ 155 | return doubleSha((uint8_t*)data, len, hash); 156 | } 157 | #if USE_ARDUINO_STRING || USE_STD_STRING 158 | int doubleSha(const String data, uint8_t hash[32]){ 159 | DoubleSha sha; 160 | return hashString(&sha, data, hash); 161 | } 162 | #endif 163 | 164 | size_t DoubleSha::end(uint8_t hash[32]){ 165 | uint8_t h[32]; 166 | sha256_Final(&ctx.ctx, h); 167 | sha256(h, 32, hash); 168 | return 32; 169 | } 170 | 171 | /************************** SHA-512 **************************/ 172 | 173 | int sha512(const uint8_t * data, size_t len, uint8_t hash[64]){ 174 | SHA512 sha; 175 | return hashData(&sha, data, len, hash); 176 | } 177 | int sha512(const char * data, size_t len, uint8_t hash[64]){ 178 | return sha512((uint8_t*)data, len, hash); 179 | } 180 | #if USE_ARDUINO_STRING || USE_STD_STRING 181 | int sha512(const String data, uint8_t hash[64]){ 182 | SHA512 sha; 183 | return hashString(&sha, data, hash); 184 | } 185 | #endif 186 | 187 | void SHA512::begin(){ 188 | sha512_Init(&ctx.ctx); 189 | }; 190 | void SHA512::beginHMAC(const uint8_t * key, size_t keySize){ 191 | ubtc_hmac_sha512_Init(&ctx, key, keySize); 192 | } 193 | size_t SHA512::write(const uint8_t * data, size_t len){ 194 | sha512_Update(&ctx.ctx, data, len); 195 | return len; 196 | } 197 | size_t SHA512::write(uint8_t b){ 198 | uint8_t arr[1] = { b }; 199 | sha512_Update(&ctx.ctx, arr, 1); 200 | return 1; 201 | } 202 | size_t SHA512::end(uint8_t hash[64]){ 203 | sha512_Final(&ctx.ctx, hash); 204 | return 64; 205 | } 206 | size_t SHA512::endHMAC(uint8_t hmac[64]){ 207 | ubtc_hmac_sha512_Final(&ctx, hmac); 208 | return 64; 209 | } 210 | 211 | int sha512Hmac(const uint8_t * key, size_t keyLen, const uint8_t * data, size_t dataLen, uint8_t hash[64]){ 212 | ubtc_hmac_sha512(key, keyLen, data, dataLen, hash); 213 | return 64; 214 | } 215 | -------------------------------------------------------------------------------- /src/Hash.h: -------------------------------------------------------------------------------- 1 | /** @file Hash.h 2 | * \brief All hashing functions and classes live here 3 | */ 4 | #ifndef __HASH_H__18NLNNCSJ2 5 | #define __HASH_H__18NLNNCSJ2 6 | 7 | #include "uBitcoin_conf.h" 8 | #include "BaseClasses.h" 9 | #include 10 | #include 11 | #include "utility/trezor/sha2.h" 12 | #include "utility/trezor/ripemd160.h" 13 | #include "utility/trezor/hmac.h" 14 | 15 | /** \brief Abstract hashing class */ 16 | class HashAlgorithm : public SerializeStream{ 17 | public: 18 | size_t available(){ return 100; }; 19 | void begin(){}; 20 | virtual size_t write(const uint8_t * data, size_t len) = 0; 21 | virtual size_t write(uint8_t b) = 0; 22 | virtual size_t end(uint8_t * hash) = 0; 23 | }; 24 | 25 | /************************* RIPEMD-160 *************************/ 26 | 27 | /** \brief ripemd-160 one-line hashing function */ 28 | int rmd160(const uint8_t * data, size_t len, uint8_t hash[20]); 29 | int rmd160(const char * data, size_t len, uint8_t hash[20]); 30 | #if USE_ARDUINO_STRING 31 | int rmd160(const String data, uint8_t hash[20]); 32 | #endif 33 | #if USE_STD_STRING 34 | int rmd160(const std::string data, uint8_t hash[20]); 35 | #endif 36 | 37 | class RMD160 : public HashAlgorithm{ 38 | public: 39 | RMD160(){ begin(); }; 40 | void begin(); 41 | size_t write(const uint8_t * data, size_t len); 42 | size_t write(uint8_t b); 43 | size_t end(uint8_t hash[20]); 44 | protected: 45 | RIPEMD160_CTX ctx; 46 | }; 47 | 48 | /************************** SHA-256 **************************/ 49 | 50 | /** \brief sha256 one-line hashing function → 32 bytes output */ 51 | int sha256(const uint8_t * data, size_t len, uint8_t hash[32]); 52 | int sha256(const char * data, size_t len, uint8_t hash[32]); 53 | #if USE_ARDUINO_STRING 54 | int sha256(const String data, uint8_t hash[32]); 55 | #endif 56 | #if USE_STD_STRING 57 | int sha256(const std::string data, uint8_t hash[32]); 58 | #endif 59 | 60 | int sha256Hmac(const uint8_t * key, size_t keyLen, const uint8_t * data, size_t dataLen, uint8_t hash[32]); 61 | 62 | class SHA256 : public HashAlgorithm{ 63 | public: 64 | SHA256(){ begin(); }; 65 | void begin(); 66 | void beginHMAC(const uint8_t * key, size_t keySize); 67 | size_t write(const uint8_t * data, size_t len); 68 | size_t write(uint8_t b); 69 | size_t end(uint8_t hash[32]); 70 | size_t endHMAC(uint8_t hmac[32]); 71 | protected: 72 | HMAC_SHA256_CTX ctx; 73 | }; 74 | 75 | /************************ Tagged hash ************************/ 76 | 77 | /** \brief tagged hash class as defined in bip-schnorr (bip340) */ 78 | class TaggedHash : public SHA256{ 79 | public: 80 | TaggedHash(const char * tag); 81 | }; 82 | 83 | /** \brief tagged hash one-line hashing function → 32 bytes output */ 84 | int tagged_hash(const char * tag, const uint8_t * data, size_t dataLen, uint8_t hash[32]); 85 | int tagged_hash(const char * tag, const char * data, size_t dataLen, uint8_t hash[32]); 86 | #if USE_ARDUINO_STRING 87 | int tagged_hash(const String tag, const String data, uint8_t hash[32]); 88 | #endif 89 | #if USE_STD_STRING 90 | int tagged_hash(const std::string tag, const std::string data, uint8_t hash[32]); 91 | #endif 92 | 93 | 94 | /************************* Hash-160 **************************/ 95 | /******************** rmd160( sha256( m ) ) ******************/ 96 | 97 | /** \brief rmd160(sha256(data)) → 20 bytes output */ 98 | int hash160(const uint8_t * data, size_t len, uint8_t hash[20]); 99 | int hash160(const uint8_t * data, size_t len, uint8_t hash[20]); 100 | int hash160(const char * data, size_t len, uint8_t hash[20]); 101 | #if USE_ARDUINO_STRING 102 | int hash160(const String data, uint8_t hash[20]); 103 | #endif 104 | #if USE_STD_STRING 105 | int hash160(const std::string data, uint8_t hash[20]); 106 | #endif 107 | 108 | class Hash160 : public SHA256{ 109 | public: 110 | size_t end(uint8_t hash[20]); 111 | }; 112 | 113 | /********************** Double SHA-256 ***********************/ 114 | /******************** sha256( sha256( m ) ) ******************/ 115 | 116 | /** \brief sha256(sha256(data)) → 32 bytes output */ 117 | int doubleSha(const uint8_t * data, size_t len, uint8_t hash[32]); 118 | int doubleSha(const char * data, size_t len, uint8_t hash[32]); 119 | #if USE_ARDUINO_STRING 120 | int doubleSha(const String data, uint8_t hash[32]); 121 | #endif 122 | #if USE_STD_STRING 123 | int doubleSha(const std::string data, uint8_t hash[32]); 124 | #endif 125 | 126 | class DoubleSha : public SHA256{ 127 | public: 128 | size_t end(uint8_t hash[32]); 129 | }; 130 | 131 | /************************** SHA-512 **************************/ 132 | 133 | int sha512Hmac(const uint8_t * key, size_t keyLen, const uint8_t * data, size_t dataLen, uint8_t hash[64]); 134 | 135 | int sha512(const uint8_t * data, size_t len, uint8_t hash[64]); 136 | int sha512(const char * data, size_t len, uint8_t hash[64]); 137 | #if USE_ARDUINO_STRING 138 | int sha512(const String data, uint8_t hash[64]); 139 | #endif 140 | #if USE_STD_STRING 141 | int sha512(const std::string data, uint8_t hash[64]); 142 | #endif 143 | 144 | class SHA512 : public HashAlgorithm{ 145 | public: 146 | SHA512(){ begin(); }; 147 | void begin(); 148 | void beginHMAC(const uint8_t * key, size_t keySize); 149 | size_t write(const uint8_t * data, size_t len); 150 | size_t write(uint8_t b); 151 | size_t end(uint8_t hash[64]); 152 | size_t endHMAC(uint8_t hmac[64]); 153 | protected: 154 | HMAC_SHA512_CTX ctx; 155 | }; 156 | 157 | #endif // __HASH_H__18NLNNCSJ2 158 | -------------------------------------------------------------------------------- /src/Networks.cpp: -------------------------------------------------------------------------------- 1 | // all known networks 2 | #include "Networks.h" 3 | 4 | const Network Mainnet = { 5 | 0x00, // p2pkh 6 | 0x05, // p2sh 7 | "bc", // bech32 8 | 0x80, // wif 9 | { 0x04, 0x88, 0xad, 0xe4 }, // xprv 10 | { 0x04, 0x9d, 0x78, 0x78 }, // yprv 11 | { 0x04, 0xb2, 0x43, 0x0c }, // zprv 12 | { 0x02, 0x95, 0xb0, 0x05 }, // Yprv 13 | { 0x02, 0xaa, 0x7a, 0x99 }, // Zprv 14 | { 0x04, 0x88, 0xb2, 0x1e }, // xpub 15 | { 0x04, 0x9d, 0x7c, 0xb2 }, // ypub 16 | { 0x04, 0xb2, 0x47, 0x46 }, // zpub 17 | { 0x02, 0x95, 0xb4, 0x3f }, // Ypub 18 | { 0x02, 0xaa, 0x7e, 0xd3 }, // Zpub 19 | 0 // bip32 coin type 20 | }; 21 | 22 | const Network Testnet = { 23 | 0x6F, // p2pkh 24 | 0xC4, // p2sh 25 | "tb", // bech32 26 | 0xEF, // wif 27 | { 0x04, 0x35, 0x83, 0x94 }, // tprv 28 | { 0x04, 0x4a, 0x4e, 0x28 }, // uprv 29 | { 0x04, 0x5f, 0x18, 0xbc }, // vprv 30 | { 0x02, 0x42, 0x85, 0xb5 }, // Uprv 31 | { 0x02, 0x57, 0x50, 0x48 }, // Vprv 32 | { 0x04, 0x35, 0x87, 0xcf }, // tpub 33 | { 0x04, 0x4a, 0x52, 0x62 }, // upub 34 | { 0x04, 0x5f, 0x1c, 0xf6 }, // vpub 35 | { 0x02, 0x42, 0x89, 0xef }, // Upub 36 | { 0x02, 0x57, 0x54, 0x83 }, // Vpub 37 | 1 // bip32 coin type 38 | }; 39 | 40 | const Network Regtest = { 41 | 0x6F, // p2pkh 42 | 0xC4, // p2sh 43 | "bcrt", // bech32 44 | 0xEF, // wif 45 | { 0x04, 0x35, 0x83, 0x94 }, // tprv 46 | { 0x04, 0x4a, 0x4e, 0x28 }, // uprv 47 | { 0x04, 0x5f, 0x18, 0xbc }, // vprv 48 | { 0x02, 0x42, 0x85, 0xb5 }, // Uprv 49 | { 0x02, 0x57, 0x50, 0x48 }, // Vprv 50 | { 0x04, 0x35, 0x87, 0xcf }, // tpub 51 | { 0x04, 0x4a, 0x52, 0x62 }, // upub 52 | { 0x04, 0x5f, 0x1c, 0xf6 }, // vpub 53 | { 0x02, 0x42, 0x89, 0xef }, // Upub 54 | { 0x02, 0x57, 0x54, 0x83 }, // Vpub 55 | 1 // bip32 coin type 56 | }; 57 | 58 | // signet is the same as testnet 59 | const Network Signet = Testnet; 60 | 61 | const Network * networks[4] = { &Mainnet, &Testnet, &Regtest, &Signet }; 62 | const uint8_t networks_len = 4; 63 | -------------------------------------------------------------------------------- /src/Networks.h: -------------------------------------------------------------------------------- 1 | #ifndef __UBTC_NETWORKS_H__ 2 | #define __UBTC_NETWORKS_H__ 3 | 4 | #include 5 | 6 | /** \brief Prefixes for particular network (Mainnet / Testnet ).
7 | * HD key prefixes are described here:
8 | * https://github.com/satoshilabs/slips/blob/master/slip-0132.md
9 | * useful tool: in https://iancoleman.io/bip39/ 10 | */ 11 | typedef struct { 12 | /** \brief Pay-To-Pubkey-Hash addresses */ 13 | uint8_t p2pkh; 14 | /** \brief Pay-To-Script-Hash addresses */ 15 | uint8_t p2sh; 16 | /** \brief Prefix for segwit addreses ...for regtest it is larger */ 17 | char bech32[5]; 18 | /** \brief Wallet Import Format, used in PrivateKey */ 19 | uint8_t wif; 20 | /** \brief HD private key for legacy addresses (P2PKH) */ 21 | uint8_t xprv[4]; 22 | /** \brief HD private key for nested Segwit (P2SH-P2WPKH) */ 23 | uint8_t yprv[4]; 24 | /** \brief HD private key for native Segwit (P2WPKH) */ 25 | uint8_t zprv[4]; 26 | /** \brief HD private key for nested Segwit Multisig (P2SH-P2WSH) */ 27 | uint8_t Yprv[4]; 28 | /** \brief HD private key for native Segwit Multisig (P2WSH) */ 29 | uint8_t Zprv[4]; 30 | /** \brief HD public key for legacy addresses (P2PKH) */ 31 | uint8_t xpub[4]; 32 | /** \brief HD public key for nested Segwit (P2SH-P2WPKH) */ 33 | uint8_t ypub[4]; 34 | /** \brief HD public key for native Segwit (P2WPKH) */ 35 | uint8_t zpub[4]; 36 | /** \brief HD public key for nested Segwit Multisig (P2SH-P2WSH) */ 37 | uint8_t Ypub[4]; 38 | /** \brief HD public key for native Segwit Multisig (P2WSH) */ 39 | uint8_t Zpub[4]; 40 | /** \brief bip32 coin index */ 41 | uint32_t bip32; 42 | } Network; 43 | 44 | extern const Network Mainnet; 45 | extern const Network Testnet; 46 | extern const Network Regtest; 47 | extern const Network Signet; 48 | 49 | extern const Network * networks[]; 50 | extern const uint8_t networks_len; 51 | 52 | #endif // __UBTC_NETWORKS_H__ -------------------------------------------------------------------------------- /src/OpCodes.h: -------------------------------------------------------------------------------- 1 | #ifndef __OPCODES_H__R3NU8EN25O 2 | #define __OPCODES_H__R3NU8EN25O 3 | 4 | #include "uBitcoin_conf.h" 5 | 6 | // reference: https://en.bitcoin.it/wiki/Script#Opcodes 7 | 8 | // uncomment the following string to use disabled op-codes: 9 | // #define INCLUDE_DISABLED 10 | 11 | /* OP_CODES */ 12 | 13 | /* Constants */ 14 | 15 | #define OP_0 0 16 | #define OP_PUSHDATA1 76 17 | #define OP_PUSHDATA2 77 18 | #define OP_PUSHDATA4 78 19 | #define OP_1NEGATE 79 20 | #define OP_RESERVED 80 21 | #define OP_1 81 22 | #define OP_2 82 23 | #define OP_3 83 24 | #define OP_4 84 25 | #define OP_5 85 26 | #define OP_6 86 27 | #define OP_7 87 28 | #define OP_8 88 29 | #define OP_9 89 30 | #define OP_10 90 31 | #define OP_11 91 32 | #define OP_12 92 33 | #define OP_13 93 34 | #define OP_14 94 35 | #define OP_15 95 36 | #define OP_16 96 37 | 38 | /* Flow control */ 39 | 40 | #define OP_NOP 97 41 | #define OP_VER 98 42 | #define OP_IF 99 43 | #define OP_NOTIF 100 44 | #define OP_VERIF 101 45 | #define OP_VERNOTIF 102 46 | #define OP_ELSE 103 47 | #define OP_ENDIF 104 48 | #define OP_VERIFY 105 49 | #define OP_RETURN 106 50 | 51 | /* Stack */ 52 | 53 | #define OP_TOALTSTACK 107 54 | #define OP_FROMALTSTACK 108 55 | #define OP_2DROP 109 56 | #define OP_2DUP 110 57 | #define OP_3DUP 111 58 | #define OP_2OVER 112 59 | #define OP_2ROT 113 60 | #define OP_2SWAP 114 61 | #define OP_IFDUP 115 62 | #define OP_DEPTH 116 63 | #define OP_DROP 117 64 | #define OP_DUP 118 65 | #define OP_NIP 119 66 | #define OP_OVER 120 67 | #define OP_PICK 121 68 | #define OP_ROLL 122 69 | #define OP_ROT 123 70 | #define OP_SWAP 124 71 | #define OP_TUCK 125 72 | 73 | /* Splice */ 74 | 75 | #ifdef INCLUDE_DISABLED 76 | #define OP_CAT 126 77 | #define OP_SUBSTR 127 78 | #define OP_LEFT 128 79 | #define OP_RIGHT 129 80 | #endif 81 | 82 | #define OP_SIZE 130 83 | 84 | /* Bitwise logic */ 85 | 86 | #ifdef INCLUDE_DISABLED 87 | #define OP_INVERT 131 88 | #define OP_AND 132 89 | #define OP_OR 133 90 | #define OP_XOR 134 91 | #endif 92 | 93 | #define OP_EQUAL 135 94 | #define OP_EQUALVERIFY 136 95 | #define OP_RESERVED1 137 96 | #define OP_RESERVED2 138 97 | 98 | /* Arithmetic */ 99 | 100 | #define OP_1ADD 139 101 | #define OP_1SUB 140 102 | 103 | #ifdef INCLUDE_DISABLED 104 | #define OP_2MUL 141 105 | #define OP_2DIV 142 106 | #endif 107 | 108 | #define OP_NEGATE 143 109 | #define OP_ABS 144 110 | #define OP_NOT 145 111 | #define OP_0NOTEQUAL 146 112 | #define OP_ADD 147 113 | #define OP_SUB 148 114 | 115 | #ifdef INCLUDE_DISABLED 116 | #define OP_MUL 149 117 | #define OP_DIV 150 118 | #define OP_MOD 151 119 | #define OP_LSHIFT 152 120 | #define OP_RSHIFT 153 121 | #endif 122 | 123 | #define OP_BOOLAND 154 124 | #define OP_BOOLOR 155 125 | #define OP_NUMEQUAL 156 126 | #define OP_NUMEQUALVERIFY 157 127 | #define OP_NUMNOTEQUAL 158 128 | #define OP_LESSTHAN 159 129 | #define OP_GREATERTHAN 160 130 | #define OP_LESSTHANOREQUAL 161 131 | #define OP_GREATERTHANOREQUAL 162 132 | #define OP_MIN 163 133 | #define OP_MAX 164 134 | #define OP_WITHIN 165 135 | 136 | /* Crypto */ 137 | 138 | #define OP_RIPEMD160 166 139 | #define OP_SHA1 167 140 | #define OP_SHA256 168 141 | #define OP_HASH160 169 142 | #define OP_HASH256 170 143 | #define OP_CODESEPARATOR 171 144 | #define OP_CHECKSIG 172 145 | #define OP_CHECKSIGVERIFY 173 146 | #define OP_CHECKMULTISIG 174 147 | #define OP_CHECKMULTISIGVERIFY 175 148 | #define OP_NOP1 176 149 | 150 | /* Locktime */ 151 | 152 | #define OP_CHECKLOCKTIMEVERIFY 177 153 | #define OP_CHECKSEQUENCEVERIFY 178 154 | 155 | /* Reserved */ 156 | 157 | #define OP_NOP4 179 158 | #define OP_NOP5 180 159 | #define OP_NOP6 181 160 | #define OP_NOP7 182 161 | #define OP_NOP8 183 162 | #define OP_NOP9 184 163 | #define OP_NOP10 185 164 | #define OP_NULLDATA 252 165 | 166 | /* Pseudo-words 167 | * These opcodes are used internally 168 | * for assisting with transaction matching. 169 | * They are invalid if used in actual scripts. 170 | */ 171 | #define OP_PUBKEYHASH 253 172 | #define OP_PUBKEY 254 173 | #define OP_INVALIDOPCODE 255 174 | 175 | #endif /* __OPCODES_H__R3NU8EN25O */ -------------------------------------------------------------------------------- /src/PSBT.h: -------------------------------------------------------------------------------- 1 | #ifndef __PSBT_H__ 2 | #define __PSBT_H__ 3 | 4 | #include "Bitcoin.h" 5 | 6 | // TODO: 7 | // - SIGHASH types, and other key-value pairs that are still not implemented 8 | // - finalize() 9 | 10 | /** \brief Derivation information */ 11 | typedef struct{ 12 | /** \brief PublicKey that we are going to derive */ 13 | PublicKey pubkey; 14 | /** \brief Fingerprint of the root HD key */ 15 | uint8_t fingerprint[4]; 16 | /** \brief Derivation path */ 17 | uint32_t * derivation; 18 | uint8_t derivationLen; 19 | } PSBTDerivation; 20 | 21 | /** \brief Partial signature */ 22 | typedef struct{ 23 | /** \brief Public key for the signature */ 24 | PublicKey pubkey; 25 | /** \brief Signature we generated */ 26 | Signature signature; 27 | } PSBTPartialSignature; 28 | 29 | /** \brief Data required for input signing */ 30 | typedef struct{ 31 | /** \brief TransactionOutput data - scriptPubkey and amount */ 32 | TxOut txOut; 33 | /** \brief Derivation paths for the keys required for signing. 34 | * Can be more than one in case of multisig. 35 | */ 36 | PSBTDerivation * derivations; 37 | uint8_t derivationsLen; 38 | /** \brief Redeem script for P2SH */ 39 | Script redeemScript; 40 | /** \brief Witness script for P2WSH */ 41 | Script witnessScript; 42 | /** \brief Signatures we will generate. In most cases will be just one. */ 43 | PSBTPartialSignature * signatures; 44 | uint8_t signaturesLen; 45 | } PSBTInputMetadata; 46 | 47 | /** \brief Data required to confirm ownership of the output */ 48 | typedef struct{ 49 | /** \brief Derivation paths for the keys. 50 | * Can be more than one in case of multisig. 51 | */ 52 | PSBTDerivation * derivations; 53 | uint8_t derivationsLen; 54 | /** \brief Redeem script for P2SH */ 55 | Script redeemScript; 56 | /** \brief Witness script for P2WSH */ 57 | Script witnessScript; 58 | } PSBTOutputMetadata; 59 | 60 | /** \brief Calculates descriptor checksum for Bitcoin Core. */ 61 | size_t descriptorChecksum(const char * span, size_t spanLen, char * output, size_t outputSize); 62 | #if USE_ARDUINO_STRING 63 | String descriptorChecksum(String descriptor); 64 | #elif USE_STD_STRING 65 | std::string descriptorChecksum(std::string descriptor); 66 | #endif 67 | 68 | /** \brief PSBT class. See [bip174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) */ 69 | class PSBT : public Streamable{ 70 | protected: 71 | virtual size_t from_stream(ParseStream *s); 72 | virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const; 73 | Script key; // key for parsing 74 | Script value; // value for parsing 75 | uint8_t current_section; 76 | size_t last_key_pos; 77 | public: 78 | virtual size_t length() const; 79 | PSBT(){ txInsMeta = NULL; txOutsMeta = NULL; status = PARSING_DONE; current_section = 0; last_key_pos = 0; }; 80 | PSBT(PSBT const &other); 81 | ~PSBT(); 82 | Tx tx; 83 | PSBTInputMetadata * txInsMeta; 84 | PSBTOutputMetadata * txOutsMeta; 85 | 86 | /** \brief adds key-value pair to section */ 87 | int add(uint8_t section, const Script * k, const Script * v); 88 | /** \brief Signes everything it can with keys derived from root HD private key */ 89 | uint8_t sign(const HDPrivateKey root); 90 | /** \brief parses psbt transaction from base64 encoded string */ 91 | #if USE_ARDUINO_STRING 92 | size_t parseBase64(String b64); 93 | String toBase64(); 94 | #endif 95 | #if USE_STD_STRING 96 | size_t parseBase64(std::string b64); 97 | std::string toBase64(); 98 | #endif 99 | /** \brief Calculates fee if input amounts are known */ 100 | uint64_t fee() const; 101 | /** \brief Verifies if output is mine */ 102 | bool isMine(uint8_t outputNumber, const HDPublicKey xpub) const; 103 | bool isMine(uint8_t outputNumber, const HDPrivateKey xprv) const; 104 | // TODO: add verify() function that checks all the fields (scripts, pubkeys etc) 105 | // TODO: add isChange() function that would verify the output with respect the inputs 106 | PSBT &operator=(PSBT const &other); 107 | bool isValid() const{ return status==PARSING_DONE; }; 108 | explicit operator bool() const{ return isValid(); }; 109 | }; 110 | 111 | #endif // __PSBT_H__ -------------------------------------------------------------------------------- /src/uBitcoin_conf.h: -------------------------------------------------------------------------------- 1 | #ifndef __UBITCOIN_CONF_H__ 2 | #define __UBITCOIN_CONF_H__ 3 | 4 | /* Change this if you want to have other network by default */ 5 | #define DEFAULT_NETWORK Mainnet 6 | 7 | /* Change this config file to adjust to your framework */ 8 | #ifndef USE_STDONLY 9 | #ifdef ARDUINO 10 | #include 11 | #else 12 | #define MBED 13 | #include 14 | #endif 15 | #endif 16 | 17 | /* If you don't have a Stream class in your framework you can implement one 18 | * by yourself and use it to parse transactions and hash on the fly. 19 | * Arduino and Mbed are using slightly different API, choose one. 20 | * TODO: describe the interface. 21 | */ 22 | 23 | /* settings for Arduino */ 24 | #ifdef ARDUINO 25 | #define USE_ARDUINO_STRING 1 /* Arduino String implementation (WString.h) */ 26 | #define USE_ARDUINO_STREAM 1 /* Arduino Stream class */ 27 | #define USE_STD_STRING 0 /* Standard library std::string */ 28 | #define USE_MBED_STREAM 0 /* Mbed Stream class */ 29 | #endif 30 | 31 | #ifdef MBED 32 | #define USE_ARDUINO_STRING 0 /* Arduino String implementation (WString.h) */ 33 | #define USE_ARDUINO_STREAM 0 /* Arduino Stream class */ 34 | #define USE_STD_STRING 1 /* Standard library std::string */ 35 | #define USE_MBED_STREAM 1 /* Mbed Stream class */ 36 | #endif 37 | 38 | #ifdef USE_STDONLY 39 | #ifndef USE_ARDUINO_STRING 40 | #define USE_ARDUINO_STRING 0 /* Arduino String implementation (WString.h) */ 41 | #endif 42 | #ifndef USE_ARDUINO_STREAM 43 | #define USE_ARDUINO_STREAM 0 /* Arduino Stream class */ 44 | #endif 45 | #ifndef USE_STD_STRING 46 | #define USE_STD_STRING 1 /* Standard library std::string */ 47 | #endif 48 | #ifndef USE_MBED_STREAM 49 | #define USE_MBED_STREAM 0 /* Mbed Stream class */ 50 | #endif 51 | #endif 52 | 53 | #if USE_STD_STRING 54 | #include 55 | // using std::string; 56 | #endif 57 | 58 | #endif //__UBITCOIN_CONF_H__ 59 | -------------------------------------------------------------------------------- /src/utility/segwit_addr.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017 Pieter Wuille 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | #include 22 | #include 23 | #include 24 | 25 | #include "segwit_addr.h" 26 | 27 | uint32_t bech32_polymod_step(uint32_t pre) { 28 | uint8_t b = pre >> 25; 29 | return ((pre & 0x1FFFFFF) << 5) ^ 30 | (-((b >> 0) & 1) & 0x3b6a57b2UL) ^ 31 | (-((b >> 1) & 1) & 0x26508e6dUL) ^ 32 | (-((b >> 2) & 1) & 0x1ea119faUL) ^ 33 | (-((b >> 3) & 1) & 0x3d4233ddUL) ^ 34 | (-((b >> 4) & 1) & 0x2a1462b3UL); 35 | } 36 | 37 | static const char* charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; 38 | 39 | static const int8_t charset_rev[128] = { 40 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43 | 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, 44 | -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 45 | 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, 46 | -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 47 | 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 48 | }; 49 | 50 | int bech32_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len) { 51 | uint32_t chk = 1; 52 | size_t i = 0; 53 | while (hrp[i] != 0) { 54 | int ch = hrp[i]; 55 | if (ch < 33 || ch > 126) { 56 | return 0; 57 | } 58 | 59 | if (ch >= 'A' && ch <= 'Z') return 0; 60 | chk = bech32_polymod_step(chk) ^ (ch >> 5); 61 | ++i; 62 | } 63 | if (i + 7 + data_len > MAX_BECH32_SIZE) return 0; 64 | chk = bech32_polymod_step(chk); 65 | while (*hrp != 0) { 66 | chk = bech32_polymod_step(chk) ^ (*hrp & 0x1f); 67 | *(output++) = *(hrp++); 68 | } 69 | *(output++) = '1'; 70 | for (i = 0; i < data_len; ++i) { 71 | if (*data >> 5) return 0; 72 | chk = bech32_polymod_step(chk) ^ (*data); 73 | *(output++) = charset[*(data++)]; 74 | } 75 | for (i = 0; i < 6; ++i) { 76 | chk = bech32_polymod_step(chk); 77 | } 78 | chk ^= 1; 79 | for (i = 0; i < 6; ++i) { 80 | *(output++) = charset[(chk >> ((5 - i) * 5)) & 0x1f]; 81 | } 82 | *output = 0; 83 | return 1; 84 | } 85 | 86 | int bech32_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input) { 87 | uint32_t chk = 1; 88 | size_t i; 89 | size_t input_len = strlen(input); 90 | size_t hrp_len; 91 | int have_lower = 0, have_upper = 0; 92 | if (input_len < 8 || input_len > MAX_BECH32_SIZE) { 93 | return 0; 94 | } 95 | *data_len = 0; 96 | while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1') { 97 | ++(*data_len); 98 | } 99 | hrp_len = input_len - (1 + *data_len); 100 | if (hrp_len < 1 || *data_len < 6) { 101 | return 0; 102 | } 103 | *(data_len) -= 6; 104 | for (i = 0; i < hrp_len; ++i) { 105 | int ch = input[i]; 106 | if (ch < 33 || ch > 126) { 107 | return 0; 108 | } 109 | if (ch >= 'a' && ch <= 'z') { 110 | have_lower = 1; 111 | } else if (ch >= 'A' && ch <= 'Z') { 112 | have_upper = 1; 113 | ch = (ch - 'A') + 'a'; 114 | } 115 | hrp[i] = ch; 116 | chk = bech32_polymod_step(chk) ^ (ch >> 5); 117 | } 118 | hrp[i] = 0; 119 | chk = bech32_polymod_step(chk); 120 | for (i = 0; i < hrp_len; ++i) { 121 | chk = bech32_polymod_step(chk) ^ (input[i] & 0x1f); 122 | } 123 | ++i; 124 | while (i < input_len) { 125 | int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]]; 126 | if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1; 127 | if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1; 128 | if (v == -1) { 129 | return 0; 130 | } 131 | chk = bech32_polymod_step(chk) ^ v; 132 | if (i + 6 < input_len) { 133 | data[i - (1 + hrp_len)] = v; 134 | } 135 | ++i; 136 | } 137 | if (have_lower && have_upper) { 138 | return 0; 139 | } 140 | return chk == 1; 141 | } 142 | 143 | int convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad) { 144 | uint32_t val = 0; 145 | int bits = 0; 146 | uint32_t maxv = (((uint32_t)1) << outbits) - 1; 147 | while (inlen--) { 148 | val = (val << inbits) | *(in++); 149 | bits += inbits; 150 | while (bits >= outbits) { 151 | bits -= outbits; 152 | out[(*outlen)++] = (val >> bits) & maxv; 153 | } 154 | } 155 | if (pad) { 156 | if (bits) { 157 | out[(*outlen)++] = (val << (outbits - bits)) & maxv; 158 | } 159 | } else if (((val << (outbits - bits)) & maxv) || bits >= inbits) { 160 | return 0; 161 | } 162 | return 1; 163 | } 164 | 165 | int segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t *witprog, size_t witprog_len) { 166 | uint8_t data[65]; 167 | size_t datalen = 0; 168 | if (witver > 16) return 0; 169 | if (witver == 0 && witprog_len != 20 && witprog_len != 32) return 0; 170 | if (witprog_len < 2 || witprog_len > 40) return 0; 171 | data[0] = witver; 172 | convert_bits(data + 1, &datalen, 5, witprog, witprog_len, 8, 1); 173 | ++datalen; 174 | return bech32_encode(output, hrp, data, datalen); 175 | } 176 | 177 | int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { 178 | uint8_t data[84]; 179 | char hrp_actual[84]; 180 | size_t data_len; 181 | if (!bech32_decode(hrp_actual, data, &data_len, addr)) return 0; 182 | if (data_len == 0 || data_len > 65) return 0; 183 | if (strncmp(hrp, hrp_actual, 84) != 0) return 0; 184 | if (data[0] > 16) return 0; 185 | *witdata_len = 0; 186 | if (!convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0; 187 | if (*witdata_len < 2 || *witdata_len > 40) return 0; 188 | if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0; 189 | *witver = data[0]; 190 | return 1; 191 | } -------------------------------------------------------------------------------- /src/utility/segwit_addr.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017 Pieter Wuille 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef _SEGWIT_ADDR_H_ 23 | #define _SEGWIT_ADDR_H_ 1 24 | 25 | #include 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #define MAX_BECH32_SIZE 1000 // for lightning 32 | 33 | /** Encode a SegWit address 34 | * 35 | * Out: output: Pointer to a buffer of size 73 + strlen(hrp) that will be 36 | * updated to contain the null-terminated address. 37 | * In: hrp: Pointer to the null-terminated human readable part to use 38 | * (chain/network specific). 39 | * ver: Version of the witness program (between 0 and 16 inclusive). 40 | * prog: Data bytes for the witness program (between 2 and 40 bytes). 41 | * prog_len: Number of data bytes in prog. 42 | * Returns 1 if successful. 43 | */ 44 | int segwit_addr_encode( 45 | char *output, 46 | const char *hrp, 47 | int ver, 48 | const uint8_t *prog, 49 | size_t prog_len 50 | ); 51 | 52 | /** Decode a SegWit address 53 | * 54 | * Out: ver: Pointer to an int that will be updated to contain the witness 55 | * program version (between 0 and 16 inclusive). 56 | * prog: Pointer to a buffer of size 40 that will be updated to 57 | * contain the witness program bytes. 58 | * prog_len: Pointer to a size_t that will be updated to contain the length 59 | * of bytes in prog. 60 | * hrp: Pointer to the null-terminated human readable part that is 61 | * expected (chain/network specific). 62 | * addr: Pointer to the null-terminated address. 63 | * Returns 1 if successful. 64 | */ 65 | int segwit_addr_decode( 66 | int* ver, 67 | uint8_t* prog, 68 | size_t* prog_len, 69 | const char* hrp, 70 | const char* addr 71 | ); 72 | 73 | /** Encode a Bech32 string 74 | * 75 | * Out: output: Pointer to a buffer of size strlen(hrp) + data_len + 8 that 76 | * will be updated to contain the null-terminated Bech32 string. 77 | * In: hrp : Pointer to the null-terminated human readable part. 78 | * data : Pointer to an array of 5-bit values. 79 | * data_len: Length of the data array. 80 | * Returns 1 if successful. 81 | */ 82 | int bech32_encode( 83 | char *output, 84 | const char *hrp, 85 | const uint8_t *data, 86 | size_t data_len 87 | ); 88 | 89 | /** Decode a Bech32 string 90 | * 91 | * Out: hrp: Pointer to a buffer of size strlen(input) - 6. Will be 92 | * updated to contain the null-terminated human readable part. 93 | * data: Pointer to a buffer of size strlen(input) - 8 that will 94 | * hold the encoded 5-bit data values. 95 | * data_len: Pointer to a size_t that will be updated to be the number 96 | * of entries in data. 97 | * In: input: Pointer to a null-terminated Bech32 string. 98 | * Returns 1 if succesful. 99 | */ 100 | int bech32_decode( 101 | char *hrp, 102 | uint8_t *data, 103 | size_t *data_len, 104 | const char *input 105 | ); 106 | 107 | int convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad); 108 | 109 | #ifdef __cplusplus 110 | } /* end of extern "C" */ 111 | #endif 112 | 113 | #endif -------------------------------------------------------------------------------- /src/utility/trezor/address.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Daira Hopwood 3 | * Copyright (c) 2016 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "address.h" 25 | #include "bignum.h" 26 | 27 | size_t address_prefix_bytes_len(uint32_t address_type) 28 | { 29 | if (address_type <= 0xFF) return 1; 30 | if (address_type <= 0xFFFF) return 2; 31 | if (address_type <= 0xFFFFFF) return 3; 32 | return 4; 33 | } 34 | 35 | void address_write_prefix_bytes(uint32_t address_type, uint8_t *out) 36 | { 37 | if (address_type > 0xFFFFFF) *(out++) = address_type >> 24; 38 | if (address_type > 0xFFFF) *(out++) = (address_type >> 16) & 0xFF; 39 | if (address_type > 0xFF) *(out++) = (address_type >> 8) & 0xFF; 40 | *(out++) = address_type & 0xFF; 41 | } 42 | 43 | bool address_check_prefix(const uint8_t *addr, uint32_t address_type) 44 | { 45 | if (address_type <= 0xFF) { 46 | return address_type == (uint32_t)(addr[0]); 47 | } 48 | if (address_type <= 0xFFFF) { 49 | return address_type == (((uint32_t) addr[0] << 8) | ((uint32_t) addr[1])); 50 | } 51 | if (address_type <= 0xFFFFFF) { 52 | return address_type == (((uint32_t) addr[0] << 16) | ((uint32_t) addr[1] << 8) | ((uint32_t) addr[2])); 53 | } 54 | return address_type == (((uint32_t) addr[0] << 24) | ((uint32_t) addr[1] << 16) | ((uint32_t) addr[2] << 8) | ((uint32_t) addr[3])); 55 | } 56 | 57 | #if USE_ETHEREUM 58 | #include "sha3.h" 59 | 60 | void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id) 61 | { 62 | const char *hex = "0123456789abcdef"; 63 | for (int i = 0; i < 20; i++) { 64 | address[i * 2] = hex[(addr[i] >> 4) & 0xF]; 65 | address[i * 2 + 1] = hex[addr[i] & 0xF]; 66 | } 67 | address[40] = 0; 68 | 69 | SHA3_CTX ctx; 70 | uint8_t hash[32]; 71 | keccak_256_Init(&ctx); 72 | if (rskip60) { 73 | char prefix[16]; 74 | int prefix_size = bn_format_uint64(chain_id, NULL, "0x", 0, 0, false, prefix, sizeof(prefix)); 75 | keccak_Update(&ctx, (const uint8_t *)prefix, prefix_size); 76 | } 77 | keccak_Update(&ctx, (const uint8_t *)address, 40); 78 | keccak_Final(&ctx, hash); 79 | 80 | for (int i = 0; i < 20; i++) { 81 | if (hash[i] & 0x80 && address[i * 2 ] >= 'a' && address[i * 2 ] <= 'f') { 82 | address[i * 2] -= 0x20; 83 | } 84 | if (hash[i] & 0x08 && address[i * 2 + 1] >= 'a' && address[i * 2 + 1] <= 'f') { 85 | address[i * 2 + 1] -= 0x20; 86 | } 87 | } 88 | } 89 | #endif 90 | -------------------------------------------------------------------------------- /src/utility/trezor/address.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Daira Hopwood 3 | * Copyright (c) 2016 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __ADDRESS_H__ 25 | #define __ADDRESS_H__ 26 | 27 | #include 28 | #include 29 | #include 30 | #include "options.h" 31 | 32 | size_t address_prefix_bytes_len(uint32_t address_type); 33 | void address_write_prefix_bytes(uint32_t address_type, uint8_t *out); 34 | bool address_check_prefix(const uint8_t *addr, uint32_t address_type); 35 | #if USE_ETHEREUM 36 | void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id); 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/utility/trezor/base58.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __BASE58_H__ 25 | #define __BASE58_H__ 26 | 27 | #include 28 | #include 29 | #include "hasher.h" 30 | #include "options.h" 31 | 32 | extern const char b58digits_ordered[]; 33 | extern const int8_t b58digits_map[]; 34 | 35 | int base58_encode_check(const uint8_t *data, int len, HasherType hasher_type, char *str, int strsize); 36 | int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen); 37 | 38 | // Private 39 | bool b58tobin(void *bin, size_t *binszp, const char *b58); 40 | int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str); 41 | bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz); 42 | 43 | #if USE_GRAPHENE 44 | int base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize); 45 | int base58gph_decode_check(const char *str, uint8_t *data, int datalen); 46 | int b58gphcheck(const void *bin, size_t binsz, const char *base58str); 47 | #endif 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/utility/trezor/bignum.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * Copyright (c) 2016 Alex Beregszaszi 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included 14 | * in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 20 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef __BIGNUM_H__ 26 | #define __BIGNUM_H__ 27 | 28 | #include 29 | #include 30 | #include 31 | #include "options.h" 32 | 33 | // bignum256 are 256 bits stored as 8*30 bit + 1*16 bit 34 | // val[0] are lowest 30 bits, val[8] highest 16 bits 35 | typedef struct { 36 | uint32_t val[9]; 37 | } bignum256; 38 | 39 | #ifdef __cplusplus 40 | extern "C" 41 | { 42 | #endif 43 | 44 | // read 4 big endian bytes into uint32 45 | uint32_t read_be(const uint8_t *data); 46 | 47 | // write 4 big endian bytes 48 | void write_be(uint8_t *data, uint32_t x); 49 | 50 | // read 4 little endian bytes into uint32 51 | uint32_t read_le(const uint8_t *data); 52 | 53 | // write 4 little endian bytes 54 | void write_le(uint8_t *data, uint32_t x); 55 | 56 | void bn_read_be(const uint8_t *in_number, bignum256 *out_number); 57 | 58 | void bn_write_be(const bignum256 *in_number, uint8_t *out_number); 59 | 60 | void bn_read_le(const uint8_t *in_number, bignum256 *out_number); 61 | 62 | void bn_write_le(const bignum256 *in_number, uint8_t *out_number); 63 | 64 | void bn_read_uint32(uint32_t in_number, bignum256 *out_number); 65 | 66 | void bn_read_uint64(uint64_t in_number, bignum256 *out_number); 67 | 68 | static inline uint32_t bn_write_uint32(const bignum256 *in_number) 69 | { 70 | return in_number->val[0] | (in_number->val[1] << 30); 71 | } 72 | 73 | static inline uint64_t bn_write_uint64(const bignum256 *in_number) 74 | { 75 | uint64_t tmp; 76 | tmp = in_number->val[2]; 77 | tmp <<= 30; 78 | tmp |= in_number->val[1]; 79 | tmp <<= 30; 80 | tmp |= in_number->val[0]; 81 | return tmp; 82 | } 83 | 84 | // copies number a to b 85 | static inline void bn_copy(const bignum256 *a, bignum256 *b) { 86 | *b = *a; 87 | } 88 | 89 | int bn_bitcount(const bignum256 *a); 90 | 91 | unsigned int bn_digitcount(const bignum256 *a); 92 | 93 | void bn_zero(bignum256 *a); 94 | 95 | int bn_is_zero(const bignum256 *a); 96 | 97 | void bn_one(bignum256 *a); 98 | 99 | static inline int bn_is_even(const bignum256 *a) { 100 | return (a->val[0] & 1) == 0; 101 | } 102 | 103 | static inline int bn_is_odd(const bignum256 *a) { 104 | return (a->val[0] & 1) == 1; 105 | } 106 | 107 | int bn_is_less(const bignum256 *a, const bignum256 *b); 108 | 109 | int bn_is_equal(const bignum256 *a, const bignum256 *b); 110 | 111 | void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, const bignum256 *falsecase); 112 | 113 | void bn_lshift(bignum256 *a); 114 | 115 | void bn_rshift(bignum256 *a); 116 | 117 | void bn_setbit(bignum256 *a, uint8_t bit); 118 | 119 | void bn_clearbit(bignum256 *a, uint8_t bit); 120 | 121 | uint32_t bn_testbit(bignum256 *a, uint8_t bit); 122 | 123 | void bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c); 124 | 125 | void bn_mult_half(bignum256 *x, const bignum256 *prime); 126 | 127 | void bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime); 128 | 129 | void bn_mod(bignum256 *x, const bignum256 *prime); 130 | 131 | void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime); 132 | 133 | void bn_fast_mod(bignum256 *x, const bignum256 *prime); 134 | 135 | void bn_sqrt(bignum256 *x, const bignum256 *prime); 136 | 137 | void bn_inverse(bignum256 *x, const bignum256 *prime); 138 | 139 | void bn_normalize(bignum256 *a); 140 | 141 | void bn_add(bignum256 *a, const bignum256 *b); 142 | 143 | void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime); 144 | 145 | void bn_addi(bignum256 *a, uint32_t b); 146 | 147 | void bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime); 148 | 149 | void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, const bignum256 *prime); 150 | 151 | void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res); 152 | 153 | void bn_divmod58(bignum256 *a, uint32_t *r); 154 | 155 | void bn_divmod1000(bignum256 *a, uint32_t *r); 156 | 157 | size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen); 158 | 159 | static inline size_t bn_format_uint64(uint64_t amount, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen) 160 | { 161 | bignum256 amnt; 162 | bn_read_uint64(amount, &amnt); 163 | 164 | return bn_format(&amnt, prefix, suffix, decimals, exponent, trailing, out, outlen); 165 | } 166 | 167 | #if USE_BN_PRINT 168 | void bn_print(const bignum256 *a); 169 | void bn_print_raw(const bignum256 *a); 170 | #endif 171 | 172 | #ifdef __cplusplus 173 | } // extern "C" 174 | #endif 175 | 176 | #endif 177 | -------------------------------------------------------------------------------- /src/utility/trezor/bip32.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __BIP32_H__ 25 | #define __BIP32_H__ 26 | 27 | #include 28 | #include 29 | #include 30 | #include "ecdsa.h" 31 | // #include "ed25519-donna/ed25519.h" 32 | #include "options.h" 33 | 34 | typedef struct { 35 | const char *bip32_name; // string for generating BIP32 xprv from seed 36 | const ecdsa_curve *params; // ecdsa curve parameters, null for ed25519 37 | 38 | HasherType hasher_base58; 39 | HasherType hasher_sign; 40 | HasherType hasher_pubkey; 41 | HasherType hasher_script; 42 | } curve_info; 43 | 44 | typedef struct { 45 | uint32_t depth; 46 | uint32_t child_num; 47 | uint8_t chain_code[32]; 48 | 49 | uint8_t private_key[32]; 50 | uint8_t private_key_extension[32]; 51 | 52 | uint8_t public_key[33]; 53 | const curve_info *curve; 54 | } HDNode; 55 | 56 | // int hdnode_from_xpub(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *public_key, const char *curve, HDNode *out); 57 | // 58 | // int hdnode_from_xprv(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *private_key, const char *curve, HDNode *out); 59 | // 60 | // int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, HDNode *out); 61 | // 62 | // #define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000)) 63 | // 64 | // int hdnode_private_ckd(HDNode *inout, uint32_t i); 65 | // 66 | // #if USE_CARDANO 67 | // int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i); 68 | // int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, const uint8_t *seed, int seed_len, HDNode *out); 69 | // #endif 70 | // 71 | // int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code); 72 | // 73 | // int hdnode_public_ckd(HDNode *inout, uint32_t i); 74 | // 75 | // void hdnode_public_ckd_address_optimized(const curve_point *pub, const uint8_t *chain_code, uint32_t i, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize, int addrformat); 76 | // 77 | // #if USE_BIP32_CACHE 78 | // int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, uint32_t *fingerprint); 79 | // #endif 80 | // 81 | // uint32_t hdnode_fingerprint(HDNode *node); 82 | // 83 | // void hdnode_fill_public_key(HDNode *node); 84 | // 85 | // #if USE_ETHEREUM 86 | // int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash); 87 | // #endif 88 | // 89 | // #if USE_NEM 90 | // int hdnode_get_nem_address(HDNode *node, uint8_t version, char *address); 91 | // int hdnode_get_nem_shared_key(const HDNode *node, const ed25519_public_key peer_public_key, const uint8_t *salt, ed25519_public_key mul, uint8_t *shared_key); 92 | // int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key, const uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer); 93 | // int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key, uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer); 94 | // #endif 95 | // 96 | // int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType hasher_sign, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); 97 | // int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); 98 | // 99 | // int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, uint8_t *session_key, int *result_size); 100 | // 101 | // int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize); 102 | // 103 | // int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize); 104 | // 105 | // int hdnode_deserialize(const char *str, uint32_t version_public, uint32_t version_private, const char *curve, HDNode *node, uint32_t *fingerprint); 106 | // 107 | // void hdnode_get_address_raw(HDNode *node, uint32_t version, uint8_t *addr_raw); 108 | // void hdnode_get_address(HDNode *node, uint32_t version, char *addr, int addrsize); 109 | // 110 | // const curve_info *get_curve_by_name(const char *curve_name); 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/utility/trezor/bip39.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #include "bip39.h" 28 | #include "hmac.h" 29 | #include "rand.h" 30 | #include "sha2.h" 31 | #include "pbkdf2.h" 32 | #include "bip39_english.h" 33 | #include "options.h" 34 | #include "memzero.h" 35 | 36 | #if USE_BIP39_CACHE 37 | 38 | static int bip39_cache_index = 0; 39 | 40 | static CONFIDENTIAL struct { 41 | bool set; 42 | char mnemonic[256]; 43 | char passphrase[64]; 44 | uint8_t seed[512 / 8]; 45 | } bip39_cache[BIP39_CACHE_SIZE]; 46 | 47 | #endif 48 | 49 | const char *mnemonic_generate(int strength) 50 | { 51 | if (strength % 32 || strength < 128 || strength > 256) { 52 | return 0; 53 | } 54 | uint8_t data[32]; 55 | random_buffer(data, 32); 56 | const char *r = mnemonic_from_data(data, strength / 8); 57 | memzero(data, sizeof(data)); 58 | return r; 59 | } 60 | 61 | static CONFIDENTIAL char mnemo[24 * 10]; 62 | 63 | const char *mnemonic_from_data(const uint8_t *data, int len) 64 | { 65 | if (len % 4 || len < 16 || len > 32) { 66 | return 0; 67 | } 68 | 69 | uint8_t bits[32 + 1]; 70 | 71 | sha256_Raw(data, len, bits); 72 | // checksum 73 | bits[len] = bits[0]; 74 | // data 75 | memcpy(bits, data, len); 76 | 77 | int mlen = len * 3 / 4; 78 | 79 | int i, j, idx; 80 | char *p = mnemo; 81 | for (i = 0; i < mlen; i++) { 82 | idx = 0; 83 | for (j = 0; j < 11; j++) { 84 | idx <<= 1; 85 | idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0; 86 | } 87 | strcpy(p, wordlist[idx]); 88 | p += strlen(wordlist[idx]); 89 | *p = (i < mlen - 1) ? ' ' : 0; 90 | p++; 91 | } 92 | memzero(bits, sizeof(bits)); 93 | 94 | return mnemo; 95 | } 96 | 97 | void mnemonic_clear(void) 98 | { 99 | memzero(mnemo, sizeof(mnemo)); 100 | } 101 | 102 | int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy) 103 | { 104 | if (!mnemonic) { 105 | return 0; 106 | } 107 | 108 | uint32_t i = 0, n = 0; 109 | 110 | while (mnemonic[i]) { 111 | if (mnemonic[i] == ' ') { 112 | n++; 113 | } 114 | i++; 115 | } 116 | n++; 117 | 118 | // check number of words 119 | if (n != 12 && n != 18 && n != 24) { 120 | return 0; 121 | } 122 | 123 | char current_word[10]; 124 | uint32_t j, k, ki, bi = 0; 125 | uint8_t bits[32 + 1]; 126 | 127 | memzero(bits, sizeof(bits)); 128 | i = 0; 129 | while (mnemonic[i]) { 130 | j = 0; 131 | while (mnemonic[i] != ' ' && mnemonic[i] != 0) { 132 | if (j >= sizeof(current_word) - 1) { 133 | return 0; 134 | } 135 | current_word[j] = mnemonic[i]; 136 | i++; j++; 137 | } 138 | current_word[j] = 0; 139 | if (mnemonic[i] != 0) { 140 | i++; 141 | } 142 | k = 0; 143 | for (;;) { 144 | if (!wordlist[k]) { // word not found 145 | return 0; 146 | } 147 | if (strcmp(current_word, wordlist[k]) == 0) { // word found on index k 148 | for (ki = 0; ki < 11; ki++) { 149 | if (k & (1 << (10 - ki))) { 150 | bits[bi / 8] |= 1 << (7 - (bi % 8)); 151 | } 152 | bi++; 153 | } 154 | break; 155 | } 156 | k++; 157 | } 158 | } 159 | if (bi != n * 11) { 160 | return 0; 161 | } 162 | memcpy(entropy, bits, sizeof(bits)); 163 | return n * 11; 164 | } 165 | 166 | int mnemonic_check(const char *mnemonic) 167 | { 168 | uint8_t bits[32 + 1]; 169 | int seed_len = mnemonic_to_entropy(mnemonic, bits); 170 | if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) { 171 | return 0; 172 | } 173 | int words = seed_len / 11; 174 | 175 | uint8_t checksum = bits[words * 4 / 3]; 176 | sha256_Raw(bits, words * 4 / 3, bits); 177 | if (words == 12) { 178 | return (bits[0] & 0xF0) == (checksum & 0xF0); // compare first 4 bits 179 | } else if (words == 18) { 180 | return (bits[0] & 0xFC) == (checksum & 0xFC); // compare first 6 bits 181 | } else if (words == 24) { 182 | return bits[0] == checksum; // compare 8 bits 183 | } 184 | return 0; 185 | } 186 | 187 | // passphrase must be at most 256 characters otherwise it would be truncated 188 | void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total)) 189 | { 190 | int mnemoniclen = strlen(mnemonic); 191 | int passphraselen = strlen(passphrase); 192 | #if USE_BIP39_CACHE 193 | // check cache 194 | if (mnemoniclen < 256 && passphraselen < 64) { 195 | for (int i = 0; i < BIP39_CACHE_SIZE; i++) { 196 | if (!bip39_cache[i].set) continue; 197 | if (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue; 198 | if (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue; 199 | // found the correct entry 200 | memcpy(seed, bip39_cache[i].seed, 512 / 8); 201 | return; 202 | } 203 | } 204 | #endif 205 | uint8_t salt[8 + 256]; 206 | memcpy(salt, "mnemonic", 8); 207 | memcpy(salt + 8, passphrase, passphraselen); 208 | static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx; 209 | pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, mnemoniclen, salt, passphraselen + 8, 1); 210 | if (progress_callback) { 211 | progress_callback(0, BIP39_PBKDF2_ROUNDS); 212 | } 213 | for (int i = 0; i < 16; i++) { 214 | pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16); 215 | if (progress_callback) { 216 | progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16, BIP39_PBKDF2_ROUNDS); 217 | } 218 | } 219 | pbkdf2_hmac_sha512_Final(&pctx, seed); 220 | memzero(salt, sizeof(salt)); 221 | #if USE_BIP39_CACHE 222 | // store to cache 223 | if (mnemoniclen < 256 && passphraselen < 64) { 224 | bip39_cache[bip39_cache_index].set = true; 225 | strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic); 226 | strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase); 227 | memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8); 228 | bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE; 229 | } 230 | #endif 231 | } 232 | 233 | const char * const *mnemonic_wordlist(void) 234 | { 235 | return wordlist; 236 | } 237 | -------------------------------------------------------------------------------- /src/utility/trezor/bip39.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __BIP39_H__ 25 | #define __BIP39_H__ 26 | 27 | #include 28 | 29 | #define BIP39_PBKDF2_ROUNDS 2048 30 | 31 | #ifdef __cplusplus 32 | extern "C" 33 | { 34 | #endif 35 | 36 | const char *mnemonic_generate(int strength); // strength in bits 37 | const char *mnemonic_from_data(const uint8_t *data, int len); 38 | void mnemonic_clear(void); 39 | 40 | int mnemonic_check(const char *mnemonic); 41 | 42 | int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy); 43 | 44 | // passphrase must be at most 256 characters otherwise it would be truncated 45 | void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total)); 46 | 47 | const char * const *mnemonic_wordlist(void); 48 | 49 | #ifdef __cplusplus 50 | } // extern "C" 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/utility/trezor/ecdsa.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __ECDSA_H__ 25 | #define __ECDSA_H__ 26 | 27 | #include 28 | #include "options.h" 29 | #include "bignum.h" 30 | #include "hasher.h" 31 | 32 | // curve point x and y 33 | typedef struct { 34 | bignum256 x, y; 35 | } curve_point; 36 | 37 | typedef struct { 38 | 39 | bignum256 prime; // prime order of the finite field 40 | curve_point G; // initial curve point 41 | bignum256 order; // order of G 42 | bignum256 order_half; // order of G divided by 2 43 | int a; // coefficient 'a' of the elliptic curve 44 | bignum256 b; // coefficient 'b' of the elliptic curve 45 | 46 | #if USE_PRECOMPUTED_CP 47 | const curve_point cp[64][8]; 48 | #endif 49 | 50 | } ecdsa_curve; 51 | 52 | // 4 byte prefix + 40 byte data (segwit) 53 | // 1 byte prefix + 64 byte data (cashaddr) 54 | #define MAX_ADDR_RAW_SIZE 65 55 | // bottle neck is cashaddr 56 | // segwit is at most 90 characters plus NUL separator 57 | // cashaddr: human readable prefix + 1 separator + 104 data + 8 checksum + 1 NUL 58 | // we choose 130 as maximum (including NUL character) 59 | #define MAX_ADDR_SIZE 130 60 | // 4 byte prefix + 32 byte privkey + 1 byte compressed marker 61 | #define MAX_WIF_RAW_SIZE (4 + 32 + 1) 62 | // (4 + 32 + 1 + 4 [checksum]) * 8 / log2(58) plus NUL. 63 | #define MAX_WIF_SIZE (57) 64 | 65 | #ifdef __cplusplus 66 | extern "C" 67 | { 68 | #endif 69 | 70 | void point_copy(const curve_point *cp1, curve_point *cp2); 71 | void point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2); 72 | void point_double(const ecdsa_curve *curve, curve_point *cp); 73 | void point_multiply(const ecdsa_curve *curve, const bignum256 *k, const curve_point *p, curve_point *res); 74 | void point_set_infinity(curve_point *p); 75 | int point_is_infinity(const curve_point *p); 76 | int point_is_equal(const curve_point *p, const curve_point *q); 77 | int point_is_negative_of(const curve_point *p, const curve_point *q); 78 | void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res); 79 | int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *pub_key, uint8_t *session_key); 80 | void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y); 81 | int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed); 82 | 83 | int ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); 84 | int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); 85 | void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key); 86 | void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key); 87 | void ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey, uint8_t *pubkeyhash); 88 | void ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw); 89 | void ecdsa_get_address(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize); 90 | void ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw); 91 | void ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize); 92 | void ecdsa_get_wif(const uint8_t *priv_key, uint32_t version, HasherType hasher_base58, char *wif, int wifsize); 93 | 94 | int ecdsa_address_decode(const char *addr, uint32_t version, HasherType hasher_base58, uint8_t *out); 95 | int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_point *pub); 96 | int ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub); 97 | int ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len); 98 | int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest); 99 | int ecdsa_recover_pub_from_sig (const ecdsa_curve *curve, uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest, int recid); 100 | int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der); 101 | 102 | #ifdef __cplusplus 103 | } /* end of extern "C" */ 104 | #endif 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /src/utility/trezor/hasher.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 Saleem Rashid 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "hasher.h" 24 | #include "ripemd160.h" 25 | 26 | void hasher_Init(Hasher *hasher, HasherType type) { 27 | hasher->type = type; 28 | 29 | switch (hasher->type) { 30 | case HASHER_SHA2: 31 | case HASHER_SHA2D: 32 | case HASHER_SHA2_RIPEMD: 33 | sha256_Init(&hasher->ctx.sha2); 34 | break; 35 | case HASHER_SHA3: 36 | #if USE_KECCAK 37 | case HASHER_SHA3K: 38 | #endif 39 | sha3_256_Init(&hasher->ctx.sha3); 40 | break; 41 | } 42 | } 43 | 44 | void hasher_Reset(Hasher *hasher) { 45 | hasher_Init(hasher, hasher->type); 46 | } 47 | 48 | void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length) { 49 | switch (hasher->type) { 50 | case HASHER_SHA2: 51 | case HASHER_SHA2D: 52 | case HASHER_SHA2_RIPEMD: 53 | sha256_Update(&hasher->ctx.sha2, data, length); 54 | break; 55 | case HASHER_SHA3: 56 | #if USE_KECCAK 57 | case HASHER_SHA3K: 58 | #endif 59 | sha3_Update(&hasher->ctx.sha3, data, length); 60 | break; 61 | } 62 | } 63 | 64 | void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]) { 65 | switch (hasher->type) { 66 | case HASHER_SHA2: 67 | sha256_Final(&hasher->ctx.sha2, hash); 68 | break; 69 | case HASHER_SHA2D: 70 | sha256_Final(&hasher->ctx.sha2, hash); 71 | hasher_Raw(HASHER_SHA2, hash, HASHER_DIGEST_LENGTH, hash); 72 | break; 73 | case HASHER_SHA2_RIPEMD: 74 | sha256_Final(&hasher->ctx.sha2, hash); 75 | ripemd160(hash, HASHER_DIGEST_LENGTH, hash); 76 | break; 77 | case HASHER_SHA3: 78 | sha3_Final(&hasher->ctx.sha3, hash); 79 | break; 80 | #if USE_KECCAK 81 | case HASHER_SHA3K: 82 | keccak_Final(&hasher->ctx.sha3, hash); 83 | break; 84 | #endif 85 | } 86 | } 87 | 88 | void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]) { 89 | Hasher hasher; 90 | 91 | hasher_Init(&hasher, type); 92 | hasher_Update(&hasher, data, length); 93 | hasher_Final(&hasher, hash); 94 | } 95 | -------------------------------------------------------------------------------- /src/utility/trezor/hasher.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 Saleem Rashid 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __HASHER_H__ 24 | #define __HASHER_H__ 25 | 26 | #include 27 | #include 28 | 29 | #include "sha2.h" 30 | #include "sha3.h" 31 | 32 | #define HASHER_DIGEST_LENGTH 32 33 | 34 | typedef enum { 35 | HASHER_SHA2, 36 | HASHER_SHA2D, 37 | HASHER_SHA2_RIPEMD, 38 | 39 | HASHER_SHA3, 40 | #if USE_KECCAK 41 | HASHER_SHA3K, 42 | #endif 43 | } HasherType; 44 | 45 | typedef struct { 46 | HasherType type; 47 | 48 | union { 49 | SHA256_CTX sha2; // for HASHER_SHA2{,D} 50 | SHA3_CTX sha3; // for HASHER_SHA3{,K} 51 | } ctx; 52 | } Hasher; 53 | 54 | void hasher_Init(Hasher *hasher, HasherType type); 55 | void hasher_Reset(Hasher *hasher); 56 | void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length); 57 | void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]); 58 | 59 | void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/utility/trezor/hmac.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | #include 24 | 25 | #include "hmac.h" 26 | #include "memzero.h" 27 | 28 | // add way how to mark confidential data 29 | #ifndef CONFIDENTIAL 30 | #define CONFIDENTIAL 31 | #endif 32 | 33 | void ubtc_hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen) 34 | { 35 | static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH]; 36 | memset(i_key_pad, 0, SHA256_BLOCK_LENGTH); 37 | if (keylen > SHA256_BLOCK_LENGTH) { 38 | sha256_Raw(key, keylen, i_key_pad); 39 | } else { 40 | memcpy(i_key_pad, key, keylen); 41 | } 42 | for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) { 43 | hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; 44 | i_key_pad[i] ^= 0x36; 45 | } 46 | sha256_Init(&(hctx->ctx)); 47 | sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH); 48 | memzero(i_key_pad, sizeof(i_key_pad)); 49 | } 50 | 51 | void ubtc_hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen) 52 | { 53 | sha256_Update(&(hctx->ctx), msg, msglen); 54 | } 55 | 56 | void ubtc_hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) 57 | { 58 | sha256_Final(&(hctx->ctx), hmac); 59 | sha256_Init(&(hctx->ctx)); 60 | sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH); 61 | sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH); 62 | sha256_Final(&(hctx->ctx), hmac); 63 | memzero(hctx, sizeof(HMAC_SHA256_CTX)); 64 | } 65 | 66 | void ubtc_hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac) 67 | { 68 | static CONFIDENTIAL HMAC_SHA256_CTX hctx; 69 | ubtc_hmac_sha256_Init(&hctx, key, keylen); 70 | ubtc_hmac_sha256_Update(&hctx, msg, msglen); 71 | ubtc_hmac_sha256_Final(&hctx, hmac); 72 | } 73 | 74 | void ubtc_hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest) 75 | { 76 | static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH/sizeof(uint32_t)]; 77 | 78 | memzero(key_pad, sizeof(key_pad)); 79 | if (keylen > SHA256_BLOCK_LENGTH) { 80 | static CONFIDENTIAL SHA256_CTX context; 81 | sha256_Init(&context); 82 | sha256_Update(&context, key, keylen); 83 | sha256_Final(&context, (uint8_t*)key_pad); 84 | } else { 85 | memcpy(key_pad, key, keylen); 86 | } 87 | 88 | /* compute o_key_pad and its digest */ 89 | for (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) { 90 | uint32_t data; 91 | #if BYTE_ORDER == LITTLE_ENDIAN 92 | REVERSE32(key_pad[i], data); 93 | #else 94 | data = key_pad[i]; 95 | #endif 96 | key_pad[i] = data ^ 0x5c5c5c5c; 97 | } 98 | sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest); 99 | 100 | /* convert o_key_pad to i_key_pad and compute its digest */ 101 | for (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) { 102 | key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636; 103 | } 104 | sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest); 105 | memzero(key_pad, sizeof(key_pad)); 106 | } 107 | 108 | void ubtc_hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen) 109 | { 110 | static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH]; 111 | memset(i_key_pad, 0, SHA512_BLOCK_LENGTH); 112 | if (keylen > SHA512_BLOCK_LENGTH) { 113 | sha512_Raw(key, keylen, i_key_pad); 114 | } else { 115 | memcpy(i_key_pad, key, keylen); 116 | } 117 | for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) { 118 | hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; 119 | i_key_pad[i] ^= 0x36; 120 | } 121 | sha512_Init(&(hctx->ctx)); 122 | sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH); 123 | memzero(i_key_pad, sizeof(i_key_pad)); 124 | } 125 | 126 | void ubtc_hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen) 127 | { 128 | sha512_Update(&(hctx->ctx), msg, msglen); 129 | } 130 | 131 | void ubtc_hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) 132 | { 133 | sha512_Final(&(hctx->ctx), hmac); 134 | sha512_Init(&(hctx->ctx)); 135 | sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH); 136 | sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH); 137 | sha512_Final(&(hctx->ctx), hmac); 138 | memzero(hctx, sizeof(HMAC_SHA512_CTX)); 139 | } 140 | 141 | void ubtc_hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac) 142 | { 143 | HMAC_SHA512_CTX hctx; 144 | ubtc_hmac_sha512_Init(&hctx, key, keylen); 145 | ubtc_hmac_sha512_Update(&hctx, msg, msglen); 146 | ubtc_hmac_sha512_Final(&hctx, hmac); 147 | } 148 | 149 | void ubtc_hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest) 150 | { 151 | static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH/sizeof(uint64_t)]; 152 | 153 | memzero(key_pad, sizeof(key_pad)); 154 | if (keylen > SHA512_BLOCK_LENGTH) { 155 | static CONFIDENTIAL SHA512_CTX context; 156 | sha512_Init(&context); 157 | sha512_Update(&context, key, keylen); 158 | sha512_Final(&context, (uint8_t*)key_pad); 159 | } else { 160 | memcpy(key_pad, key, keylen); 161 | } 162 | 163 | /* compute o_key_pad and its digest */ 164 | for (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) { 165 | uint64_t data; 166 | #if BYTE_ORDER == LITTLE_ENDIAN 167 | REVERSE64(key_pad[i], data); 168 | #else 169 | data = key_pad[i]; 170 | #endif 171 | key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c; 172 | } 173 | sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest); 174 | 175 | /* convert o_key_pad to i_key_pad and compute its digest */ 176 | for (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) { 177 | key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636; 178 | } 179 | sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest); 180 | memzero(key_pad, sizeof(key_pad)); 181 | } 182 | -------------------------------------------------------------------------------- /src/utility/trezor/hmac.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT HMAC_SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __HMAC_H__ 25 | #define __HMAC_H__ 26 | 27 | #include 28 | #include "sha2.h" 29 | 30 | typedef struct _HMAC_SHA256_CTX { 31 | uint8_t o_key_pad[SHA256_BLOCK_LENGTH]; 32 | SHA256_CTX ctx; 33 | } HMAC_SHA256_CTX; 34 | 35 | typedef struct _HMAC_SHA512_CTX { 36 | uint8_t o_key_pad[SHA512_BLOCK_LENGTH]; 37 | SHA512_CTX ctx; 38 | } HMAC_SHA512_CTX; 39 | 40 | #ifdef __cplusplus 41 | extern "C" 42 | { 43 | #endif 44 | 45 | void ubtc_hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen); 46 | void ubtc_hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen); 47 | void ubtc_hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac); 48 | void ubtc_hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac); 49 | void ubtc_hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest); 50 | 51 | void ubtc_hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen); 52 | void ubtc_hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen); 53 | void ubtc_hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac); 54 | void ubtc_hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac); 55 | void ubtc_hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest); 56 | 57 | #ifdef __cplusplus 58 | } /* end of extern "C" */ 59 | #endif 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/utility/trezor/memzero.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void memzero(void *s, size_t n) 4 | { 5 | memset(s, 0, n); 6 | } 7 | -------------------------------------------------------------------------------- /src/utility/trezor/memzero.h: -------------------------------------------------------------------------------- 1 | #ifndef __MEMZERO_H__ 2 | #define __MEMZERO_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | void memzero(void *s, size_t n); 12 | 13 | #ifdef __cplusplus 14 | } /* end of extern "C" */ 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/utility/trezor/options.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Pavol Rusnak 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __OPTIONS_H__ 24 | #define __OPTIONS_H__ 25 | 26 | // use precomputed Curve Points (some scalar multiples of curve base point G) 27 | #ifndef USE_PRECOMPUTED_CP 28 | #define USE_PRECOMPUTED_CP 1 29 | #endif 30 | 31 | // use fast inverse method 32 | #ifndef USE_INVERSE_FAST 33 | #define USE_INVERSE_FAST 1 34 | #endif 35 | 36 | // support for printing bignum256 structures via printf 37 | #ifndef USE_BN_PRINT 38 | #define USE_BN_PRINT 0 39 | #endif 40 | 41 | // use deterministic signatures 42 | #ifndef USE_RFC6979 43 | #define USE_RFC6979 1 44 | #endif 45 | 46 | // implement BIP32 caching 47 | #ifndef USE_BIP32_CACHE 48 | #define USE_BIP32_CACHE 1 49 | #define BIP32_CACHE_SIZE 10 50 | #define BIP32_CACHE_MAXDEPTH 8 51 | #endif 52 | 53 | // support constructing BIP32 nodes from ed25519 and curve25519 curves. 54 | #ifndef USE_BIP32_25519_CURVES 55 | #define USE_BIP32_25519_CURVES 0 56 | #endif 57 | 58 | // implement BIP39 caching 59 | #ifndef USE_BIP39_CACHE 60 | #define USE_BIP39_CACHE 1 61 | #define BIP39_CACHE_SIZE 4 62 | #endif 63 | 64 | // support Ethereum operations 65 | #ifndef USE_ETHEREUM 66 | #define USE_ETHEREUM 0 67 | #endif 68 | 69 | // support Graphene operations (STEEM, BitShares) 70 | #ifndef USE_GRAPHENE 71 | #define USE_GRAPHENE 0 72 | #endif 73 | 74 | // support NEM operations 75 | #ifndef USE_NEM 76 | #define USE_NEM 0 77 | #endif 78 | 79 | // support MONERO operations 80 | #ifndef USE_MONERO 81 | #define USE_MONERO 0 82 | #endif 83 | 84 | // support CARDANO operations 85 | #ifndef USE_CARDANO 86 | #define USE_CARDANO 0 87 | #endif 88 | 89 | // support Keccak hashing 90 | #ifndef USE_KECCAK 91 | #define USE_KECCAK 0 92 | #endif 93 | 94 | // add way how to mark confidential data 95 | #ifndef CONFIDENTIAL 96 | #define CONFIDENTIAL 97 | #endif 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/utility/trezor/pbkdf2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include "pbkdf2.h" 26 | #include "hmac.h" 27 | #include "sha2.h" 28 | #include "memzero.h" 29 | 30 | void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr) 31 | { 32 | SHA256_CTX ctx; 33 | #if BYTE_ORDER == LITTLE_ENDIAN 34 | REVERSE32(blocknr, blocknr); 35 | #endif 36 | 37 | ubtc_hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig); 38 | memzero(pctx->g, sizeof(pctx->g)); 39 | pctx->g[8] = 0x80000000; 40 | pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8; 41 | 42 | memcpy (ctx.state, pctx->idig, sizeof(pctx->idig)); 43 | ctx.bitcount = SHA256_BLOCK_LENGTH * 8; 44 | sha256_Update(&ctx, salt, saltlen); 45 | sha256_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr)); 46 | sha256_Final(&ctx, (uint8_t*)pctx->g); 47 | #if BYTE_ORDER == LITTLE_ENDIAN 48 | for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) { 49 | REVERSE32(pctx->g[k], pctx->g[k]); 50 | } 51 | #endif 52 | sha256_Transform(pctx->odig, pctx->g, pctx->g); 53 | memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH); 54 | pctx->first = 1; 55 | } 56 | 57 | void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations) 58 | { 59 | for (uint32_t i = pctx->first; i < iterations; i++) { 60 | sha256_Transform(pctx->idig, pctx->g, pctx->g); 61 | sha256_Transform(pctx->odig, pctx->g, pctx->g); 62 | for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH/sizeof(uint32_t); j++) { 63 | pctx->f[j] ^= pctx->g[j]; 64 | } 65 | } 66 | pctx->first = 0; 67 | } 68 | 69 | void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key) 70 | { 71 | #if BYTE_ORDER == LITTLE_ENDIAN 72 | for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH/sizeof(uint32_t); k++) { 73 | REVERSE32(pctx->f[k], pctx->f[k]); 74 | } 75 | #endif 76 | memcpy(key, pctx->f, SHA256_DIGEST_LENGTH); 77 | memzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX)); 78 | } 79 | 80 | void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen) 81 | { 82 | uint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH; 83 | uint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH; 84 | if (last_block_size) { 85 | blocks_count++; 86 | } else { 87 | last_block_size = SHA256_DIGEST_LENGTH; 88 | } 89 | for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) { 90 | PBKDF2_HMAC_SHA256_CTX pctx; 91 | pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr); 92 | pbkdf2_hmac_sha256_Update(&pctx, iterations); 93 | uint8_t digest[SHA256_DIGEST_LENGTH]; 94 | pbkdf2_hmac_sha256_Final(&pctx, digest); 95 | uint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH; 96 | if (blocknr < blocks_count) { 97 | memcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH); 98 | } else { 99 | memcpy(key + key_offset, digest, last_block_size); 100 | } 101 | } 102 | } 103 | 104 | void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr) 105 | { 106 | SHA512_CTX ctx; 107 | #if BYTE_ORDER == LITTLE_ENDIAN 108 | REVERSE32(blocknr, blocknr); 109 | #endif 110 | 111 | ubtc_hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig); 112 | memzero(pctx->g, sizeof(pctx->g)); 113 | pctx->g[8] = 0x8000000000000000; 114 | pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8; 115 | 116 | memcpy (ctx.state, pctx->idig, sizeof(pctx->idig)); 117 | ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8; 118 | ctx.bitcount[1] = 0; 119 | sha512_Update(&ctx, salt, saltlen); 120 | sha512_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr)); 121 | sha512_Final(&ctx, (uint8_t*)pctx->g); 122 | #if BYTE_ORDER == LITTLE_ENDIAN 123 | for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) { 124 | REVERSE64(pctx->g[k], pctx->g[k]); 125 | } 126 | #endif 127 | sha512_Transform(pctx->odig, pctx->g, pctx->g); 128 | memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH); 129 | pctx->first = 1; 130 | } 131 | 132 | void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations) 133 | { 134 | for (uint32_t i = pctx->first; i < iterations; i++) { 135 | sha512_Transform(pctx->idig, pctx->g, pctx->g); 136 | sha512_Transform(pctx->odig, pctx->g, pctx->g); 137 | for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) { 138 | pctx->f[j] ^= pctx->g[j]; 139 | } 140 | } 141 | pctx->first = 0; 142 | } 143 | 144 | void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key) 145 | { 146 | #if BYTE_ORDER == LITTLE_ENDIAN 147 | for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH/sizeof(uint64_t); k++) { 148 | REVERSE64(pctx->f[k], pctx->f[k]); 149 | } 150 | #endif 151 | memcpy(key, pctx->f, SHA512_DIGEST_LENGTH); 152 | memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX)); 153 | } 154 | 155 | void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen) 156 | { 157 | uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH; 158 | uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH; 159 | if (last_block_size) { 160 | blocks_count++; 161 | } else { 162 | last_block_size = SHA512_DIGEST_LENGTH; 163 | } 164 | for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) { 165 | PBKDF2_HMAC_SHA512_CTX pctx; 166 | pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr); 167 | pbkdf2_hmac_sha512_Update(&pctx, iterations); 168 | uint8_t digest[SHA512_DIGEST_LENGTH]; 169 | pbkdf2_hmac_sha512_Final(&pctx, digest); 170 | uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH; 171 | if (blocknr < blocks_count) { 172 | memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH); 173 | } else { 174 | memcpy(key + key_offset, digest, last_block_size); 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/utility/trezor/pbkdf2.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __PBKDF2_H__ 25 | #define __PBKDF2_H__ 26 | 27 | #include 28 | #include "sha2.h" 29 | 30 | typedef struct _PBKDF2_HMAC_SHA256_CTX { 31 | uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; 32 | uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; 33 | uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)]; 34 | uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)]; 35 | char first; 36 | } PBKDF2_HMAC_SHA256_CTX; 37 | 38 | typedef struct _PBKDF2_HMAC_SHA512_CTX { 39 | uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; 40 | uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; 41 | uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)]; 42 | uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)]; 43 | char first; 44 | } PBKDF2_HMAC_SHA512_CTX; 45 | 46 | void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr); 47 | void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations); 48 | void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key); 49 | void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen); 50 | 51 | void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr); 52 | void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations); 53 | void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key); 54 | void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/utility/trezor/rand.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | // Node: heavily edited by uBitcoin developers with inspiration from micropython source code. 25 | 26 | #include "rand.h" 27 | #include "sha2.h" 28 | #include 29 | 30 | // esp boards 31 | #if defined(ESP_PLATFORM) 32 | 33 | #include 34 | uint32_t __attribute__((weak)) random32(void){ 35 | return esp_random(); 36 | } 37 | 38 | #elif defined(ESP8266) 39 | // see http://esp8266-re.foogod.com/wiki/Random_Number_Generator 40 | #define WDEV_HWRNG ((volatile uint32_t*)0x3ff20e44) 41 | uint32_t __attribute__((weak)) random32(void){ 42 | uint32_t rngint = 0; 43 | uint32_t v = 0; 44 | for(int i=0; i<4; i++){ 45 | v = (*WDEV_HWRNG); 46 | rngint = (rngint << 8) | v; 47 | } 48 | return rngint; 49 | } 50 | 51 | // stm boards 52 | #elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32G0) 53 | 54 | #if defined(RNG) 55 | 56 | // taken from micropython source code 57 | #define RNG_TIMEOUT_MS (10) 58 | 59 | uint32_t __attribute__((weak)) random32(void) { 60 | // Enable the RNG peripheral if it's not already enabled 61 | if (!(RNG->CR & RNG_CR_RNGEN)) { 62 | #if defined(STM32H7) 63 | // Set RNG Clock source 64 | __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ); 65 | __HAL_RCC_RNG_CONFIG(RCC_RNGCLKSOURCE_PLL); 66 | #endif 67 | __HAL_RCC_RNG_CLK_ENABLE(); 68 | RNG->CR |= RNG_CR_RNGEN; 69 | } 70 | 71 | // Wait for a new random number to be ready, takes on the order of 10us 72 | uint32_t start = HAL_GetTick(); 73 | while (!(RNG->SR & RNG_SR_DRDY)) { 74 | if (HAL_GetTick() - start >= RNG_TIMEOUT_MS) { 75 | return 0; 76 | } 77 | } 78 | 79 | // Get and return the new random number 80 | return RNG->DR; 81 | } 82 | #else 83 | 84 | // fallback to prng 85 | #define UBTC_USE_PRNG 86 | 87 | #endif // defined RNG 88 | 89 | // PC 90 | #elif defined(__unix__) || defined(__APPLE__) || defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) || defined(__ANDROID__) 91 | 92 | // rand from os random source 93 | #include 94 | 95 | uint32_t __attribute__((weak)) random32(void){ 96 | return (uint32_t)rand(); 97 | } 98 | 99 | #else 100 | 101 | // fallback to prng 102 | #define UBTC_USE_PRNG 103 | 104 | #endif 105 | 106 | // fallback option if no RNG on this platform 107 | #ifdef UBTC_USE_PRNG 108 | 109 | #pragma message("\nWARGNING! RANDOM NUMBER GENERATOR IS NOT SUPPORTED ON THIS PLATFORM! \n\ 110 | Pseudo-random generator will be used unless you define\n\ 111 | your own random function like so: \n\n\ 112 | extern \"C\" { \n\ 113 | uint32_t random32(){\n\ 114 | ...get random value somehow...\n\ 115 | return value;\n\ 116 | }\n\ 117 | }") 118 | 119 | 120 | uint32_t __attribute__((weak)) random32(void) { 121 | static uint32_t pad = 0xeda4baba, n = 69, d = 233; 122 | static uint8_t dat = 0; 123 | 124 | pad += dat + d * n; 125 | pad = (pad << 3) + (pad >> 29); 126 | n = pad | 2; 127 | d ^= (pad << 31) + (pad >> 1); 128 | dat ^= (char)pad ^ (d >> 8) ^ 1; 129 | 130 | return pad ^ (d << 5) ^ (pad >> 18) ^ (dat << 1); 131 | } 132 | 133 | #endif // UBTC_USE_PRNG 134 | 135 | // 136 | // The following code is platform independent 137 | // 138 | 139 | void __attribute__((weak)) random_buffer(uint8_t *buf, size_t len) 140 | { 141 | uint32_t r = 0; 142 | for (size_t i = 0; i < len; i++) { 143 | if (i % 4 == 0) { 144 | r = random32(); 145 | } 146 | buf[i] = (r >> ((i % 4) * 8)) & 0xFF; 147 | } 148 | } 149 | 150 | uint32_t random_uniform(uint32_t n) 151 | { 152 | uint32_t x, max = 0xFFFFFFFF - (0xFFFFFFFF % n); 153 | while ((x = random32()) >= max); 154 | return x / (max / n); 155 | } 156 | 157 | void random_permute(char *str, size_t len) 158 | { 159 | for (int i = len - 1; i >= 1; i--) { 160 | int j = random_uniform(i + 1); 161 | char t = str[j]; 162 | str[j] = str[i]; 163 | str[i] = t; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/utility/trezor/rand.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __RAND_H__ 25 | #define __RAND_H__ 26 | 27 | #include 28 | #include 29 | 30 | #ifdef __cplusplus 31 | extern "C" 32 | { 33 | #endif 34 | 35 | uint32_t random32(void); 36 | void random_buffer(uint8_t *buf, size_t len); 37 | 38 | uint32_t random_uniform(uint32_t n); 39 | void random_permute(char *buf, size_t len); 40 | 41 | #ifdef __cplusplus 42 | } // extern "C" 43 | #endif 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/utility/trezor/rfc6979.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * Copyright (c) 2015 Jochen Hoenicke 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included 14 | * in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 20 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include "rfc6979.h" 27 | #include "hmac.h" 28 | #include "memzero.h" 29 | 30 | void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) { 31 | uint8_t bx[2*32]; 32 | uint8_t buf[32 + 1 + 2*32]; 33 | 34 | memcpy(bx, priv_key, 32); 35 | memcpy(bx+32, hash, 32); 36 | 37 | memset(state->v, 1, sizeof(state->v)); 38 | memset(state->k, 0, sizeof(state->k)); 39 | 40 | memcpy(buf, state->v, sizeof(state->v)); 41 | buf[sizeof(state->v)] = 0x00; 42 | memcpy(buf + sizeof(state->v) + 1, bx, 64); 43 | ubtc_hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); 44 | ubtc_hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); 45 | 46 | memcpy(buf, state->v, sizeof(state->v)); 47 | buf[sizeof(state->v)] = 0x01; 48 | memcpy(buf + sizeof(state->v) + 1, bx, 64); 49 | ubtc_hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); 50 | ubtc_hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); 51 | 52 | memzero(bx, sizeof(bx)); 53 | memzero(buf, sizeof(buf)); 54 | } 55 | 56 | // generate next number from deterministic random number generator 57 | void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state) 58 | { 59 | uint8_t buf[32 + 1]; 60 | 61 | ubtc_hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); 62 | memcpy(buf, state->v, sizeof(state->v)); 63 | buf[sizeof(state->v)] = 0x00; 64 | ubtc_hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k); 65 | ubtc_hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); 66 | memcpy(rnd, buf, 32); 67 | memzero(buf, sizeof(buf)); 68 | } 69 | 70 | // generate K in a deterministic way, according to RFC6979 71 | // http://tools.ietf.org/html/rfc6979 72 | void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) 73 | { 74 | uint8_t buf[32]; 75 | generate_rfc6979(buf, state); 76 | bn_read_be(buf, k); 77 | memzero(buf, sizeof(buf)); 78 | } 79 | -------------------------------------------------------------------------------- /src/utility/trezor/rfc6979.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * Copyright (c) 2015-2017 Jochen Hoenicke 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included 14 | * in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 20 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef __RFC6979_H__ 26 | #define __RFC6979_H__ 27 | 28 | #include 29 | #include "bignum.h" 30 | 31 | // rfc6979 pseudo random number generator state 32 | typedef struct { 33 | uint8_t v[32], k[32]; 34 | } rfc6979_state; 35 | 36 | #ifdef __cplusplus 37 | extern "C" 38 | { 39 | #endif 40 | 41 | void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *rng); 42 | void generate_rfc6979(uint8_t rnd[32], rfc6979_state *rng); 43 | void generate_k_rfc6979(bignum256 *k, rfc6979_state *rng); 44 | 45 | #ifdef __cplusplus 46 | } /* end of extern "C" */ 47 | #endif 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/utility/trezor/ripemd160.h: -------------------------------------------------------------------------------- 1 | #ifndef __RIPEMD160_H__ 2 | #define __RIPEMD160_H__ 3 | 4 | #include 5 | 6 | #define RIPEMD160_BLOCK_LENGTH 64 7 | #define RIPEMD160_DIGEST_LENGTH 20 8 | 9 | typedef struct _RIPEMD160_CTX { 10 | uint32_t total[2]; /*!< number of bytes processed */ 11 | uint32_t state[5]; /*!< intermediate digest state */ 12 | uint8_t buffer[RIPEMD160_BLOCK_LENGTH]; /*!< data block being processed */ 13 | } RIPEMD160_CTX; 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | void ripemd160_Init(RIPEMD160_CTX *ctx); 21 | void ripemd160_Update(RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen); 22 | void ripemd160_Final(RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH]); 23 | void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH]); 24 | 25 | #ifdef __cplusplus 26 | } /* end of extern "C" */ 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/utility/trezor/secp256k1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "secp256k1.h" 25 | 26 | const ecdsa_curve secp256k1 = { 27 | /* .prime */ { 28 | /*.val =*/ {0x3ffffc2f, 0x3ffffffb, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} 29 | }, 30 | 31 | /* G */ { 32 | /*.x =*/{/*.val =*/{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb, 0x70b0702, 0x18a573a, 0xbbac55a, 0x199fbe77, 0x79be}}, 33 | /*.y =*/{/*.val =*/{0x3b10d4b8, 0x311f423f, 0x28554199, 0x5ed1229, 0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8, 0x483a}} 34 | }, 35 | 36 | /* order */ { 37 | /*.val =*/{0x10364141, 0x3f497a33, 0x348a03bb, 0x2bb739ab, 0x3ffffeba, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} 38 | }, 39 | 40 | /* order_half */ { 41 | /*.val =*/{0x281b20a0, 0x3fa4bd19, 0x3a4501dd, 0x15db9cd5, 0x3fffff5d, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x7fff} 42 | }, 43 | 44 | /* a */ 0, 45 | 46 | /* b */ { 47 | /*.val =*/{7} 48 | } 49 | 50 | #if USE_PRECOMPUTED_CP 51 | , 52 | /* cp */ { 53 | #include "secp256k1.table" 54 | } 55 | #endif 56 | }; 57 | 58 | const curve_info secp256k1_info = { 59 | .bip32_name = "Bitcoin seed", 60 | .params = &secp256k1, 61 | .hasher_base58 = HASHER_SHA2D, 62 | .hasher_sign = HASHER_SHA2D, 63 | .hasher_pubkey = HASHER_SHA2_RIPEMD, 64 | .hasher_script = HASHER_SHA2, 65 | }; 66 | 67 | // const curve_info secp256k1_decred_info = { 68 | // .bip32_name = "Bitcoin seed", 69 | // .params = &secp256k1, 70 | // .hasher_base58 = HASHER_BLAKED, 71 | // .hasher_sign = HASHER_BLAKE, 72 | // .hasher_pubkey = HASHER_BLAKE_RIPEMD, 73 | // .hasher_script = HASHER_BLAKE, 74 | // }; 75 | // 76 | // const curve_info secp256k1_groestl_info = { 77 | // .bip32_name = "Bitcoin seed", 78 | // .params = &secp256k1, 79 | // .hasher_base58 = HASHER_GROESTLD_TRUNC, 80 | // .hasher_sign = HASHER_SHA2, 81 | // .hasher_pubkey = HASHER_SHA2_RIPEMD, 82 | // .hasher_script = HASHER_SHA2, 83 | // }; 84 | // 85 | // const curve_info secp256k1_smart_info = { 86 | // .bip32_name = "Bitcoin seed", 87 | // .params = &secp256k1, 88 | // .hasher_base58 = HASHER_SHA3K, 89 | // .hasher_sign = HASHER_SHA2, 90 | // .hasher_pubkey = HASHER_SHA2_RIPEMD, 91 | // .hasher_script = HASHER_SHA2, 92 | // }; 93 | -------------------------------------------------------------------------------- /src/utility/trezor/secp256k1.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-2014 Tomas Dzetkulic 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | * OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __SECP256K1_H__ 25 | #define __SECP256K1_H__ 26 | 27 | #include 28 | 29 | #include "ecdsa.h" 30 | #include "bip32.h" 31 | 32 | extern const ecdsa_curve secp256k1; 33 | extern const curve_info secp256k1_info; 34 | // extern const curve_info secp256k1_decred_info; 35 | // extern const curve_info secp256k1_groestl_info; 36 | // extern const curve_info secp256k1_smart_info; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/utility/trezor/sha2.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2000-2001 Aaron D. Gifford 3 | * Copyright (c) 2013-2014 Pavol Rusnak 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. Neither the name of the copyright holder nor the names of contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef __SHA2_H__ 32 | #define __SHA2_H__ 33 | 34 | #include 35 | #include 36 | 37 | #define SHA256_BLOCK_LENGTH 64 38 | #define SHA256_DIGEST_LENGTH 32 39 | #define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) 40 | #define SHA512_BLOCK_LENGTH 128 41 | #define SHA512_DIGEST_LENGTH 64 42 | #define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) 43 | 44 | typedef struct _SHA256_CTX { 45 | uint32_t state[8]; 46 | uint64_t bitcount; 47 | uint32_t buffer[SHA256_BLOCK_LENGTH/sizeof(uint32_t)]; 48 | } SHA256_CTX; 49 | typedef struct _SHA512_CTX { 50 | uint64_t state[8]; 51 | uint64_t bitcount[2]; 52 | uint64_t buffer[SHA512_BLOCK_LENGTH/sizeof(uint64_t)]; 53 | } SHA512_CTX; 54 | 55 | /*** ENDIAN REVERSAL MACROS *******************************************/ 56 | #ifndef LITTLE_ENDIAN 57 | #define LITTLE_ENDIAN 1234 58 | #define BIG_ENDIAN 4321 59 | #endif 60 | 61 | #ifndef BYTE_ORDER 62 | #define BYTE_ORDER LITTLE_ENDIAN 63 | #endif 64 | 65 | #if BYTE_ORDER == LITTLE_ENDIAN 66 | #define REVERSE32(w,x) { \ 67 | uint32_t tmp = (w); \ 68 | tmp = (tmp >> 16) | (tmp << 16); \ 69 | (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ 70 | } 71 | #define REVERSE64(w,x) { \ 72 | uint64_t tmp = (w); \ 73 | tmp = (tmp >> 32) | (tmp << 32); \ 74 | tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ 75 | ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ 76 | (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ 77 | ((tmp & 0x0000ffff0000ffffULL) << 16); \ 78 | } 79 | #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 80 | 81 | extern const uint32_t sha1_initial_hash_value[5]; 82 | extern const uint32_t sha256_initial_hash_value[8]; 83 | extern const uint64_t sha512_initial_hash_value[8]; 84 | 85 | #ifdef __cplusplus 86 | extern "C" 87 | { 88 | #endif 89 | 90 | void sha256_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out); 91 | void sha256_Init(SHA256_CTX *); 92 | void sha256_Update(SHA256_CTX*, const uint8_t*, size_t); 93 | void sha256_Final(SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]); 94 | char* sha256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); 95 | void sha256_Raw(const uint8_t*, size_t, uint8_t[SHA256_DIGEST_LENGTH]); 96 | char* sha256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); 97 | 98 | void sha512_Transform(const uint64_t* state_in, const uint64_t* data, uint64_t* state_out); 99 | void sha512_Init(SHA512_CTX*); 100 | void sha512_Update(SHA512_CTX*, const uint8_t*, size_t); 101 | void sha512_Final(SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]); 102 | char* sha512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); 103 | void sha512_Raw(const uint8_t*, size_t, uint8_t[SHA512_DIGEST_LENGTH]); 104 | char* sha512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); 105 | 106 | #ifdef __cplusplus 107 | } /* end of extern "C" */ 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /src/utility/trezor/sha3.h: -------------------------------------------------------------------------------- 1 | /* sha3.h - an implementation of Secure Hash Algorithm 3 (Keccak). 2 | * based on the 3 | * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 4 | * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche 5 | * 6 | * Copyright: 2013 Aleksey Kravchenko 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a 9 | * copy of this software and associated documentation files (the "Software"), 10 | * to deal in the Software without restriction, including without limitation 11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 | * and/or sell copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so. 14 | * 15 | * This program is distributed in the hope that it will be useful, but 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 | * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! 18 | */ 19 | 20 | #ifndef __SHA3_H__ 21 | #define __SHA3_H__ 22 | 23 | #include 24 | #include "options.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #define sha3_224_hash_size 28 31 | #define sha3_256_hash_size 32 32 | #define sha3_384_hash_size 48 33 | #define sha3_512_hash_size 64 34 | #define sha3_max_permutation_size 25 35 | #define sha3_max_rate_in_qwords 24 36 | 37 | #define SHA3_224_BLOCK_LENGTH 144 38 | #define SHA3_256_BLOCK_LENGTH 136 39 | #define SHA3_384_BLOCK_LENGTH 104 40 | #define SHA3_512_BLOCK_LENGTH 72 41 | 42 | #define SHA3_224_DIGEST_LENGTH sha3_224_hash_size 43 | #define SHA3_256_DIGEST_LENGTH sha3_256_hash_size 44 | #define SHA3_384_DIGEST_LENGTH sha3_384_hash_size 45 | #define SHA3_512_DIGEST_LENGTH sha3_512_hash_size 46 | 47 | /** 48 | * SHA3 Algorithm context. 49 | */ 50 | typedef struct SHA3_CTX 51 | { 52 | /* 1600 bits algorithm hashing state */ 53 | uint64_t hash[sha3_max_permutation_size]; 54 | /* 1536-bit buffer for leftovers */ 55 | uint64_t message[sha3_max_rate_in_qwords]; 56 | /* count of bytes in the message[] buffer */ 57 | unsigned rest; 58 | /* size of a message block processed at once */ 59 | unsigned block_size; 60 | } SHA3_CTX; 61 | 62 | /* methods for calculating the hash function */ 63 | 64 | void sha3_224_Init(SHA3_CTX *ctx); 65 | void sha3_256_Init(SHA3_CTX *ctx); 66 | void sha3_384_Init(SHA3_CTX *ctx); 67 | void sha3_512_Init(SHA3_CTX *ctx); 68 | void sha3_Update(SHA3_CTX *ctx, const unsigned char* msg, size_t size); 69 | void sha3_Final(SHA3_CTX *ctx, unsigned char* result); 70 | 71 | #if USE_KECCAK 72 | #define keccak_224_Init sha3_224_Init 73 | #define keccak_256_Init sha3_256_Init 74 | #define keccak_384_Init sha3_384_Init 75 | #define keccak_512_Init sha3_512_Init 76 | #define keccak_Update sha3_Update 77 | void keccak_Final(SHA3_CTX *ctx, unsigned char* result); 78 | void keccak_256(const unsigned char* data, size_t len, unsigned char* digest); 79 | void keccak_512(const unsigned char* data, size_t len, unsigned char* digest); 80 | #endif 81 | 82 | void sha3_256(const unsigned char* data, size_t len, unsigned char* digest); 83 | void sha3_512(const unsigned char* data, size_t len, unsigned char* digest); 84 | 85 | #ifdef __cplusplus 86 | } /* extern "C" */ 87 | #endif /* __cplusplus */ 88 | 89 | #endif /* __SHA3_H__ */ 90 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | # Paths 2 | BUILD_DIR = build 3 | SRC_DIR = . 4 | # uBitcoin library 5 | LIB_DIR = ../src 6 | 7 | # Tools 8 | ifeq ($(OS),Windows_NT) 9 | TOOLCHAIN_PREFIX ?= x86_64-w64-mingw32- 10 | MKDIR_P = mkdir 11 | RM_R = rmdir /s /q 12 | else 13 | TOOLCHAIN_PREFIX ?= 14 | MKDIR_P = mkdir -p 15 | RM_R = rm -r 16 | endif 17 | 18 | # compilers 19 | CC := $(TOOLCHAIN_PREFIX)gcc 20 | CXX := $(TOOLCHAIN_PREFIX)g++ 21 | 22 | # uBitcoin sources 23 | CXX_SOURCES += $(wildcard $(LIB_DIR)/*.cpp) 24 | C_SOURCES += $(wildcard $(LIB_DIR)/utility/trezor/*.c) \ 25 | $(wildcard $(LIB_DIR)/utility/*.c) \ 26 | $(wildcard $(LIB_DIR)/*.c) \ 27 | $(wildcard $(SRC_DIR)/*.c) 28 | 29 | # include lib path, don't use mbed or arduino config (-DUSE_STDONLY) 30 | CFLAGS = -I$(LIB_DIR) -g 31 | CPPFLAGS = -I$(LIB_DIR) -DUSE_STDONLY -DUBTC_TEST -g 32 | 33 | OBJS = $(patsubst $(SRC_DIR)/%, $(BUILD_DIR)/src/%.o, \ 34 | $(patsubst $(LIB_DIR)/%, $(BUILD_DIR)/lib/%.o, \ 35 | $(C_SOURCES) $(CXX_SOURCES))) 36 | 37 | vpath %.cpp $(SRC_DIR) 38 | vpath %.cpp $(LIB_DIR) 39 | vpath %.c $(SRC_DIR) 40 | vpath %.c $(LIB_DIR) 41 | 42 | TESTS=$(wildcard $(SRC_DIR)/*.cpp) 43 | TESTOBJS=$(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/test/%.cpp.o, $(TESTS)) 44 | TESTBINS=$(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/%.test, $(TESTS)) 45 | 46 | 47 | .PHONY: clean all run 48 | 49 | all: $(TESTBINS) 50 | 51 | run: $(TESTBINS) 52 | for test in $(TESTBINS); do echo $$test; ./$$test ; done 53 | 54 | # keep object files 55 | .SECONDARY: $(OBJS) $(TESTOBJS) 56 | 57 | # lib c sources 58 | $(BUILD_DIR)/lib/%.c.o: %.c 59 | $(MKDIR_P) $(dir $@) 60 | $(CC) -c $(CFLAGS) $< -o $@ 61 | 62 | # lib cpp sources 63 | $(BUILD_DIR)/lib/%.cpp.o: %.cpp 64 | $(MKDIR_P) $(dir $@) 65 | $(CXX) -c $(CPPFLAGS) $< -o $@ 66 | 67 | # lib c sources 68 | $(BUILD_DIR)/src/%.c.o: %.c 69 | $(MKDIR_P) $(dir $@) 70 | $(CC) -c $(CFLAGS) $< -o $@ 71 | 72 | # test cpp sources 73 | $(BUILD_DIR)/test/%.cpp.o: %.cpp 74 | $(MKDIR_P) $(dir $@) 75 | $(CXX) -c $(CPPFLAGS) $< -o $@ 76 | 77 | $(BUILD_DIR)/%.test: $(BUILD_DIR)/test/%.cpp.o $(OBJS) 78 | $(CXX) $< $(OBJS) $(CPPFLAGS) -o $@ 79 | 80 | clean: 81 | $(RM_R) $(BUILD_DIR) 82 | -------------------------------------------------------------------------------- /tests/sysrand.c: -------------------------------------------------------------------------------- 1 | #ifdef UBTC_TEST // only compile with test flag 2 | 3 | #include 4 | #include 5 | 6 | // use system random function 7 | uint32_t random32(void){ 8 | return (uint32_t)rand(); 9 | } 10 | 11 | #endif // UBTC_TEST 12 | -------------------------------------------------------------------------------- /tests/test_conversion.cpp: -------------------------------------------------------------------------------- 1 | #ifdef UBTC_TEST // only compile with test flag 2 | 3 | #include "minunit.h" 4 | #include "Conversion.h" // to print byte arrays in hex format 5 | 6 | using std::string; 7 | 8 | const char message[] = "Hello world!"; // message to convert 9 | const uint8_t * bytes = (const uint8_t *)message; 10 | const char b58[] = "2NEpo7TZRhna7vSvL"; 11 | const char b58check[] = "9wWTEnNTWna86WmtFaRbXa"; 12 | const char b64[] = "SGVsbG8gd29ybGQh"; 13 | 14 | uint8_t out[100]; 15 | size_t sz; 16 | string s; 17 | 18 | MU_TEST(test_base58) { 19 | s = toBase58(bytes, strlen(message)); 20 | mu_assert(strcmp(s.c_str(), b58) == 0, "toBase58 conversion is invalid"); 21 | 22 | sz = fromBase58(b58, out, sizeof(out)); 23 | mu_assert(sz == strlen(message), "fromBase58 size is wrong"); 24 | mu_assert(memcmp(out, bytes, sz) == 0, "fromBase58 decoding is wrong"); 25 | 26 | s = toBase58Check(bytes, strlen(message)); 27 | mu_assert(strcmp(s.c_str(), b58check) == 0, "toBase58 conversion is invalid"); 28 | 29 | sz = fromBase58Check(b58check, out, sizeof(out)); 30 | mu_assert(sz == strlen(message), "fromBase58Check size is wrong"); 31 | mu_assert(memcmp(out, bytes, sz) == 0, "fromBase58Check decoding is wrong"); 32 | 33 | sz = fromBase58(b58check, out, sizeof(out)); 34 | mu_assert(sz == (strlen(message)+4), "fromBase58 size is wrong"); 35 | mu_assert(memcmp(out, bytes, sz-4) == 0, "fromBase58 decoding is wrong"); 36 | } 37 | 38 | MU_TEST(test_base64) { 39 | s = toBase64(bytes, strlen(message)); 40 | mu_assert(strcmp(s.c_str(), b64) == 0, "toBase64 conversion is invalid"); 41 | 42 | sz = fromBase64(b64, out, sizeof(out)); 43 | mu_assert(sz == strlen(message), "fromBase64 size is wrong"); 44 | mu_assert(memcmp(out, bytes, sz) == 0, "fromBase64 decoding is wrong"); 45 | 46 | char *msgs[] = { 47 | "Man", "Ma", "M", "light w", "light wo", "light wor", "light work", "light work.", 48 | "\x6c\x68\x40\xa2\xc4\xbe\xfe\xa7\x85\x30\x20", NULL 49 | }; 50 | char *b64msgs[] = { 51 | "TWFu", "TWE=", "TQ==", "bGlnaHQgdw==", "bGlnaHQgd28=", "bGlnaHQgd29y", "bGlnaHQgd29yaw==", "bGlnaHQgd29yay4=", 52 | "bGhAosS+/qeFMCA=", NULL 53 | }; 54 | char *b64msgs_url[] = { 55 | "TWFu", "TWE", "TQ", "bGlnaHQgdw", "bGlnaHQgd28", "bGlnaHQgd29y", "bGlnaHQgd29yaw", "bGlnaHQgd29yay4", 56 | "bGhAosS-_qeFMCA", NULL 57 | }; 58 | size_t i = 0; 59 | while(msgs[i] != NULL){ 60 | char *msg = msgs[i]; 61 | s = toBase64((uint8_t*)msg, strlen(msg)); 62 | mu_assert(strcmp(s.c_str(), b64msgs[i]) == 0, "toBase64 conversion is invalid"); 63 | 64 | sz = fromBase64(b64msgs[i], out, sizeof(out)); 65 | mu_assert(sz == strlen(msg), "fromBase64 size is wrong"); 66 | mu_assert(memcmp(out, msg, sz) == 0, "fromBase64 decoding is wrong"); 67 | 68 | s = toBase64((uint8_t*)msg, strlen(msg), BASE64_NOPADDING | BASE64_URLSAFE); 69 | size_t l = toBase64Length((uint8_t*)msg, strlen(msg), BASE64_NOPADDING | BASE64_URLSAFE); 70 | mu_assert(strcmp(s.c_str(), b64msgs_url[i]) == 0, "toBase64 urlsafe conversion is invalid"); 71 | 72 | sz = fromBase64(b64msgs_url[i], out, sizeof(out), BASE64_NOPADDING | BASE64_URLSAFE); 73 | mu_assert(sz == strlen(msg), "fromBase64 size is wrong"); 74 | mu_assert(memcmp(out, msg, sz) == 0, "fromBase64 urlsafe decoding is wrong"); 75 | 76 | i++; 77 | } 78 | } 79 | 80 | MU_TEST(test_nullptr) { 81 | s = toBase64(NULL, strlen(message)); 82 | mu_assert(strcmp(s.c_str(), "") == 0, "toBase64 doesn't handle nullptr properly"); 83 | 84 | sz = fromBase64(b64, NULL, sizeof(out)); 85 | mu_assert(sz == 0, "fromBase64 doesn't handle nullptr properly"); 86 | 87 | s = toBase58(NULL, strlen(message)); 88 | mu_assert(strcmp(s.c_str(), "") == 0, "toBase58 doesn't handle nullptr properly"); 89 | 90 | sz = fromBase58(b58, NULL, sizeof(out)); 91 | mu_assert(sz == 0, "fromBase58 doesn't handle nullptr properly"); 92 | 93 | s = toBase58Check(NULL, strlen(message)); 94 | mu_assert(strcmp(s.c_str(), "") == 0, "toBase58Check doesn't handle nullptr properly"); 95 | 96 | sz = fromBase58Check(b58check, NULL, sizeof(out)); 97 | mu_assert(sz == 0, "fromBase58Check doesn't handle nullptr properly"); 98 | } 99 | 100 | MU_TEST_SUITE(test_conversion) { 101 | MU_RUN_TEST(test_base58); 102 | MU_RUN_TEST(test_base64); 103 | MU_RUN_TEST(test_nullptr); 104 | } 105 | 106 | int main(int argc, char *argv[]) { 107 | MU_RUN_SUITE(test_conversion); 108 | MU_REPORT(); 109 | return MU_EXIT_CODE; 110 | } 111 | 112 | #endif // UBTC_TEST 113 | -------------------------------------------------------------------------------- /tests/test_hash.cpp: -------------------------------------------------------------------------------- 1 | #ifdef UBTC_TEST // only compile with test flag 2 | 3 | #include "minunit.h" 4 | #include "Hash.h" // all single-line hashing algorithms 5 | #include "Conversion.h" // to print byte arrays in hex format 6 | 7 | using namespace std; 8 | 9 | char message[] = "Hello world!"; // message to hash 10 | 11 | MU_TEST(test_sha256) { 12 | uint8_t hash[32]; 13 | int hashLen = sha256(message, hash); 14 | string hexresult = toHex(hash, hashLen); 15 | char expected[] = "c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a"; 16 | mu_assert(strcmp(expected, hexresult.c_str()) == 0, "sha256 with string is invalid"); 17 | 18 | // using bytes 19 | uint8_t hash2[32]; 20 | uint8_t *bytes = (uint8_t *)message; 21 | size_t byteslen = strlen(message); 22 | 23 | sha256(bytes, byteslen, hash2); 24 | mu_assert(memcmp(hash, hash2, sizeof(hash)) == 0, "sha256 with bytes is invalid"); 25 | 26 | // sending data in pieces 27 | SHA256 h; 28 | h.begin(); 29 | h.write(bytes, 5); // add first 5 bytes to hash 30 | h.write(bytes+5, byteslen-5); // add the rest 31 | h.end(hash2); // result will be stored in the hash array 32 | mu_assert(memcmp(hash, hash2, sizeof(hash)) == 0, "sha256 in pieces is invalid"); 33 | } 34 | 35 | MU_TEST(test_ripemd160) { 36 | uint8_t hash[20]; 37 | int hashLen = rmd160(message, hash); 38 | string hexresult = toHex(hash, hashLen); 39 | mu_assert(strcmp(hexresult.c_str(), "7f772647d88750add82d8e1a7a3e5c0902a346a3") == 0, "ripemd160 is wrong"); 40 | } 41 | 42 | MU_TEST(test_hash160) { 43 | uint8_t hash[20]; 44 | int hashLen = hash160(message, hash); 45 | string hexresult = toHex(hash, hashLen); 46 | mu_assert(strcmp(hexresult.c_str(), "621281c15fb62d5c6013ea29007491e8b174e1b9") == 0, "hash160 is wrong"); 47 | } 48 | 49 | MU_TEST(test_doublesha256) { 50 | uint8_t hash[32]; 51 | int hashLen = doubleSha(message, hash); 52 | string hexresult = toHex(hash, hashLen); 53 | mu_assert(strcmp(hexresult.c_str(), "7982970534e089b839957b7e174725ce1878731ed6d700766e59cb16f1c25e27") == 0, "double sha256 is wrong"); 54 | } 55 | 56 | MU_TEST(test_taggedhash) { 57 | uint8_t hash[32]; 58 | int hashLen = tagged_hash("some tag", message, hash); 59 | string hexresult = toHex(hash, hashLen); 60 | mu_assert(strcmp(hexresult.c_str(), "5f03803bda8dc3b9ddc0e954d6dbb51543a3517bd84970e64a8825bcaddedbae") == 0, "tagged hash is wrong"); 61 | } 62 | 63 | MU_TEST(test_sha512) { 64 | uint8_t hash[64]; 65 | int hashLen = sha512(message, hash); 66 | string hexresult = toHex(hash, hashLen); 67 | mu_assert(strcmp(hexresult.c_str(), "f6cde2a0f819314cdde55fc227d8d7dae3d28cc556222a0a8ad66d91ccad4aad6094f517a2182360c9aacf6a3dc323162cb6fd8cdffedb0fe038f55e85ffb5b6") == 0, "sha512 is wrong"); 68 | } 69 | 70 | MU_TEST_SUITE(test_hash) { 71 | MU_RUN_TEST(test_sha256); 72 | MU_RUN_TEST(test_ripemd160); 73 | MU_RUN_TEST(test_hash160); 74 | MU_RUN_TEST(test_doublesha256); 75 | MU_RUN_TEST(test_sha512); 76 | } 77 | 78 | int main(int argc, char *argv[]) { 79 | MU_RUN_SUITE(test_hash); 80 | MU_REPORT(); 81 | return MU_EXIT_CODE; 82 | } 83 | 84 | #endif // UBTC_TEST 85 | -------------------------------------------------------------------------------- /tests/test_mnemonic.cpp: -------------------------------------------------------------------------------- 1 | #ifdef UBTC_TEST // only compile with test flag 2 | 3 | #include "minunit.h" 4 | #include "Bitcoin.h" 5 | 6 | using namespace std; 7 | 8 | #define MNEMONIC "arch volcano urge cradle turn labor skin secret squeeze denial jacket vintage fix glad lemon" 9 | #define PASSWORD "my secret password" 10 | 11 | MU_TEST(test_password) { 12 | HDPrivateKey hd(MNEMONIC, PASSWORD); 13 | mu_assert(bool(hd), "hd wallet should be valid"); 14 | mu_assert(strcmp(hd.xprv().c_str(), "xprv9s21ZrQH143K3a5zf698hDA7tWk75bUs2aK5ZUzsSHPxk6MUv2NqUM8NwzFLKqeLeeaH3VGxTcLBgyE9vHYWVnY6JjkuCw9k4HpxHPnodhs") == 0, "Root xprv is invalid"); 15 | } 16 | 17 | MU_TEST_SUITE(test_mnemonic) { 18 | MU_RUN_TEST(test_password); 19 | } 20 | 21 | int main(int argc, char *argv[]) { 22 | MU_RUN_SUITE(test_mnemonic); 23 | MU_REPORT(); 24 | return MU_EXIT_CODE; 25 | } 26 | 27 | #endif // UBTC_TEST 28 | -------------------------------------------------------------------------------- /tests/test_schnorr.cpp: -------------------------------------------------------------------------------- 1 | #ifdef UBTC_TEST // only compile with test flag 2 | 3 | #include "minunit.h" 4 | #include "Bitcoin.h" 5 | #include "Hash.h" 6 | #include "Conversion.h" // to print byte arrays in hex format 7 | 8 | using namespace std; 9 | 10 | char message[] = "Hello world!"; // message to hash 11 | 12 | MU_TEST(test_schnorrsign) { 13 | uint8_t hash[32]; 14 | int hashLen = tagged_hash("some tag", message, hash); 15 | // check signing (it's also an odd public key) 16 | PrivateKey pk("KxsLKrFM2X4kK4zkxGtmTaWv2tvyNLdZmuMWhni3DeKDcDFeS3DU"); 17 | SchnorrSignature sig = pk.schnorr_sign(hash); 18 | string hexsig = string(sig); 19 | mu_assert(strcmp(hexsig.c_str(), "49ece67cead2bd0ec6b926f376e0e17ebb27e744beadbdf4aeed67115470ae2e9ceb0c17f710c3c3c33480b55d8069b81a2894d09d3d759e3bea46f92cd1bd7f") == 0, "schnorr signature is wrong"); 20 | // check verification 21 | PublicKey pub = pk.publicKey(); 22 | mu_assert(pub.schnorr_verify(sig, hash) == true, "schnorr verification failed"); 23 | // check it also works with 02... key 24 | PublicKey pub2; 25 | uint8_t arr[32]; 26 | fromHex("6930f46dd0b16d866d59d1054aa63298b357499cd1862ef16f3f55f1cafceb82", arr, 32); 27 | pub2.from_x(arr, 32); 28 | mu_assert(pub2.schnorr_verify(sig, hash) == true, "schnorr verification failed"); 29 | } 30 | 31 | 32 | MU_TEST_SUITE(test_schnorr) { 33 | MU_RUN_TEST(test_schnorrsign); 34 | } 35 | 36 | int main(int argc, char *argv[]) { 37 | MU_RUN_SUITE(test_schnorr); 38 | MU_REPORT(); 39 | return MU_EXIT_CODE; 40 | } 41 | 42 | #endif // UBTC_TEST 43 | --------------------------------------------------------------------------------