diff --git a/README.md b/README.md index 157c383..b16c204 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # 1. Introduction to *blockchain-crypto-mpc* **blockchain-crypto-mpc** is an open source library released by [Unbound -Tech](https://www.unboundtech.com/company/about/) that provides the +Tech](http://bit.ly/2SpMJ7W) that provides the cryptographic foundation to resolve one of the hardest challenges associated with crypto asset and blockchain applications: **The protection of cryptographic signing keys and seed secrets**. @@ -10,7 +10,7 @@ protection of cryptographic signing keys and seed secrets**. Unbound leverages [secure multiparty computation -(MPC)](https://www.unboundtech.com/technology-distributed-trust-platform/) +(MPC)](http://bit.ly/2Skw8m1) for the protection and management of cryptographic keys and secrets, and provides industry-grade MPC-based solutions for key management, key protection and additional applications. The protocols were designed by @@ -24,7 +24,6 @@ This readme includes an overview of this library, why it is important, what it allows you to achieve, sample use cases, and how to use the library (high level description). -This repository includes a tool for benchmarking the **blockchain-crypto-mpc** library. See [mpc_crypto_bench](https://github.com/unbound-tech/blockchain-crypto-mpc/blob/master/bench/README_MPC_Crypto_Bench.md) in the [bench](./bench) folder for more information. # 2. Who Should Use it? @@ -81,15 +80,11 @@ to use blockchain applications for all.** **blockchain-crypto-mpc** includes a secure MPC implementation of the following algorithms: -- 2-party ECDSA secp256k1: generation and signing - +- 2-party ECDSA secp256k1: generation and signing - 2-party EdDSA ed25519: generation and signing - - 2-party BIP32 (based on the [BIP32 specification](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)): generation, hard derivation, and normal derivation - - Key share refresh - - Zero-knowledge backup The source code is written in C++ and the external API in C. Detailed @@ -131,16 +126,12 @@ them). - Guaranteed non-repudiation; the application server cannot sign any transaction without cooperation from the endpoint device. - - No single point of compromise: Compromising the seed or key material requires the attacker to compromise both the server and the endpoint simultaneously. - - No key or seed material ever appears in the clear throughout its lifecycle, including while in use and during generation. - - Resilient to side-channel attacks. - - A model that empowers a crypto service provider to create an excellent user experience by delivering a wallet service while maintaining a very high security level and granting the users full @@ -167,16 +158,12 @@ of both participants (and communication between them). - Both devices must collaborate and approve any transaction. No single device can approve a transaction. - - No single point of compromise: Compromising the seed or key material requires the attacker to compromise both the laptop and the mobile device simultaneously. - - No key or seed material ever appears in the clear throughout its lifecycle, including while in use and during generation. - - Resilient to side-channel attacks. - - A model that empowers a wallet provider to create an excellent user experience while maintaining a very high security level and granting the users full control of their crypto assets. @@ -223,7 +210,28 @@ the user's device and the Trustee Service, key share B is used by the user's dev It's important to highlight that each of these pairs is completely independent, each is effectively a backup of the same seed. -# 5. Technical Overview and Usage Guidelines +# 5. Benchmarking and Performance + +This repository includes a two different tools for benchmarking the **blockchain-crypto-mpc** library. + +1. MPC Crypto Bench - a tool written C++. See [mpc_crypto_bench](https://github.com/unbound-tech/blockchain-crypto-mpc/blob/master/bench/README.md) in the [bench](./bench) folder for more information. +2. MPC Crypto Python script. See [mpc_crypto](https://github.com/unbound-tech/blockchain-crypto-mpc/blob/master/python/README.md) in the [Python](./python) folder for more information. + +MPC Crypto Bench tests the raw protocols, with no networking involved, while the MPC Crypto Python script is uses a client and server with actual networking. + +Using the Python script, each command was run for 20 iterations and resulted in the following performance numbers: + +| Algorithm | Command | Time (seconds) | +|-----------|----------|:--------------:| +| ECDSA | Generate | 0.945 | +| ECDSA | Sign | 0.015 | +| EdDSA | Generate | 0.003 | +| EdDSA | Sign | 0.003 | + +The tests were run on a server with an Intel Xeon E5-2686 v4 (2.30 GHz) with 32 GB RAM. + + +# 6. Technical Overview and Usage Guidelines Unbound's Blockchain Crypto MPC open source library provides functions @@ -236,7 +244,7 @@ messages that are sent between the peers. Note that the actual communication between peers is not included in this library. ![blockchain-crypto-mpc system](docs/images/os-system.png) -## 5.1 Definitions +## 6.1 Definitions Blockchain Crypto MPC utilizes the following three structures: @@ -245,10 +253,8 @@ Blockchain Crypto MPC utilizes the following three structures: phase of the process or in any location at any time. A key share is a piece of a key, which can be used by Unbound's MPC technology to sign transactions. - 2. **Message** -- Data that is passed to the other peer. The message contains information about the action in progress. - 3. **Context** -- Since each action, such as signing with a key, involves multiple messages between the two peers, the status of the action is preserved in a context. @@ -257,27 +263,23 @@ The **key share**, **message**, and **context** contain varying amounts of information depending on the type action, and therefore they are structures. -## 5.2 Actions +## 6.2 Actions The library provides the following actions: -- 2-party ECDSA secp256k1: generation and signing - +- 2-party ECDSA secp256k1: generation and signing - 2-party EdDSA ed25519: generation and signing - - 2-party BIP32 (based on the [BIP32 specification](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)): generation, hard derivation, and normal derivation - - Key share refresh - - Zero-knowledge backup The library also provides mechanisms to handle serialization, deserialization, and memory management for the key share, message, and context structures. -## 5.3 System Flow +## 6.3 System Flow The system flow is shown in the following figure: @@ -301,11 +303,11 @@ peer can then do any necessary cleanup, such as freeing memory, or copying an updated key share to storage. -### 5.3.1 Peer Roles +### 6.3.1 Peer Roles Peer roles are determined by which peer initiates key generation. This peer must be used for any subsequent key operations, such as signing, derivation, and backup. For example, if peer A generates a key and then peer B wants to initiate a signing process, it should make a request to the peer A to start the process. When complete, the peer A can send the result to peer B. Peer B can verify this result with the *verify* function. -### 5.3.2 Detailed Flow +### 6.3.2 Detailed Flow A detailed flow is described in the following procedure: @@ -329,7 +331,7 @@ Throughout the entire process the same context should be used. If the context ne -### 5.3.3 Example Action +### 6.3.3 Example Action An example of an ECDSA signing action is shown in the following figure. @@ -341,4 +343,3 @@ for initialization. After initialization, each peer calls the finished with the signing process. The signature, which is the result of the signing process, is received by calling the final function, **MPCCrypto_finalEcdsaSign()**, after which the signing process is done. - diff --git a/bench/README_MPC_Crypto_Bench.md b/bench/README.md similarity index 78% rename from bench/README_MPC_Crypto_Bench.md rename to bench/README.md index 4954881..ea78f96 100644 --- a/bench/README_MPC_Crypto_Bench.md +++ b/bench/README.md @@ -4,9 +4,10 @@ ## Build Instructions -First, compile the **blockchain-crypto-mpc** library as described in [build.md](https://github.com/unbound-tech/blockchain-crypto-mpc/blob/master/build.md). +This utility is compiled along with the **blockchain-crypto-mpc** library. Following the build instructions found [here](https://github.com/unbound-tech/blockchain-crypto-mpc/blob/master/build.md). + +The executable is called **mpc_crypto_bench**. -Next, compile the benchmark utility by running `make`. The resulting executable is called **mpc_crypto_bench**. ## Command Line diff --git a/build.md b/build.md index c0e0168..60a7415 100644 --- a/build.md +++ b/build.md @@ -32,6 +32,25 @@ The repository includes a simple makefile for building in Linux. 1. Review the makefile and modify as needed for your environment. 1. Run *make*. +For example, on Ubuntu Linux, use the following: +```sudo add-apt-repository ppa:webupd8team/java +sudo apt-get update +sudo apt-get install oracle-java8-installer +export JAVA_HOME=/usr/lib/jvm/java-8-oracle/ + +sudo apt install make +sudo apt install make-guile +sudo apt-get install gcc +sudo apt-get install g++ +sudo apt-get install openssl +sudo apt-get install libssl-dev + +git clone https://github.com/unbound-tech/blockchain-crypto-mpc.git +cd blockchain-crypto-mpc +make +export LD_LIBRARY_PATH=. +``` + ### Windows The repository includes a Visual Studio solution. diff --git a/python/README.md b/python/README.md new file mode 100644 index 0000000..79960ba --- /dev/null +++ b/python/README.md @@ -0,0 +1,46 @@ +# MPC Crypto Python Script + +**MPC Crypto** is a Python script that can be used to accurately measure the speed of the **blockchain-crypto-mpc** library. It runs **blockchain-crypto-mpc** with a specified algorithm for a number of iterations and then returns that average runtime. The utility strives to measure the raw speed of the **blockchain-crypto-mpc** library, without any delays due to networking. + +## Command Line + +Before running the command line, set the following environment variable, pointing to wherever you compiled the **blockchain-crypto-mpc** library: + +`LD_LIBRARY_PATH=/home/centos/Unbound/blockchain-crypto-mpc` + +Run the utility with the following command: + +``` +python mpc_demo.py \ + --type \ + --command \ + --in_file .bin \ + --data_file .dat \ + --repeat +``` + +where *algorithm* can be one of the following: + +- ECDSA - for ECDSA +- EDDSA - for EdDSA + +The value of *iterations* designates how many times to loop. + +## Example + +To run 10 iterations of ECDSA key signing: + +``` +python mpc_demo.py --type ECDSA --command sign --in_file key_share2.bin --data_file data.dat --repeat 5 +ECDSA signing... +ok +ECDSA signing... +ok +ECDSA signing... +ok +ECDSA signing... +ok +ECDSA signing... +ok +Took 15.4986 ms on average +``` diff --git a/python/mpc_demo.py b/python/mpc_demo.py index 5b97aef..277460f 100644 --- a/python/mpc_demo.py +++ b/python/mpc_demo.py @@ -123,7 +123,7 @@ def run_sign(inShare, cryptoType): with open(args.data_file, "rb") as f: inData = f.read() with obj: - obj.initSign(inData, True) + obj.initSign(inData) exec_mpc_exchange(obj) sig = obj.getSignResult() print("ok") @@ -183,6 +183,7 @@ def run_command(params): def run_server(): serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + serversocket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) serversocket.bind((args.host, args.port)) serversocket.listen(5) @@ -190,12 +191,12 @@ def run_server(): clientsocket, address = serversocket.accept() params = argparse.Namespace() while True: - header = clientsocket.recv(6) + header = clientsocket.recv(3*4) if not header: break - params.command = commands[int.from_bytes(header[:1], 'big')] - params.type = types[int.from_bytes(header[1:2], 'big')] - params.size = int.from_bytes(header[2:], 'big') + params.command = commands[struct.unpack("i", header[:4])[0]] + params.type = types[struct.unpack("i", header[4:8])[0]] + params.size = struct.unpack("i", header[8:])[0] print(params) out, outputFile = run_command(params) @@ -208,10 +209,12 @@ def run_server(): def run_client(): global clientsocket clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + clientsocket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) clientsocket.connect((args.host, args.port)) - header = commands.index(args.command).to_bytes( - 1, 'big') + types.index(args.type).to_bytes(1, 'big') + args.size.to_bytes(4, 'big') + header = struct.pack("i", commands.index(args.command)) + \ + struct.pack("i", types.index(args.type)) + \ + struct.pack("i", args.size) startTime = datetime.datetime.now() for _ in range(args.repeat): clientsocket.send(header) @@ -259,7 +262,6 @@ def run_client(): if not args.command or not args.type: parser.error('Command and Type required for Client') clientsocket = None - if args.server: peer = SERVER run_server()