From b1461cc48d692d859376fcd62bf4e9d11dc59459 Mon Sep 17 00:00:00 2001 From: Rohit Narurkar Date: Mon, 11 Jan 2021 15:09:14 +0530 Subject: [PATCH] Support for encrypted JSON keystore (#138) * feat: add support for encrypted json keystores * fix: ignore gitkeep file from keystore tests * feat: use tempfile crate for temporary test dir/files --- Cargo.lock | 266 +++++++++++++++-------- ethers-core/src/types/signature.rs | 2 +- ethers-signers/Cargo.toml | 4 +- ethers-signers/src/wallet/private_key.rs | 75 ++++++- 4 files changed, 254 insertions(+), 93 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64fae011..dc9b7d8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,15 +244,9 @@ checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "bytes" @@ -441,9 +435,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.0.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8492de420e9e60bc9a1d66e2dbb91825390b738a388606600663fc529b4b307" +checksum = "f627126b946c25a4638eec0ea634fc52506dea98db118aae985118ce7c3d723f" dependencies = [ "byteorder", "digest", @@ -545,6 +539,20 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "eth-keystore" +version = "0.1.0" +source = "git+https://github.com/roynalnaruto/eth-keystore-rs#32777a4bfbd6edc804c88b702b8ffa83546a46c9" +dependencies = [ + "hex", + "rand 0.7.3", + "rust-crypto", + "serde", + "serde_json", + "thiserror", + "uuid", +] + [[package]] name = "ethabi-next" version = "13.0.0" @@ -618,7 +626,7 @@ dependencies = [ "futures-util", "hex", "once_cell", - "pin-project 1.0.3", + "pin-project 1.0.4", "serde", "serde_json", "thiserror", @@ -659,7 +667,7 @@ version = "0.1.3" dependencies = [ "arrayvec", "bincode", - "bytes 1.0.0", + "bytes", "ecdsa", "elliptic-curve", "ethabi-next", @@ -712,7 +720,7 @@ dependencies = [ "futures-timer", "futures-util", "hex", - "pin-project 1.0.3", + "pin-project 1.0.4", "reqwest", "serde", "serde_json", @@ -731,6 +739,7 @@ dependencies = [ "async-trait", "coins-ledger", "elliptic-curve", + "eth-keystore", "ethers", "ethers-core", "futures-executor", @@ -740,6 +749,7 @@ dependencies = [ "serde", "serde_json", "sha2", + "tempfile", "thiserror", "tokio", "yubihsm", @@ -811,6 +821,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "1.1.0" @@ -819,9 +835,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0" +checksum = "c70be434c505aee38639abccb918163b63158a4b4bb791b45b7023044bdc3c9c" dependencies = [ "futures-channel", "futures-core", @@ -834,9 +850,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64" +checksum = "f01c61843314e95f96cc9245702248733a3a3d744e43e2e755e3c7af8348a0a9" dependencies = [ "futures-core", "futures-sink", @@ -844,15 +860,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" +checksum = "db8d3b0917ff63a2a96173133c02818fac4a746b0a57569d3baca9ec0e945e08" [[package]] name = "futures-executor" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65" +checksum = "9ee9ca2f7eb4475772cf39dd1cd06208dce2670ad38f4d9c7262b3e15f127068" dependencies = [ "futures-core", "futures-task", @@ -862,15 +878,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb" +checksum = "e37c1a51b037b80922864b8eed90692c5cd8abd4c71ce49b77146caa47f3253b" [[package]] name = "futures-macro" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556" +checksum = "0f8719ca0e1f3c5e34f3efe4570ef2c0610ca6da85ae7990d472e9cbfba13664" dependencies = [ "proc-macro-hack", "proc-macro2", @@ -880,15 +896,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d" +checksum = "f6adabac1290109cfa089f79192fb6244ad2c3f1cc2281f3e1dd987592b71feb" [[package]] name = "futures-task" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d" +checksum = "a92a0843a2ff66823a8f7c77bffe9a09be2b64e533562c412d63075643ec0038" dependencies = [ "once_cell", ] @@ -901,9 +917,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2" +checksum = "036a2107cdeb57f6d7322f1b6c363dad67cd63ca3b7d1b925bdf75bd5d96cda9" dependencies = [ "futures-channel", "futures-core", @@ -912,13 +928,19 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project 1.0.3", + "pin-project-lite", "pin-utils", "proc-macro-hack", "proc-macro-nested", "slab", ] +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + [[package]] name = "generic-array" version = "0.14.4" @@ -931,24 +953,24 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4" +checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "wasi 0.10.1+wasi-snapshot-preview1", ] [[package]] @@ -980,7 +1002,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b67e66362108efccd8ac053abafc8b7a8d86a37e6e48fc4f6f7485eb5e9e6a5" dependencies = [ - "bytes 1.0.0", + "bytes", "fnv", "futures-core", "futures-sink", @@ -1044,11 +1066,11 @@ dependencies = [ [[package]] name = "http" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84129d298a6d57d246960ff8eb831ca4af3f96d29e2e28848dae275408658e26" +checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" dependencies = [ - "bytes 0.5.6", + "bytes", "fnv", "itoa", ] @@ -1059,7 +1081,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" dependencies = [ - "bytes 1.0.0", + "bytes", "http", ] @@ -1081,7 +1103,7 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12219dc884514cb4a6a03737f4413c0e01c23a1b059b0156004b23f1e19dccbe" dependencies = [ - "bytes 1.0.0", + "bytes", "futures-channel", "futures-core", "futures-util", @@ -1091,7 +1113,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project 1.0.3", + "pin-project 1.0.4", "socket2", "tokio", "tower-service", @@ -1168,7 +1190,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" dependencies = [ - "bytes 1.0.0", + "bytes", ] [[package]] @@ -1219,9 +1241,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" [[package]] name = "libflate" @@ -1243,9 +1265,9 @@ checksum = "3286f09f7d4926fc486334f28d8d2e6ebe4f7f9994494b6dab27ddfad2c9b11b" [[package]] name = "libusb1-sys" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3b8385bdc8931a82a0865a3a7285e2c28e41287824dc92c7724b7759a0c685" +checksum = "be241693102a24766d0b8526c8988771edac2842630d7e730f8e9fbc014f3703" dependencies = [ "cc", "libc", @@ -1506,11 +1528,11 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a83804639aad6ba65345661744708855f9fbcb71176ea8d28d05aeb11d975e7" +checksum = "95b70b68509f17aa2857863b6fa00bf21fc93674c7a8893de2f469f6aa7ca2f2" dependencies = [ - "pin-project-internal 1.0.3", + "pin-project-internal 1.0.4", ] [[package]] @@ -1526,9 +1548,9 @@ dependencies = [ [[package]] name = "pin-project-internal" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7bcc46b8f73443d15bc1c5fecbb315718491fa9187fa483f0e359323cde8b3a" +checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71" dependencies = [ "proc-macro2", "quote", @@ -1537,9 +1559,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" +checksum = "ba36e0a6cc5a4c645073f4984f1ed55d09f5857d4de7c14550baa81a39ef5a17" [[package]] name = "pin-utils" @@ -1647,13 +1669,36 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64de9a0c5361e034f1aefc9f71a86871ec870e766fe31a009734a989b329286a" +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.15", + "getrandom 0.1.16", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", @@ -1662,13 +1707,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76330fb486679b4ace3670f117bbc9e16204005c4bde9c4bd372f45bed34f12" +checksum = "c24fcd450d3fa2b592732565aa4f17a27a61c65ece4726353e000939b0edee34" dependencies = [ "libc", "rand_chacha 0.3.0", - "rand_core 0.6.0", + "rand_core 0.6.1", "rand_hc 0.3.0", ] @@ -1689,25 +1734,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ "ppv-lite86", - "rand_core 0.6.0", + "rand_core 0.6.1", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.15", + "getrandom 0.1.16", ] [[package]] name = "rand_core" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8b34ba8cfb21243bd8df91854c830ff0d785fff2e82ebd4434c2644cb9ada18" +checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5" dependencies = [ - "getrandom 0.2.0", + "getrandom 0.2.1", ] [[package]] @@ -1725,7 +1785,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" dependencies = [ - "rand_core 0.6.0", + "rand_core 0.6.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", ] [[package]] @@ -1736,9 +1805,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "regex" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" dependencies = [ "aho-corasick", "memchr", @@ -1748,9 +1817,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" [[package]] name = "remove_dir_all" @@ -1768,7 +1837,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd281b1030aa675fb90aa994d07187645bb3c8fc756ca766e7c3070b439de9de" dependencies = [ "base64", - "bytes 1.0.0", + "bytes", "encoding_rs", "futures-core", "futures-util", @@ -1838,6 +1907,19 @@ dependencies = [ "libusb1-sys", ] +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +dependencies = [ + "gcc", + "libc", + "rand 0.3.23", + "rustc-serialize", + "time", +] + [[package]] name = "rustc-demangle" version = "0.1.18" @@ -1850,6 +1932,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + [[package]] name = "rustls" version = "0.19.0" @@ -1923,9 +2011,9 @@ dependencies = [ [[package]] name = "serde-aux" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a16764e861bd10990815d72767548131b2084079170bedec7cbf5a8ade2daeb" +checksum = "0162d500b846a7b331e583abaaa9c5c63c5777aa515dda3567c410ba243ce8be" dependencies = [ "serde", "serde_json", @@ -2063,9 +2151,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72" +checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" dependencies = [ "proc-macro2", "quote", @@ -2132,21 +2220,20 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447" dependencies = [ "lazy_static", ] [[package]] name = "time" -version = "0.1.44" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -2181,7 +2268,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d258221f566b6c803c7b4714abadc080172b272090cdc5e244a6d4dd13c3a6bd" dependencies = [ "autocfg", - "bytes 1.0.0", + "bytes", "libc", "memchr", "mio", @@ -2242,7 +2329,7 @@ dependencies = [ "futures-util", "log", "native-tls", - "pin-project 1.0.3", + "pin-project 1.0.4", "tokio", "tokio-native-tls", "tungstenite", @@ -2254,7 +2341,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36135b7e7da911f5f8b9331209f7fab4cc13498f3fff52f72a710c78187e3148" dependencies = [ - "bytes 1.0.0", + "bytes", "futures-core", "futures-sink", "log", @@ -2313,13 +2400,13 @@ checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" dependencies = [ "base64", "byteorder", - "bytes 1.0.0", + "bytes", "http", "httparse", "input_buffer", "log", "native-tls", - "rand 0.8.0", + "rand 0.8.1", "sha-1", "url", "utf-8", @@ -2397,6 +2484,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" dependencies = [ + "rand 0.7.3", "serde", ] @@ -2436,9 +2524,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" +version = "0.10.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9" [[package]] name = "wasm-bindgen" diff --git a/ethers-core/src/types/signature.rs b/ethers-core/src/types/signature.rs index 8d896f86..ef4bc80d 100644 --- a/ethers-core/src/types/signature.rs +++ b/ethers-core/src/types/signature.rs @@ -65,7 +65,7 @@ pub struct Signature { impl fmt::Display for Signature { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let sig = <[u8; 65]>::from(self); - write!(f, "{}", hex::encode(sig)) + write!(f, "{}", hex::encode(&sig[..])) } } diff --git a/ethers-signers/Cargo.toml b/ethers-signers/Cargo.toml index 27758667..9ee54b6a 100644 --- a/ethers-signers/Cargo.toml +++ b/ethers-signers/Cargo.toml @@ -19,6 +19,7 @@ thiserror = { version = "1.0.22", default-features = false } serde = { version = "1.0.118", default-features = false } coins-ledger = { version = "0.1.0", default-features = false, optional = true } +eth-keystore = { git = "https://github.com/roynalnaruto/eth-keystore-rs" } hex = { version = "0.4.2", default-features = false, features = ["std"] } async-trait = { version = "0.1.40", default-features = false } elliptic-curve = { version = "0.8.4", default-features = false } @@ -32,8 +33,9 @@ futures-executor = "0.3.8" ethers = { version = "0.1.3", path = "../ethers" } yubihsm = { version = "0.37.0", features = ["secp256k1", "usb", "mockhsm"] } +tempfile = "3.1.0" tokio = { version = "1.0", default-features = false, features = ["macros"] } -serde_json = { version = "1.0.55", default-features = false } +serde_json = { version = "1.0.55", default-features = false } [features] celo = ["ethers-core/celo"] diff --git a/ethers-signers/src/wallet/private_key.rs b/ethers-signers/src/wallet/private_key.rs index 71d2686a..ae890852 100644 --- a/ethers-signers/src/wallet/private_key.rs +++ b/ethers-signers/src/wallet/private_key.rs @@ -1,6 +1,7 @@ //! Specific helper functions for loading an offline K256 Private Key stored on disk use super::Wallet; +use eth_keystore::KeystoreError; use ethers_core::{ k256::{ ecdsa::SigningKey, elliptic_curve::error::Error as K256Error, EncodedPoint as K256PublicKey, @@ -9,7 +10,16 @@ use ethers_core::{ types::Address, utils::keccak256, }; -use std::str::FromStr; +use std::{path::Path, str::FromStr}; +use thiserror::Error; + +#[derive(Error, Debug)] +/// Error thrown by the Wallet module +pub enum WalletError { + /// Underlying eth keystore error + #[error(transparent)] + EthKeystoreError(#[from] KeystoreError), +} impl Clone for Wallet { fn clone(&self) -> Self { @@ -23,7 +33,43 @@ impl Clone for Wallet { } impl Wallet { - // TODO: Add support for mnemonic and encrypted JSON + // TODO: Add support for mnemonic + + /// Creates a new random encrypted JSON with the provided password and stores it in the + /// provided directory + pub fn new_keystore(dir: P, rng: &mut R, password: S) -> Result + where + P: AsRef, + R: Rng + CryptoRng, + S: AsRef<[u8]>, + { + let (secret, _) = eth_keystore::new(dir, rng, password)?; + let signer = SigningKey::from_bytes(secret.as_slice()) + .expect("private key should always be convertible to signing key"); + let address = key_to_address(&signer); + Ok(Self { + signer, + address, + chain_id: None, + }) + } + + /// Decrypts an encrypted JSON from the provided path to construct a Wallet instance + pub fn decrypt_keystore(keypath: P, password: S) -> Result + where + P: AsRef, + S: AsRef<[u8]>, + { + let secret = eth_keystore::decrypt_key(keypath, password)?; + let signer = SigningKey::from_bytes(secret.as_slice()) + .expect("private key should always be convertible to signing key"); + let address = key_to_address(&signer); + Ok(Self { + signer, + address, + chain_id: None, + }) + } /// Creates a new random keypair seeded with the provided RNG pub fn new(rng: &mut R) -> Self { @@ -96,6 +142,31 @@ impl FromStr for Wallet { mod tests { use super::*; use crate::Signer; + use std::fs; + use tempfile::tempdir; + + #[tokio::test] + async fn encrypted_json_keystore() { + // create and store a random encrypted JSON keystore in this directory + let dir = tempdir().unwrap(); + let mut rng = rand::thread_rng(); + let key = Wallet::::new_keystore(&dir, &mut rng, "randpsswd").unwrap(); + + // sign a message using the above key + let message = "Some data"; + let signature = key.sign_message(message).await.unwrap(); + + // read from the encrypted JSON keystore and decrypt it, while validating that the + // signatures produced by both the keys should match + let paths = fs::read_dir(dir).unwrap(); + for path in paths { + let path = path.unwrap().path(); + let key2 = Wallet::::decrypt_keystore(&path.clone(), "randpsswd").unwrap(); + let signature2 = key2.sign_message(message).await.unwrap(); + assert_eq!(signature, signature2); + assert!(std::fs::remove_file(&path).is_ok()); + } + } #[tokio::test] async fn signs_msg() {