From b63a7228a51e5c852dbe0ab8dad066d57864e888 Mon Sep 17 00:00:00 2001 From: josh Date: Mon, 9 Sep 2019 19:03:19 -0700 Subject: [PATCH 1/4] update compiler and switch to tinybip --- Cargo.lock | 94 ++++++++++---------------------------------------- Cargo.toml | 2 +- rust-toolchain | 2 +- 3 files changed, 20 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20f32d9..2eafe3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,20 +62,6 @@ dependencies = [ "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bip39" -version = "0.6.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bitflags" version = "1.0.4" @@ -180,15 +166,6 @@ dependencies = [ "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-deque" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-deque" version = "0.6.3" @@ -207,20 +184,6 @@ dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-epoch" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-epoch" version = "0.7.1" @@ -242,14 +205,6 @@ dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-utils" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-utils" version = "0.6.5" @@ -499,7 +454,6 @@ dependencies = [ name = "hedera" version = "0.4.2-alpha.0" dependencies = [ - "bip39 0.6.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -523,6 +477,7 @@ dependencies = [ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "simple_asn1 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -788,7 +743,7 @@ dependencies = [ [[package]] name = "once_cell" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -875,7 +830,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1091,27 +1045,6 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rayon" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rdrand" version = "0.4.0" @@ -1351,6 +1284,20 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-bip39" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tls-api" version = "0.1.20" @@ -1864,7 +1811,6 @@ dependencies = [ "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bip39 0.6.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7059804e226b3ac116519a252d7f5fb985a5ccc0e93255e036a5f7e7283323f4" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" @@ -1878,13 +1824,10 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" "checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dae47cc3529cdab597dbc8b606e565707209b506e55848f3c15679214a56c956" @@ -1943,7 +1886,7 @@ dependencies = [ "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" -"checksum once_cell 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "53075ac5dbd2798cfbcf9f710f2737de031d8076c192d8fe66fb23f639ccbdf4" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" "checksum once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd38c1bb51148ca239ec38ef1bb4f7570d432861f03e91774d53b01c2ba2132f" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" @@ -1977,8 +1920,6 @@ dependencies = [ "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" -"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" @@ -2011,6 +1952,7 @@ dependencies = [ "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" "checksum tls-api 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e452fe2fdf40a10715adb3a5f244c7411cdf2ecc887b07160310939785db9182" "checksum tls-api-stub 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "25a2dcddd0fd52bdbedf9b4f0fd1cb884abfa0984e6a54121d4cefdf3d234e4c" "checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" diff --git a/Cargo.toml b/Cargo.toml index 65a8a10..503dc84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ query_interface = "0.3.5" httpbis = "0.7.0" log = "0.4.8" try_from = "0.3.2" -bip39 = "0.6.0-beta.1" +tiny-bip39 = "0.6.2" rand_chacha = "0.1.1" tokio = { version = "0.2.0-alpha.4" } futures = { version = "0.3.0-alpha.18", package = "futures-preview", features = [ "compat" ] } diff --git a/rust-toolchain b/rust-toolchain index 8506edd..7058602 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2019-09-06 +nightly-2019-09-10 From 087c355da9ab44d8604465ba2dcb5b1bc09d4232 Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 11 Sep 2019 21:16:51 -0700 Subject: [PATCH 2/4] bring key and mnemonic gen more inline with the js and java libraries --- Cargo.lock | 21 +++++++++- Cargo.toml | 6 ++- examples/create_account.rs | 3 +- examples/generate_key.rs | 2 +- examples/update_account.rs | 1 - src/crypto.rs | 79 ++++++++++++++++++++++++++++---------- 6 files changed, 85 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2eafe3d..4a90a4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -408,6 +408,16 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "getrandom" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "glob" version = "0.3.0" @@ -459,20 +469,22 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "grpc 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "httpbis 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "protoc-rust-grpc 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "query_interface 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1748,6 +1760,11 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -1852,6 +1869,7 @@ dependencies = [ "checksum futures-sink-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "e9b65a2481863d1b78e094a07e9c0eed458cc7dc6e72b22b7138b8a67d924859" "checksum futures-util-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "7df53daff1e98cc024bf2720f3ceb0414d96fbb0a94f3cad3a5c3bf3be1d261c" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum grpc 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e530ef7894a104a1c8525ce68787b3491efa2098ce5e5454e8324ea78893548" "checksum grpc-compiler 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b07f140d998d8940880e464f3fd291052618199432e91e59ae5c5075c0c8a40c" @@ -1992,6 +2010,7 @@ dependencies = [ "checksum unix_socket 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6aa2700417c405c38f5e6902d699345241c28c0b7ade4abaad71e35a87eb1564" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 503dc84..aa21757 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ rand_core = "0.4.0" sha2 = "0.8.0" sha3 = "0.8.2" hex = "0.3.2" +hmac = "0.7.0" failure = "0.1.5" simple_asn1 = "0.4.0" failure_derive = "0.1.5" @@ -26,13 +27,14 @@ protobuf = "2.8.1" itertools = "0.8.0" chrono = "0.4.9" parking_lot = "0.9.0" +pbkdf2 = { version = "0.3.0", default-features = false } +getrandom = "0.1.12" grpc = "0.6.1" query_interface = "0.3.5" httpbis = "0.7.0" log = "0.4.8" try_from = "0.3.2" -tiny-bip39 = "0.6.2" -rand_chacha = "0.1.1" +tiny-bip39 = { version="0.6.2", default-features = false } tokio = { version = "0.2.0-alpha.4" } futures = { version = "0.3.0-alpha.18", package = "futures-preview", features = [ "compat" ] } diff --git a/examples/create_account.rs b/examples/create_account.rs index 74c468e..d70325c 100644 --- a/examples/create_account.rs +++ b/examples/create_account.rs @@ -1,5 +1,4 @@ use failure::{format_err, Error}; -use futures::FutureExt; use hedera::{Client, SecretKey, Status}; use std::{env, thread::sleep, time::Duration}; @@ -7,7 +6,7 @@ use std::{env, thread::sleep, time::Duration}; async fn main() -> Result<(), Error> { pretty_env_logger::try_init()?; - let (secret, _) = SecretKey::generate(""); + let secret = SecretKey::generate(); let public = secret.public(); println!("secret = {}", secret); diff --git a/examples/generate_key.rs b/examples/generate_key.rs index d9c8b4d..ba8c2f6 100644 --- a/examples/generate_key.rs +++ b/examples/generate_key.rs @@ -1,7 +1,7 @@ use hedera::SecretKey; fn main() { - let (secret, mnemonic) = SecretKey::generate(""); + let (secret, mnemonic) = SecretKey::generate_mnemonic(); let public = secret.public(); println!("secret = {}", secret); diff --git a/examples/update_account.rs b/examples/update_account.rs index 6bc31c2..c4f5044 100644 --- a/examples/update_account.rs +++ b/examples/update_account.rs @@ -1,5 +1,4 @@ use failure::{format_err, Error}; -use futures::FutureExt; use hedera::{Client, Status}; use std::{env, thread::sleep, time::Duration}; diff --git a/src/crypto.rs b/src/crypto.rs index ad98ae4..6635ba1 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -1,13 +1,11 @@ use crate::proto::{self, ToProto}; -use bip39::{Language, Mnemonic, MnemonicType, Seed}; +use bip39::{Language, Mnemonic}; use ed25519_dalek; use failure::{bail, err_msg, Error}; use failure_derive::Fail; use hex; use num::BigUint; use once_cell::{sync::Lazy}; -use rand_core::SeedableRng; -use rand_chacha::ChaChaRng; use simple_asn1::{ der_decode, der_encode, oid, to_der, ASN1Block, ASN1Class, ASN1DecodeErr, ASN1EncodeErr, FromASN1, ToASN1, OID, @@ -17,6 +15,7 @@ use std::{ str::FromStr, }; use try_from::{TryFrom, TryInto}; +use hmac::Hmac; // Types used for (de-)serializing public and secret keys from ASN.1 byte // streams. @@ -370,25 +369,54 @@ impl TryFrom for PublicKey { pub struct SecretKey(ed25519_dalek::SecretKey); impl SecretKey { - /// Generate a `SecretKey` with a BIP-39 mnemonic using a cryptographically + /// Generate a `SecretKey` with 32 cryptographically random bytes + pub fn generate() -> Self { + let mut buf = [0u8; 32]; + + getrandom::getrandom(&mut buf).expect("Could not retrieve entropy from the os"); + + let bytes = Self::derive_seed(&buf); + + // this should never fail unless getrandom fails which will cause a panic + SecretKey(ed25519_dalek::SecretKey::from_bytes(&bytes).unwrap()) + } + + /// Generate a `SecretKey` with 32 bytes of provided entropy + pub fn generate_from_entropy(entropy: &[u8; 32]) -> Self { + // this should never fail since entropy is required to be a 32-length u8 array + SecretKey(ed25519_dalek::SecretKey::from_bytes(entropy).unwrap()) + } + + /// Generate a `SecretKey` alongside a BIP-39 mnemonic using a cryptographically /// secure random number generator. - /// - /// The `password` is required with the mnemonic to reproduce the secret key. - pub fn generate(password: &str) -> (Self, String) { - let mnemonic = Mnemonic::new(MnemonicType::Words24, Language::English); + pub fn generate_mnemonic() -> (Self, String) { + let mut entropy = [0u8; 32]; - let secret = Self::generate_with_mnemonic(&mnemonic, password); + getrandom::getrandom(&mut entropy).expect("Could not retrieve entropy from the os"); + + // this should never fail as 32 is a valid entropy length + let mnemonic = Mnemonic::from_entropy(&entropy, Language::English).unwrap(); + let secret = Self::generate_from_entropy(&entropy); (secret, mnemonic.into_phrase()) } - fn generate_with_mnemonic(mnemonic: &Mnemonic, password: &str) -> Self { - let mut seed: [u8; 32] = Default::default(); + /// Duplicating what is done here: + /// https://github.com/hashgraph/hedera-keygen-java/blob/master/src/main/java/com/hedera/sdk/keygen/CryptoUtils.java#L43 + fn derive_seed(entropy: &[u8]) -> [u8; 32] { + let password = entropy + .into_iter() + .chain([u8::max_value(); 8].iter()) + .map(|u| { *u }) + .collect::>(); + + let salt = [u8::max_value()]; - seed.copy_from_slice(&Seed::new(&mnemonic, password).as_bytes()[0..32]); + let mut seed = [0u8; 32]; - let mut rng = ChaChaRng::from_seed(seed); - SecretKey(ed25519_dalek::SecretKey::generate(&mut rng)) + pbkdf2::pbkdf2::>(&password, &salt, 2048, &mut seed); + + seed } /// Construct a `SecretKey` from a slice of bytes. @@ -421,15 +449,25 @@ impl SecretKey { } /// Re-construct a `SecretKey` from the supplied mnemonic and password. - pub fn from_mnemonic(mnemonic: &str, password: &str) -> Result { + pub fn from_mnemonic(mnemonic: &str) -> Result { let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English)?; - Ok(Self::generate_with_mnemonic(&mnemonic, password)) + let mut entropy = [0u8; 32]; + + let seed_entropy = mnemonic.entropy(); + + for i in 0..32 { + entropy[i] = seed_entropy[i]; + } + + //let entropy: &[u8; 32] = vec!(mnemonic.entropy()).try_into()?; + + Ok(Self::generate_from_entropy(&entropy)) } /// Return the `SecretKey` as raw bytes. #[inline] - pub fn as_bytes(&self) -> &[u8; ed25519_dalek::PUBLIC_KEY_LENGTH] { + pub fn as_bytes(&self) -> &[u8; ed25519_dalek::SECRET_KEY_LENGTH] { self.0.as_bytes() } @@ -646,7 +684,8 @@ mod tests { #[test] fn test_generate() -> Result<(), Error> { - let (key, _mnemonic) = SecretKey::generate(""); + let key = SecretKey::generate(); + let signature = key.sign(MESSAGE.as_bytes()); let verified = key.public().verify(MESSAGE.as_bytes(), &signature)?; @@ -671,8 +710,8 @@ mod tests { #[test] fn test_reconstruct() -> Result<(), Error> { - let (secret1, mnemonic) = SecretKey::generate("this-is-not-a-password"); - let secret2 = SecretKey::from_mnemonic(&mnemonic, "this-is-not-a-password")?; + let (secret1, mnemonic) = SecretKey::generate_mnemonic(); + let secret2 = SecretKey::from_mnemonic(&mnemonic)?; assert_eq!(secret1.as_bytes(), secret2.as_bytes()); From fc8b848d3371f2ad8cd50924470a86d80850f6dc Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 14 Sep 2019 02:02:48 -0700 Subject: [PATCH 3/4] reverts to proper slip-10/bip-32 based key generation --- src/crypto.rs | 177 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 118 insertions(+), 59 deletions(-) diff --git a/src/crypto.rs b/src/crypto.rs index 6635ba1..6e64de8 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -1,5 +1,5 @@ use crate::proto::{self, ToProto}; -use bip39::{Language, Mnemonic}; +use bip39::{Language, Mnemonic, MnemonicType, Seed}; use ed25519_dalek; use failure::{bail, err_msg, Error}; use failure_derive::Fail; @@ -15,7 +15,9 @@ use std::{ str::FromStr, }; use try_from::{TryFrom, TryInto}; -use hmac::Hmac; +use hmac::{Hmac, Mac}; +use sha2::Sha512; +use failure::_core::ops::Deref; // Types used for (de-)serializing public and secret keys from ASN.1 byte // streams. @@ -366,61 +368,58 @@ impl TryFrom for PublicKey { /// An EdDSA secret key. #[repr(C)] -pub struct SecretKey(ed25519_dalek::SecretKey); +pub struct SecretKey { + pub value: ed25519_dalek::SecretKey, + chain_code: Option<[u8; 32]> +} impl SecretKey { /// Generate a `SecretKey` with 32 cryptographically random bytes + /// + /// This `SecretKey` will _not_ support child key derivation. pub fn generate() -> Self { - let mut buf = [0u8; 32]; - - getrandom::getrandom(&mut buf).expect("Could not retrieve entropy from the os"); + let mut bytes:[u8; 32] = Default::default(); - let bytes = Self::derive_seed(&buf); + getrandom::getrandom(&mut bytes) + .expect("Could not retrieve secure entropy from the os"); - // this should never fail unless getrandom fails which will cause a panic - SecretKey(ed25519_dalek::SecretKey::from_bytes(&bytes).unwrap()) + Self::generate_from_entropy(&bytes) } /// Generate a `SecretKey` with 32 bytes of provided entropy + /// + /// This `SecretKey` will _not_ support child key derivation. + #[inline] pub fn generate_from_entropy(entropy: &[u8; 32]) -> Self { - // this should never fail since entropy is required to be a 32-length u8 array - SecretKey(ed25519_dalek::SecretKey::from_bytes(entropy).unwrap()) + // this should never fail since 32 byte arrays are guaranteed to be compatible + Self::from_bytes(entropy).unwrap() } /// Generate a `SecretKey` alongside a BIP-39 mnemonic using a cryptographically /// secure random number generator. + /// + /// Generated `SecretKey` will support deriving child keys with `.derive_child()`. + #[inline] pub fn generate_mnemonic() -> (Self, String) { - let mut entropy = [0u8; 32]; - - getrandom::getrandom(&mut entropy).expect("Could not retrieve entropy from the os"); - - // this should never fail as 32 is a valid entropy length - let mnemonic = Mnemonic::from_entropy(&entropy, Language::English).unwrap(); - let secret = Self::generate_from_entropy(&entropy); - - (secret, mnemonic.into_phrase()) + Self::generate_mnemonic_with_passphrase("") } - /// Duplicating what is done here: - /// https://github.com/hashgraph/hedera-keygen-java/blob/master/src/main/java/com/hedera/sdk/keygen/CryptoUtils.java#L43 - fn derive_seed(entropy: &[u8]) -> [u8; 32] { - let password = entropy - .into_iter() - .chain([u8::max_value(); 8].iter()) - .map(|u| { *u }) - .collect::>(); - - let salt = [u8::max_value()]; - - let mut seed = [0u8; 32]; - - pbkdf2::pbkdf2::>(&password, &salt, 2048, &mut seed); + /// Generate a `SecretKey` alongside a BIP-39 mnemonic using a cryptographically + /// secure random number generate and provided passphrase + /// + /// Generated `SecretKey` will support deriving child keys with `.derive_child()`. + pub fn generate_mnemonic_with_passphrase(passphrase: &str) -> (Self, String) { + let mnemonic_phrase = Mnemonic::new(MnemonicType::Words24, Language::English).into_phrase(); - seed + // Cannot fail since it is being passed in compatible generated values + (Self::from_mnemonic_with_passphrase(&mnemonic_phrase, passphrase).unwrap(), mnemonic_phrase) } /// Construct a `SecretKey` from a slice of bytes. /// Bytes are expected to be either a raw key or encoded in ASN.1. + /// + /// This `SecretKey` will _not_ support child key derivation as it is impossible + /// to determine if the original key was generated with compatibility pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result { let bytes = bytes.as_ref(); @@ -429,9 +428,10 @@ impl SecretKey { { // If the buffer looks like a {secret}{public} byte string; just pull the secret // key bytes off of it - return Ok(SecretKey(ed25519_dalek::SecretKey::from_bytes( - &bytes[..ed25519_dalek::SECRET_KEY_LENGTH], - )?)); + return Ok(SecretKey{ + value: ed25519_dalek::SecretKey::from_bytes(&bytes[..ed25519_dalek::SECRET_KEY_LENGTH], )?, + chain_code: None + }); } let info: PrivateKeyInfo = der_decode(&bytes)?; @@ -443,32 +443,56 @@ impl SecretKey { ); } - Ok(SecretKey(ed25519_dalek::SecretKey::from_bytes( - &info.private_key[2..], - )?)) + Ok(SecretKey{ + value: ed25519_dalek::SecretKey::from_bytes(&info.private_key[2..],)?, + chain_code: None + }) } - /// Re-construct a `SecretKey` from the supplied mnemonic and password. + /// Re-construct a `SecretKey` from a supplied 24-word mnemonic and passphrase. + /// + /// There is no corresponding `to_mnemonic()` as the mnemonic cannot be recovered from the key. + /// + /// Mnemonics generated by the Android and iOS wallets will work + /// + /// Returned key will support deriving child keys with `.derive_child()` + #[inline] pub fn from_mnemonic(mnemonic: &str) -> Result { + Self::from_mnemonic_with_passphrase(mnemonic, "") + } + + /// Re-construct a `SecretKey` from a supplied 24-word mnemonic and passphrase. + /// + /// There is no corresponding `to_mnemonic_with_passphrase()` as the mnemonic cannot be + /// recovered from the key. + /// + /// Mnemonics generated by the Android and iOS wallets will work + /// + /// Returned key will support deriving child keys with `.derive_child()` + pub fn from_mnemonic_with_passphrase(mnemonic: &str, passphrase: &str) -> Result { let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English)?; - let mut entropy = [0u8; 32]; + let seed = Seed::new(&mnemonic, passphrase); - let seed_entropy = mnemonic.entropy(); + let mut key_bytes: [u8; 32] = Default::default(); + key_bytes.copy_from_slice(&seed.as_bytes()[0..32]); - for i in 0..32 { - entropy[i] = seed_entropy[i]; - } + let mut chain_code: [u8; 32] = Default::default(); + chain_code.copy_from_slice(&seed.as_bytes()[32..64]); - //let entropy: &[u8; 32] = vec!(mnemonic.entropy()).try_into()?; + for i in [44u32, 3030u32, 0u32, 0u32].iter() { + let (new_key_bytes, new_chain_code) = Self::derive_child_key_bytes(&key_bytes, &chain_code, i)?; - Ok(Self::generate_from_entropy(&entropy)) - } + key_bytes.copy_from_slice(&new_key_bytes); + chain_code.copy_from_slice(&new_chain_code); + } - /// Return the `SecretKey` as raw bytes. - #[inline] - pub fn as_bytes(&self) -> &[u8; ed25519_dalek::SECRET_KEY_LENGTH] { - self.0.as_bytes() + let secret_key = SecretKey { + value: ed25519_dalek::SecretKey::from_bytes(&key_bytes)?, + chain_code: Some(chain_code) + }; + + Ok(secret_key) } /// Format a `SecretKey` as a vec of bytes in ASN.1 format. @@ -477,7 +501,7 @@ impl SecretKey { algorithm: AlgorithmIdentifier { algorithm: OID_ED25519.clone(), }, - private_key: self.0.to_bytes().to_vec(), + private_key: self.to_bytes().to_vec(), }) // NOTE: Not possible to fail. Only fail case the library has is if OIDs are // given incorrectly. @@ -487,23 +511,49 @@ impl SecretKey { /// Derive a `PublicKey` from this `SecretKey`. #[inline] pub fn public(&self) -> PublicKey { - PublicKey(ed25519_dalek::PublicKey::from(&self.0)) + PublicKey(ed25519_dalek::PublicKey::from(&self.value)) } /// Sign a message with this `SecretKey`. #[inline] pub fn sign(&self, message: impl AsRef<[u8]>) -> Signature { Signature( - ed25519_dalek::ExpandedSecretKey::from(&self.0) + ed25519_dalek::ExpandedSecretKey::from(&self.value) .sign(message.as_ref(), &self.public().0), ) } + + /// SLIP-10/BIP-32 child key derivation + fn derive_child_key_bytes(parent_key: &[u8; 32], chain_code: &[u8; 32], index: &u32) -> Result<([u8; 32], [u8; 32]), Error> { + // This can't fail since 32 bytes is a valid key length + let mut hmac = Hmac::::new_varkey(chain_code).unwrap(); + + let mut input= [0u8; 37]; + + input[0] = 0u8; + input[1..33].copy_from_slice(parent_key); + input[34..37].copy_from_slice(&index.to_be_bytes()); + + input[33] = input[33] | 128u8; + + hmac.input(&input); + + let hmac = hmac.result().code(); + + let mut new_key_bytes: [u8; 32] = Default::default(); + let mut chain_code: [u8; 32] = Default::default(); + new_key_bytes.copy_from_slice(&hmac.as_slice()[0..32]); + chain_code.copy_from_slice(&hmac.as_slice()[32..64]); + + Ok((new_key_bytes, chain_code)) + } + } impl Clone for SecretKey { #[inline] fn clone(&self) -> Self { - Self::from_bytes(self.0.as_bytes()).unwrap() + Self::from_bytes(self.as_bytes()).unwrap() } } @@ -555,6 +605,15 @@ impl Debug for SecretKey { } } +impl Deref for SecretKey { + type Target = ed25519_dalek::SecretKey; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.value + } +} + /// Format a `SecretKey` as a hex representation of its bytes in ASN.1 format. impl Display for SecretKey { #[inline] @@ -653,7 +712,7 @@ mod tests { let secret_key2: SecretKey = KEY_SECRET_HEX.parse()?; assert_eq!(public_key1, public_key2); - assert_eq!(secret_key1.0.as_bytes(), secret_key2.0.as_bytes()); + assert_eq!(secret_key1.as_bytes(), secret_key2.as_bytes()); assert_eq!(public_key1, secret_key1.public()); assert_eq!(public_key2, secret_key2.public()); assert_eq!(secret_key2.public(), secret_key1.public()); From 7a595895dfdf40b685b63472bbab9ca59d2e8b4d Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 14 Sep 2019 02:26:22 -0700 Subject: [PATCH 4/4] add derive child key for Private Keys --- src/crypto.rs | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/crypto.rs b/src/crypto.rs index 6e64de8..9aae7aa 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -313,8 +313,7 @@ impl PublicKey { } } -/// Construct a `PublicKey` from a hex representation of a raw or ASN.1 encoded -/// key. +/// Construct a `PublicKey` from a hex representation of a raw or ASN.1 encoded key. impl FromStr for PublicKey { type Err = Error; @@ -468,7 +467,7 @@ impl SecretKey { /// /// Mnemonics generated by the Android and iOS wallets will work /// - /// Returned key will support deriving child keys with `.derive_child()` + /// Returned key will support deriving child keys with `.derive_child_key(index)` pub fn from_mnemonic_with_passphrase(mnemonic: &str, passphrase: &str) -> Result { let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English)?; @@ -495,6 +494,22 @@ impl SecretKey { Ok(secret_key) } + /// Derive a new private key at the given wallet index. + /// + /// Currently fails if the key was not generated with `generate_mnemonic` or `generated_mnemonic_with_passphrase` + /// or reconstructed with `from_mnemonic` or `from_mnemonic_with_passphrase` + pub fn derive_child_key(&self, index: u32) -> Result { + let chain_code = self.chain_code + .map_or(Err(err_msg("this Ed25519 private key does not support key derivation")), |cc| {Ok(cc)})?; + + let (key_bytes, chain_code) = Self::derive_child_key_bytes(self.as_bytes(), &chain_code, &index)?; + + Ok(SecretKey{ + value: ed25519_dalek::SecretKey::from_bytes(&key_bytes)?, + chain_code: Some(chain_code) + }) + } + /// Format a `SecretKey` as a vec of bytes in ASN.1 format. pub fn to_encoded_bytes(&self) -> Vec { der_encode(&PrivateKeyInfo { @@ -532,7 +547,7 @@ impl SecretKey { input[0] = 0u8; input[1..33].copy_from_slice(parent_key); - input[34..37].copy_from_slice(&index.to_be_bytes()); + input[33..37].copy_from_slice(&index.to_be_bytes()); input[33] = input[33] | 128u8; @@ -767,6 +782,7 @@ mod tests { Ok(()) } + #[test] fn test_reconstruct() -> Result<(), Error> { let (secret1, mnemonic) = SecretKey::generate_mnemonic(); @@ -776,4 +792,16 @@ mod tests { Ok(()) } + + #[test] + fn test_reconstruct_with_passphrase() -> Result<(), Error> { + let passphrase = "HelloHedera!"; + + let (secret1, mnemonic) = SecretKey::generate_mnemonic_with_passphrase(passphrase); + let secret2 = SecretKey::from_mnemonic_with_passphrase(&mnemonic, passphrase)?; + + assert_eq!(secret1.as_bytes(), secret2.as_bytes()); + + Ok(()) + } }