├── .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 |
--------------------------------------------------------------------------------