More specifically, an Secp256k1 key-pair generator & message/transaction signer where both the enclave and the app are written in pure Rust. Made possible by the fantastic Rust SGX Software Developer Kit by Baidux Labs: https://github.com/baidu/rust-sgx-sdk
Update #4: Now with a branch that can import private keys! (See the import-secret
branch...)
Update #3: Now with full transaction sending capabilities!
Update #2: Now with full transaction-signing capabilities!
Update #1: Now with replay-attack protection!
Intel SGX Ethereum Key Management CLI.
Questions: greg@oraclize.it
Usage: ethkey_sgx [-h | --help]
ethkey_sgx generate [--keyfile=<path>]
ethkey_sgx show public [--keyfile=<path>]
ethkey_sgx show secret [--keyfile=<path>]
ethkey_sgx show address [--keyfile=<path>]
ethkey_sgx destroy [--keyfile=<path>]
ethkey_sgx show nonce [--keyfile=<path>] [--chainid=<uint>]
ethkey_sgx sign msg <message> [--keyfile=<path>] [-n | --noprefix]
ethkey_sgx verify <address> <message> <signature> [--keyfile=<path>] [-n | --noprefix]
ethkey_sgx sendtx [--to=<address>] [--value=<Wei>] [--keyfile=<path>] [--gaslimit=<uint>]
[--gasprice=<Wei>] [--nonce=<uint>] [--data=<string>] [--chainid=<uint>]
ethkey_sgx sign tx [--to=<address>] [--value=<Wei>] [--keyfile=<path>] [--gaslimit=<uint>]
[--gasprice=<Wei>] [--nonce=<uint>] [--data=<string>] [--chainid=<uint>]
Commands:
generate ❍ Generates an secp256k1 keypair inside an SGX enclave, encrypts
them & saves to disk as either ./encrypted_keypair.txt in the
current directory, or at the passed in path.
show secret ❍ Log the private key from the given encrypted keypair to the console.
show nonce ❍ Retrieves the current nonce of the keypair in a given keyfile, for
the network specified via the chain ID parameter:
1 = Ethereum Main-Net (default)
3 = Ropsten Test-Net
4 = Rinkeby Test-Net
42 = Kovan Test-Net
sign tx ❍ Signs a transaction with the given parameters and returns the raw
data ready for broadcasting to the ethereum network. If no nonce is
supplied, the tool will attempt to discover the nonce of the given
keypair for the network the transaction is destined for. See below
for the parameter defaults.
sendtx ❍ Signs a transaction per the above instructions, then sends the
transaction to an Infura node for broadcasting to the chosen network.
Returns the transactions hash if successful.
sign msg ❍ Signs a passed in message using key pair provided, otherwise uses
default keypair if it exists. Defaults to using the ethereum message
prefix and ∴ signatures are ECRecoverable.
verify ❍ Verify a given address signed a given message with a given signature.
destroy ❍ Destroys a given key file's monotonic counters, rendering the keyfile
unusable, before erasing the encrypted keyfile itself. Use with caution!
Options:
-h, --help ❍ Show this usage message.
--keyfile=<path> ❍ Path to desired encrypted keyfile [default: ./encrypted_keypair]
--to=<address> ❍ Destination address of transaction [default: ]
--value=<Wei> ❍ Amount of ether to send with transaction in Wei [default: 0]
--gaslimit=<uint> ❍ Amount of gas to send with transaction [default: 210000]
--gasprice=<Wei> ❍ Gas price for transaction in Wei [default: 20000000000]
--chainid=<uint> ❍ ID of desired chain for transaction [default: 1]
--nonce=<uint> ❍ Nonce of transaction in Wei [default: -1]
--data=<string> ❍ Additional data to send with transaction [default: ]
-n, --noprefix ❍ Does not add the ethereum message prefix when signing or verifying
a signed message. Messages signed with no prefix are NOT ECRecoverable!
❍ Pull requisite files:
Pull the Rust SGX SDK Docker image
❍ sgx-nuc@~$ docker pull baiduxlab/sgx-rust
Clone this Repo
❍ sgx-nuc@~$ git clone https://gitlab.com/gskapka/secp256k1-enclave-rust.git
❍ Prepare the Docker Container:
If using SIMULATION mode:
❍ sgx-nuc@~$ sudo docker run -v /path/to/secp256k1-enclave-rust:/root/keygen -ti baiduxlab/sgx-rust
Else if using HARDWARE mode:
❍ sgx-nuc@~$ sudo docker run -v/path/to/secp256k1-enclave-rust:/root/keygen -ti --device /dev/isgx baiduxlab/sgx-rust
Rebuild the tool chain:
❍ sgx-nuc-docker@~# rustup default nightly-2018-10-01-x86_64-unknown-linux-gnu
Add required components:
❍ sgx-nuc-docker@~# rustup component add rust-src
Finally, if using HARDWARE mode, import the service:_
❍ sgx-nuc-docker@~# /opt/intel/libsgx-enclave-common/aesm/aesm_service &
❍ Prepare the keygen:
In the ❍ sgx-nuc-docker@~/keygen
directory inside the docker, first ensure the desired mode (SW or HW) is set correctly inside the Makefile
:
// ... Beginning of file ...
######## SGX SDK Settings ########
SGX_SDK ?= /opt/intel/sgxsdk
SGX_MODE ?= HW // <-- This option. HW for Hardware or SW for software.
SGX_ARCH ?= x64
// ... Remainder of file ...
Next, set the environment variable inside the docker to the desired mode:
❍ sgx-nuc-docker@~/keygen# export SGX_MODE=HW
Then build the project:
❍ sgx-nuc-docker@~/keygen# make
And finally run it to see the usage notes:
❍ sgx-nuc-docker@~/keygen# cd bin && ./ethkey_sgx
✅ Refactor to lib crate.
✅ Make CLI with Docopt.
🔲 Remotely attest!
🔲 Save key files as their corresponding address names!
🔲 Add more tests!
✅ Make ECRecoverable sigs.
🔲 Stream to the enc. to allow file encryption.
🔲 Add rudimentary password protection.
🔲 Use mister enclave instead of mister signer!
🔲 Make threaded to have vanity addresses (can limit tried?)
✅ Abstract out generic enclave funcs (mem. allocing etc)
✅ Separate the app from the SDK repo enclave to make it lean and mean.
✅ Add transaction signing.
🔲 Make a stand alone binary for D/L.
🔲 Make a getter for enclave measurement.
🔲 Remove show public
since it's useless.
🔲 Remove ability to show private key for prod. usage.
🔲 Make a nonce getter.
✅ Add a monotonic counter to the key accesses.
✅ Add a monotonic counter to tx signing events.
✅ Add SGX time checks to stop replay attacks.