Fixing secretstore TODOs - part 1 (#5386)

* ECDKG protocol prototype

* added test for enc/dec math

* get rid of decryption_session

* added licenses

* fix after merge

* get rid of unused serde dependency

* doc

* decryption session [without commutative enc]

* failed_dec_session

* fixed tests

* added commen

* added more decryption session tests

* helper to localize an issue

* more computations to localize error

* decryption_session::SessionParams

* added tests for EC math to localize problem

* secretstore network transport

* encryption_session_works_over_network

* network errors processing

* connecting to KeyServer

* licenses

* get rid of debug println-s

* fixed secretstore args

* encryption results are stored in KS database

* decryption protocol works over network

* enc/dec Session traits

* fixing warnings

* fix after merge

* on-chain ACL checker proto

* fixed compilation

* fixed compilation

* finally fixed <odd>-of-N-scheme

* temporary commented test

* 1-of-N works in math

* scheme 1-of-N works

* updated AclStorage with real contract ABI

* remove unnecessary unsafety

* fixed grumbles

* wakeup on access denied

* encrypt secretstore messages

* 'shadow' decryption

* fix grumbles

* lost files

* secretstore cli-options

* decryption seccion when ACL check failed on master

* disallow regenerating key for existing document

* removed obsolete TODO

* fix after merge

* switched to tokio_io

* fix after merge

* fix after merge

* fix after merge

* fix after merge

* fix after merge

* fixed test

* fix after merge
This commit is contained in:
Svyatoslav Nikolsky 2017-04-08 12:26:16 +03:00 committed by Gav Wood
parent d0e057cabd
commit 93a6047912
33 changed files with 1095 additions and 668 deletions

168
Cargo.lock generated
View File

@ -30,7 +30,7 @@ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-dapps 1.7.0", "parity-dapps 1.7.0",
@ -350,7 +350,7 @@ name = "env_logger"
version = "0.4.2" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -382,7 +382,7 @@ dependencies = [
name = "ethash" name = "ethash"
version = "1.7.0" version = "1.7.0"
dependencies = [ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"sha3 0.1.0", "sha3 0.1.0",
@ -420,7 +420,7 @@ dependencies = [
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"native-contracts 0.1.0", "native-contracts 0.1.0",
"num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
@ -465,7 +465,7 @@ name = "ethcore-io"
version = "1.7.0" version = "1.7.0"
dependencies = [ dependencies = [
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.1 (git+https://github.com/paritytech/mio)", "mio 0.6.1 (git+https://github.com/paritytech/mio)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -499,7 +499,7 @@ dependencies = [
"ethcore-ipc 1.7.0", "ethcore-ipc 1.7.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.7.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.7.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -511,7 +511,7 @@ version = "1.7.0"
dependencies = [ dependencies = [
"ethcore-ipc 1.7.0", "ethcore-ipc 1.7.0",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
] ]
@ -524,7 +524,7 @@ dependencies = [
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.7.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.7.0",
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -542,7 +542,7 @@ dependencies = [
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0", "rlp 0.1.0",
"smallvec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -559,7 +559,7 @@ dependencies = [
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -579,7 +579,7 @@ dependencies = [
"ethkey 0.2.0", "ethkey 0.2.0",
"igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.1 (git+https://github.com/paritytech/mio)", "mio 0.6.1 (git+https://github.com/paritytech/mio)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"path 0.1.0", "path 0.1.0",
@ -617,7 +617,7 @@ dependencies = [
"jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0", "parity-reactor 0.1.0",
"parity-updater 1.7.0", "parity-updater 1.7.0",
@ -649,14 +649,15 @@ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"native-contracts 0.1.0", "native-contracts 0.1.0",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -674,7 +675,7 @@ dependencies = [
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-ui 1.7.0", "parity-ui 1.7.0",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
@ -698,9 +699,9 @@ dependencies = [
"jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-tcp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-tcp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -719,7 +720,7 @@ dependencies = [
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
@ -786,7 +787,7 @@ dependencies = [
"ethkey 0.2.0", "ethkey 0.2.0",
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wordlist 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wordlist 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
@ -817,7 +818,7 @@ dependencies = [
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0", "rlp 0.1.0",
@ -857,7 +858,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -922,7 +923,7 @@ dependencies = [
"ethkey 0.2.0", "ethkey 0.2.0",
"hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)", "hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)",
"libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)", "libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -964,7 +965,7 @@ dependencies = [
"cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rotor 0.6.3 (git+https://github.com/paritytech/rotor)", "rotor 0.6.3 (git+https://github.com/paritytech/rotor)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@ -982,7 +983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1079,7 +1080,7 @@ version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3"
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1093,7 +1094,7 @@ dependencies = [
"hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1105,7 +1106,7 @@ source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c0
dependencies = [ dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-tokio-ipc 0.1.0 (git+https://github.com/nikvolf/parity-tokio-ipc)", "parity-tokio-ipc 0.1.0 (git+https://github.com/nikvolf/parity-tokio-ipc)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1127,7 +1128,7 @@ source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c0
dependencies = [ dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)", "tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)",
"tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)", "tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)",
@ -1140,7 +1141,7 @@ version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3"
dependencies = [ dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1150,8 +1151,8 @@ version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3"
dependencies = [ dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1162,7 +1163,7 @@ source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c0
dependencies = [ dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1233,7 +1234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "log" name = "log"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -1262,7 +1263,7 @@ name = "mime"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1293,9 +1294,9 @@ dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1303,16 +1304,16 @@ dependencies = [
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.6.2" version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1324,8 +1325,8 @@ source = "git+https://github.com/alexcrichton/mio-named-pipes#903dc2f7eac6700c62
dependencies = [ dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1336,7 +1337,7 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1345,7 +1346,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1356,7 +1357,7 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1439,7 +1440,7 @@ dependencies = [
[[package]] [[package]]
name = "net2" name = "net2"
version = "0.2.23" version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1620,7 +1621,7 @@ dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1660,7 +1661,7 @@ dependencies = [
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"fetch 0.1.0", "fetch 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0", "parity-reactor 0.1.0",
@ -1689,7 +1690,7 @@ dependencies = [
"ethcore-io 1.7.0", "ethcore-io 1.7.0",
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0", "rlp 0.1.0",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1701,7 +1702,7 @@ name = "parity-reactor"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1713,7 +1714,7 @@ dependencies = [
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1728,11 +1729,11 @@ version = "0.1.0"
source = "git+https://github.com/nikvolf/parity-tokio-ipc#3d4234de6bdc78688ef803935111003080fd5375" source = "git+https://github.com/nikvolf/parity-tokio-ipc#3d4234de6bdc78688ef803935111003080fd5375"
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)", "mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-line 0.1.0 (git+https://github.com/tokio-rs/tokio-line)", "tokio-line 0.1.0 (git+https://github.com/tokio-rs/tokio-line)",
"tokio-named-pipes 0.1.0 (git+https://github.com/alexcrichton/tokio-named-pipes)", "tokio-named-pipes 0.1.0 (git+https://github.com/alexcrichton/tokio-named-pipes)",
"tokio-uds 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1773,7 +1774,7 @@ dependencies = [
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"ethsync 1.7.0", "ethsync 1.7.0",
"ipc-common-types 1.7.0", "ipc-common-types 1.7.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.7.0", "parity-hash-fetch 1.7.0",
"parity-reactor 0.1.0", "parity-reactor 0.1.0",
"path 0.1.0", "path 0.1.0",
@ -1992,7 +1993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper-native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2043,7 +2044,7 @@ name = "rotor"
version = "0.6.3" version = "0.6.3"
source = "git+https://github.com/paritytech/rotor#2a3764a830174aa94405593be550e8fc7ecea25a" source = "git+https://github.com/paritytech/rotor#2a3764a830174aa94405593be550e8fc7ecea25a"
dependencies = [ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.1 (git+https://github.com/paritytech/mio)", "mio 0.6.1 (git+https://github.com/paritytech/mio)",
"quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2309,7 +2310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "stats" name = "stats"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2361,7 +2362,7 @@ version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2442,14 +2443,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "tokio-core" name = "tokio-core"
version = "0.1.4" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2459,7 +2463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2468,7 +2472,7 @@ version = "0.1.0"
source = "git+https://github.com/tokio-rs/tokio-line#482614ae0c82daf584727ae65a80d854fe861f81" source = "git+https://github.com/tokio-rs/tokio-line#482614ae0c82daf584727ae65a80d854fe861f81"
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2480,10 +2484,10 @@ source = "git+https://github.com/tomusdrw/tokio-minihttp#8acbafae3e77e7f7eb516b4
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)", "tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2495,7 +2499,7 @@ source = "git+https://github.com/alexcrichton/tokio-named-pipes#3a22f8fc9a441b54
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)", "mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2504,13 +2508,13 @@ version = "0.1.0"
source = "git+https://github.com/tomusdrw/tokio-proto#f6ee08cb594fa2fc1b4178eaaca0855d66e68fd3" source = "git+https://github.com/tomusdrw/tokio-proto#f6ee08cb594fa2fc1b4178eaaca0855d66e68fd3"
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2520,13 +2524,13 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2544,10 +2548,10 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2695,7 +2699,7 @@ source = "git+https://github.com/paritytech/ws-rs.git?branch=parity-1.7#30415c17
dependencies = [ dependencies = [
"bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.1 (git+https://github.com/paritytech/mio)", "mio 0.6.1 (git+https://github.com/paritytech/mio)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2827,7 +2831,7 @@ dependencies = [
"checksum libusb-sys 0.2.3 (git+https://github.com/paritytech/libusb-sys)" = "<none>" "checksum libusb-sys 0.2.3 (git+https://github.com/paritytech/libusb-sys)" = "<none>"
"checksum linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bda158e0dabeb97ee8a401f4d17e479d6b891a14de0bba79d5cc2d4d325b5e48" "checksum linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bda158e0dabeb97ee8a401f4d17e479d6b891a14de0bba79d5cc2d4d325b5e48"
"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" "checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
"checksum lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656fa4dfcb02bcf1063c592ba3ff6a5303ee1f2afe98c8a889e8b1a77c6dfdb7" "checksum lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656fa4dfcb02bcf1063c592ba3ff6a5303ee1f2afe98c8a889e8b1a77c6dfdb7"
"checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e" "checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
@ -2835,7 +2839,7 @@ dependencies = [
"checksum mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e50bf542f81754ef69e5cea856946a3819f7c09ea97b4903c8bc8a89f74e7b6" "checksum mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e50bf542f81754ef69e5cea856946a3819f7c09ea97b4903c8bc8a89f74e7b6"
"checksum miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d1f4d337a01c32e1f2122510fed46393d53ca35a7f429cb0450abaedfa3ed54" "checksum miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d1f4d337a01c32e1f2122510fed46393d53ca35a7f429cb0450abaedfa3ed54"
"checksum mio 0.6.1 (git+https://github.com/paritytech/mio)" = "<none>" "checksum mio 0.6.1 (git+https://github.com/paritytech/mio)" = "<none>"
"checksum mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5b493dc9fd96bd2077f2117f178172b0765db4dfda3ea4d8000401e6d65d3e80" "checksum mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f27d38f824a0d267d55b29b171e9e99269a53812e385fa75c1fe700ae254a6a4"
"checksum mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)" = "<none>" "checksum mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)" = "<none>"
"checksum mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78437f00d9615c366932cbfe79790b5c2945706ba67cf78378ffacc0069ed9de" "checksum mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78437f00d9615c366932cbfe79790b5c2945706ba67cf78378ffacc0069ed9de"
"checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1"
@ -2846,7 +2850,7 @@ dependencies = [
"checksum nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "<none>" "checksum nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "<none>"
"checksum nanomsg-sys 0.5.0 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "<none>" "checksum nanomsg-sys 0.5.0 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "<none>"
"checksum native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4e52995154bb6f0b41e4379a279482c9387c1632e3798ba4e511ef8c54ee09" "checksum native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4e52995154bb6f0b41e4379a279482c9387c1632e3798ba4e511ef8c54ee09"
"checksum net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a816012ca11cb47009693c1e0c6130e26d39e4d97ee2a13c50e868ec83e3204" "checksum net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "18b9642ad6222faf5ce46f6966f59b71b9775ad5758c9e09fcf0a6c8061972b4"
"checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b" "checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b"
"checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" "checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2"
"checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e" "checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e"
@ -2944,7 +2948,7 @@ dependencies = [
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
"checksum tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aef43048292ca0bae4ab32180e85f6202cf2816c2a210c396a84b99dab9270" "checksum tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aef43048292ca0bae4ab32180e85f6202cf2816c2a210c396a84b99dab9270"
"checksum tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3d1be481b55126f02ef88ff86748086473cb537a949fc4a8f4be403a530ae54b" "checksum tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "99e958104a67877907c1454386d5482fe8e965a55d60be834a15a44328e7dc76"
"checksum tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a278fde45f1be68e44995227d426aaa4841e0980bb0a21b981092f28c3c8473" "checksum tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a278fde45f1be68e44995227d426aaa4841e0980bb0a21b981092f28c3c8473"
"checksum tokio-line 0.1.0 (git+https://github.com/tokio-rs/tokio-line)" = "<none>" "checksum tokio-line 0.1.0 (git+https://github.com/tokio-rs/tokio-line)" = "<none>"
"checksum tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)" = "<none>" "checksum tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)" = "<none>"

View File

@ -214,10 +214,10 @@ mod derivation {
use rcrypto::sha2::Sha512; use rcrypto::sha2::Sha512;
use bigint::hash::{H512, H256}; use bigint::hash::{H512, H256};
use bigint::prelude::{U256, U512, Uint}; use bigint::prelude::{U256, U512, Uint};
use secp256k1;
use secp256k1::key::{SecretKey, PublicKey}; use secp256k1::key::{SecretKey, PublicKey};
use SECP256K1; use SECP256K1;
use keccak; use keccak;
use math::curve_order;
use super::{Label, Derivation}; use super::{Label, Derivation};
#[derive(Debug)] #[derive(Debug)]
@ -233,7 +233,7 @@ mod derivation {
// For hardened derivation, pass u32 index at least 2^31 or custom Derivation::Hard(T) enum // For hardened derivation, pass u32 index at least 2^31 or custom Derivation::Hard(T) enum
// //
// Can panic if passed `private_key` is not a valid secp256k1 private key // Can panic if passed `private_key` is not a valid secp256k1 private key
// (outside of (0..curve_n()]) field // (outside of (0..curve_order()]) field
pub fn private<T>(private_key: H256, chain_code: H256, index: Derivation<T>) -> (H256, H256) where T: Label { pub fn private<T>(private_key: H256, chain_code: H256, index: Derivation<T>) -> (H256, H256) where T: Label {
match index { match index {
Derivation::Soft(index) => private_soft(private_key, chain_code, index), Derivation::Soft(index) => private_soft(private_key, chain_code, index),
@ -260,7 +260,7 @@ mod derivation {
} }
// Can panic if passed `private_key` is not a valid secp256k1 private key // Can panic if passed `private_key` is not a valid secp256k1 private key
// (outside of (0..curve_n()]) field // (outside of (0..curve_order()]) field
fn private_soft<T>(private_key: H256, chain_code: H256, index: T) -> (H256, H256) where T: Label { fn private_soft<T>(private_key: H256, chain_code: H256, index: T) -> (H256, H256) where T: Label {
let mut data = vec![0u8; 33 + T::len()]; let mut data = vec![0u8; 33 + T::len()];
@ -295,7 +295,7 @@ mod derivation {
fn private_add(k1: U256, k2: U256) -> U256 { fn private_add(k1: U256, k2: U256) -> U256 {
let sum = U512::from(k1) + U512::from(k2); let sum = U512::from(k1) + U512::from(k2);
modulo(sum, curve_n()) modulo(sum, curve_order())
} }
// todo: surely can be optimized // todo: surely can be optimized
@ -305,12 +305,6 @@ mod derivation {
md.into() md.into()
} }
// returns n (for mod(n)) for the secp256k1 elliptic curve
// todo: maybe lazy static
fn curve_n() -> U256 {
H256::from_slice(&secp256k1::constants::CURVE_ORDER).into()
}
pub fn public<T>(public_key: H512, chain_code: H256, derivation: Derivation<T>) -> Result<(H512, H256), Error> where T: Label { pub fn public<T>(public_key: H512, chain_code: H256, derivation: Derivation<T>) -> Result<(H512, H256), Error> where T: Label {
let index = match derivation { let index = match derivation {
Derivation::Soft(index) => index, Derivation::Soft(index) => index,
@ -339,7 +333,7 @@ mod derivation {
let new_chain_code = H256::from(&i_512[32..64]); let new_chain_code = H256::from(&i_512[32..64]);
// Generated private key can (extremely rarely) be out of secp256k1 key field // Generated private key can (extremely rarely) be out of secp256k1 key field
if curve_n() <= new_private.clone().into() { return Err(Error::MissingIndex); } if curve_order() <= new_private.clone().into() { return Err(Error::MissingIndex); }
let new_private_sec = SecretKey::from_slice(&SECP256K1, &*new_private) let new_private_sec = SecretKey::from_slice(&SECP256K1, &*new_private)
.expect("Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed"); .expect("Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed");
let mut new_public = PublicKey::from_secret_key(&SECP256K1, &new_private_sec) let mut new_public = PublicKey::from_secret_key(&SECP256K1, &new_private_sec)

View File

@ -27,7 +27,7 @@ pub fn public_to_address(public: &Public) -> Address {
result result
} }
#[derive(Clone)] #[derive(Debug, Clone, PartialEq)]
/// secp256k1 key pair /// secp256k1 key pair
pub struct KeyPair { pub struct KeyPair {
secret: Secret, secret: Secret,

View File

@ -16,7 +16,9 @@
use super::{SECP256K1, Public, Secret, Error}; use super::{SECP256K1, Public, Secret, Error};
use secp256k1::key; use secp256k1::key;
use secp256k1::constants::{GENERATOR_X, GENERATOR_Y}; use secp256k1::constants::{GENERATOR_X, GENERATOR_Y, CURVE_ORDER};
use bigint::prelude::U256;
use bigint::hash::H256;
/// Inplace multiply public key by secret key (EC point * scalar) /// Inplace multiply public key by secret key (EC point * scalar)
pub fn public_mul_secret(public: &mut Public, secret: &Secret) -> Result<(), Error> { pub fn public_mul_secret(public: &mut Public, secret: &Secret) -> Result<(), Error> {
@ -47,6 +49,14 @@ pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> {
Ok(()) Ok(())
} }
/// Replace public key with its negation (EC point = - EC point)
pub fn public_negate(public: &mut Public) -> Result<(), Error> {
let mut key_public = to_secp256k1_public(public)?;
key_public.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
set_public(public, &key_public);
Ok(())
}
/// Return base point of secp256k1 /// Return base point of secp256k1
pub fn generation_point() -> Public { pub fn generation_point() -> Public {
let mut public_sec_raw = [0u8; 65]; let mut public_sec_raw = [0u8; 65];
@ -61,6 +71,11 @@ pub fn generation_point() -> Public {
public public
} }
/// Return secp256k1 elliptic curve order
pub fn curve_order() -> U256 {
H256::from_slice(&CURVE_ORDER).into()
}
fn to_secp256k1_public(public: &Public) -> Result<key::PublicKey, Error> { fn to_secp256k1_public(public: &Public) -> Result<key::PublicKey, Error> {
let public_data = { let public_data = {
let mut temp = [4u8; 65]; let mut temp = [4u8; 65];

View File

@ -67,6 +67,15 @@ impl Secret {
Ok(()) Ok(())
} }
/// Inplace decrease secret key (scalar - 1)
pub fn dec(&mut self) -> Result<(), Error> {
let mut key_secret = self.to_secp256k1_secret()?;
key_secret.add_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
*self = key_secret.into();
Ok(())
}
/// Inplace multiply one secret key to another (scalar * scalar) /// Inplace multiply one secret key to another (scalar * scalar)
pub fn mul(&mut self, other: &Secret) -> Result<(), Error> { pub fn mul(&mut self, other: &Secret) -> Result<(), Error> {
let mut key_secret = self.to_secp256k1_secret()?; let mut key_secret = self.to_secp256k1_secret()?;

View File

@ -69,8 +69,11 @@ pass = "test_pass"
[secretstore] [secretstore]
disable = false disable = false
port = 8082 nodes = []
http_interface = "local"
http_port = 8082
interface = "local" interface = "local"
port = 8083
path = "$HOME/.parity/secretstore" path = "$HOME/.parity/secretstore"
[ipfs] [ipfs]

View File

@ -38,7 +38,8 @@ user = "username"
pass = "password" pass = "password"
[secretstore] [secretstore]
port = 8082 http_port = 8082
port = 8083
[ipfs] [ipfs]
enable = false enable = false

View File

@ -187,10 +187,18 @@ usage! {
// Secret Store // Secret Store
flag_no_secretstore: bool = false, flag_no_secretstore: bool = false,
or |c: &Config| otry!(c.secretstore).disable.clone(), or |c: &Config| otry!(c.secretstore).disable.clone(),
flag_secretstore_port: u16 = 8082u16, flag_secretstore_secret: Option<String> = None,
or |c: &Config| otry!(c.secretstore).port.clone(), or |c: &Config| otry!(c.secretstore).self_secret.clone().map(Some),
flag_secretstore_nodes: String = "",
or |c: &Config| otry!(c.secretstore).nodes.as_ref().map(|vec| vec.join(",")),
flag_secretstore_interface: String = "local", flag_secretstore_interface: String = "local",
or |c: &Config| otry!(c.secretstore).interface.clone(), or |c: &Config| otry!(c.secretstore).interface.clone(),
flag_secretstore_port: u16 = 8083u16,
or |c: &Config| otry!(c.secretstore).port.clone(),
flag_secretstore_http_interface: String = "local",
or |c: &Config| otry!(c.secretstore).http_interface.clone(),
flag_secretstore_http_port: u16 = 8082u16,
or |c: &Config| otry!(c.secretstore).http_port.clone(),
flag_secretstore_path: String = "$BASE/secretstore", flag_secretstore_path: String = "$BASE/secretstore",
or |c: &Config| otry!(c.secretstore).path.clone(), or |c: &Config| otry!(c.secretstore).path.clone(),
@ -454,8 +462,12 @@ struct Dapps {
#[derive(Default, Debug, PartialEq, RustcDecodable)] #[derive(Default, Debug, PartialEq, RustcDecodable)]
struct SecretStore { struct SecretStore {
disable: Option<bool>, disable: Option<bool>,
port: Option<u16>, self_secret: Option<String>,
nodes: Option<Vec<String>>,
interface: Option<String>, interface: Option<String>,
port: Option<u16>,
http_interface: Option<String>,
http_port: Option<u16>,
path: Option<String>, path: Option<String>,
} }
@ -697,8 +709,12 @@ mod tests {
flag_no_dapps: false, flag_no_dapps: false,
flag_no_secretstore: false, flag_no_secretstore: false,
flag_secretstore_port: 8082u16, flag_secretstore_secret: None,
flag_secretstore_nodes: "".into(),
flag_secretstore_interface: "local".into(), flag_secretstore_interface: "local".into(),
flag_secretstore_port: 8083u16,
flag_secretstore_http_interface: "local".into(),
flag_secretstore_http_port: 8082u16,
flag_secretstore_path: "$HOME/.parity/secretstore".into(), flag_secretstore_path: "$HOME/.parity/secretstore".into(),
// IPFS // IPFS
@ -909,8 +925,12 @@ mod tests {
}), }),
secretstore: Some(SecretStore { secretstore: Some(SecretStore {
disable: None, disable: None,
port: Some(8082), self_secret: None,
nodes: None,
interface: None, interface: None,
port: Some(8083),
http_interface: None,
http_port: Some(8082),
path: None, path: None,
}), }),
ipfs: Some(Ipfs { ipfs: Some(Ipfs {

View File

@ -182,16 +182,25 @@ API and Console Options:
vectors. Special options: "all", "none" vectors. Special options: "all", "none"
(default: {flag_ipfs_api_hosts}). (default: {flag_ipfs_api_hosts}).
Secret Store Options: Secret Store Options:
--no-secretstore Disable Secret Store functionality. (default: {flag_no_secretstore}) --no-secretstore Disable Secret Store functionality. (default: {flag_no_secretstore})
--secretstore-port PORT Specify the port portion for Secret Store Key Server --secretstore-secret SECRET Hex-encoded secret key of this node.
(default: {flag_secretstore_port}). (required, default: {flag_secretstore_secret:?}).
--secretstore-interface IP Specify the hostname portion for Secret Store Key Server, IP --secretstore-nodes NODES Comma-separated list of other secret store cluster nodes in form
should be an interface's IP address, or local NODE_PUBLIC_KEY_IN_HEX@NODE_IP_ADDR:NODE_PORT.
(required, default: {flag_secretstore_nodes}).
--secretstore-interface IP Specify the hostname portion for listening to Secret Store Key Server
internal requests, IP should be an interface's IP address, or local
(default: {flag_secretstore_interface}). (default: {flag_secretstore_interface}).
--secretstore-port PORT Specify the port portion for listening to Secret Store Key Server
internal requests (default: {flag_secretstore_port}).
--secretstore-http-interface IP Specify the hostname portion for listening to Secret Store Key Server
HTTP requests, IP should be an interface's IP address, or local
(default: {flag_secretstore_http_interface}).
--secretstore-http-port PORT Specify the port portion for listening to Secret Store Key Server
HTTP requests (default: {flag_secretstore_http_port}).
--secretstore-path PATH Specify directory where Secret Store should save its data. --secretstore-path PATH Specify directory where Secret Store should save its data.
(default: {flag_secretstore_path}) (default: {flag_secretstore_path}).
Sealing/Mining Options: Sealing/Mining Options:
--author ADDRESS Specify the block author (aka "coinbase") address --author ADDRESS Specify the block author (aka "coinbase") address

View File

@ -18,13 +18,14 @@ use std::time::Duration;
use std::io::{Read, Write, stderr}; use std::io::{Read, Write, stderr};
use std::net::SocketAddr; use std::net::SocketAddr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::collections::BTreeMap;
use std::cmp::max; use std::cmp::max;
use cli::{Args, ArgsError}; use cli::{Args, ArgsError};
use util::{Hashable, H256, U256, Uint, Bytes, version_data, Address}; use util::{Hashable, H256, U256, Uint, Bytes, version_data, Address};
use util::journaldb::Algorithm; use util::journaldb::Algorithm;
use util::Colour; use util::Colour;
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP}; use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
use ethcore::ethstore::ethkey::Secret; use ethcore::ethstore::ethkey::{Secret, Public};
use ethcore::client::{VMType}; use ethcore::client::{VMType};
use ethcore::miner::{MinerOptions, Banning, StratumOptions}; use ethcore::miner::{MinerOptions, Banning, StratumOptions};
use ethcore::verification::queue::VerifierSettings; use ethcore::verification::queue::VerifierSettings;
@ -136,7 +137,7 @@ impl Configuration {
let mut dapps_conf = self.dapps_config(); let mut dapps_conf = self.dapps_config();
let ipfs_conf = self.ipfs_config(); let ipfs_conf = self.ipfs_config();
let signer_conf = self.signer_config(); let signer_conf = self.signer_config();
let secretstore_conf = self.secretstore_config(); let secretstore_conf = self.secretstore_config()?;
let format = self.format()?; let format = self.format()?;
if self.args.flag_jsonrpc_threads.is_some() && dapps_conf.enabled { if self.args.flag_jsonrpc_threads.is_some() && dapps_conf.enabled {
@ -571,13 +572,17 @@ impl Configuration {
} }
} }
fn secretstore_config(&self) -> SecretStoreConfiguration { fn secretstore_config(&self) -> Result<SecretStoreConfiguration, String> {
SecretStoreConfiguration { Ok(SecretStoreConfiguration {
enabled: self.secretstore_enabled(), enabled: self.secretstore_enabled(),
self_secret: self.secretstore_self_secret()?,
nodes: self.secretstore_nodes()?,
interface: self.secretstore_interface(), interface: self.secretstore_interface(),
port: self.args.flag_secretstore_port, port: self.args.flag_secretstore_port,
http_interface: self.secretstore_http_interface(),
http_port: self.args.flag_secretstore_http_port,
data_path: self.directories().secretstore, data_path: self.directories().secretstore,
} })
} }
fn ipfs_config(&self) -> IpfsConfiguration { fn ipfs_config(&self) -> IpfsConfiguration {
@ -913,10 +918,43 @@ impl Configuration {
} }
fn secretstore_interface(&self) -> String { fn secretstore_interface(&self) -> String {
match self.args.flag_secretstore_interface.as_str() { Self::interface(&self.args.flag_secretstore_interface)
"local" => "127.0.0.1", }
x => x,
}.into() fn secretstore_http_interface(&self) -> String {
Self::interface(&self.args.flag_secretstore_http_interface)
}
fn secretstore_self_secret(&self) -> Result<Option<Secret>, String> {
match self.args.flag_secretstore_secret {
Some(ref s) => Ok(Some(s.parse()
.map_err(|e| format!("Invalid secret store secret: {}. Error: {:?}", s, e))?)),
None => Ok(None),
}
}
fn secretstore_nodes(&self) -> Result<BTreeMap<Public, (String, u16)>, String> {
let mut nodes = BTreeMap::new();
for node in self.args.flag_secretstore_nodes.split(',').filter(|n| n != &"") {
let public_and_addr: Vec<_> = node.split('@').collect();
if public_and_addr.len() != 2 {
return Err(format!("Invalid secret store node: {}", node));
}
let ip_and_port: Vec<_> = public_and_addr[1].split(':').collect();
if ip_and_port.len() != 2 {
return Err(format!("Invalid secret store node: {}", node));
}
let public = public_and_addr[0].parse()
.map_err(|e| format!("Invalid public key in secret store node: {}. Error: {:?}", public_and_addr[0], e))?;
let port = ip_and_port[1].parse()
.map_err(|e| format!("Invalid port in secret store node: {}. Error: {:?}", ip_and_port[1], e))?;
nodes.insert(public, (ip_and_port[0].into(), port));
}
Ok(nodes)
} }
fn stratum_interface(&self) -> String { fn stratum_interface(&self) -> String {

View File

@ -651,7 +651,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
let secretstore_deps = secretstore::Dependencies { let secretstore_deps = secretstore::Dependencies {
client: client.clone(), client: client.clone(),
}; };
let secretstore_key_server = secretstore::start(cmd.secretstore_conf.clone(), secretstore_deps); let secretstore_key_server = secretstore::start(cmd.secretstore_conf.clone(), secretstore_deps)?;
// the ipfs server // the ipfs server
let ipfs_server = ipfs::start_server(cmd.ipfs_conf.clone(), client.clone())?; let ipfs_server = ipfs::start_server(cmd.ipfs_conf.clone(), client.clone())?;

View File

@ -14,9 +14,11 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use dir::default_data_path; use dir::default_data_path;
use ethcore::client::Client; use ethcore::client::Client;
use ethkey::{Secret, Public};
use helpers::replace_home; use helpers::replace_home;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -24,10 +26,18 @@ use helpers::replace_home;
pub struct Configuration { pub struct Configuration {
/// Is secret store functionality enabled? /// Is secret store functionality enabled?
pub enabled: bool, pub enabled: bool,
/// This node secret.
pub self_secret: Option<Secret>,
/// Other nodes IDs + addresses.
pub nodes: BTreeMap<Public, (String, u16)>,
/// Interface to listen to /// Interface to listen to
pub interface: String, pub interface: String,
/// Port to listen to /// Port to listen to
pub port: u16, pub port: u16,
/// Interface to listen to
pub http_interface: String,
/// Port to listen to
pub http_port: u16,
/// Data directory path for secret store /// Data directory path for secret store
pub data_path: String, pub data_path: String,
} }
@ -55,8 +65,8 @@ mod server {
#[cfg(feature="secretstore")] #[cfg(feature="secretstore")]
mod server { mod server {
use ethkey;
use ethcore_secretstore; use ethcore_secretstore;
use ethkey::KeyPair;
use super::{Configuration, Dependencies}; use super::{Configuration, Dependencies};
/// Key server /// Key server
@ -67,37 +77,35 @@ mod server {
impl KeyServer { impl KeyServer {
/// Create new key server /// Create new key server
pub fn new(conf: Configuration, deps: Dependencies) -> Result<Self, String> { pub fn new(conf: Configuration, deps: Dependencies) -> Result<Self, String> {
let key_pairs = vec![ let self_secret = conf.self_secret.ok_or("self secret is required when using secretstore")?;
ethkey::KeyPair::from_secret("6c26a76e9b31048d170873a791401c7e799a11f0cefc0171cc31a49800967509".parse().unwrap()).unwrap(), let mut conf = ethcore_secretstore::ServiceConfiguration {
ethkey::KeyPair::from_secret("7e94018b3731afdb3b4e6f4c3e179475640166da12e1d1b0c7d80729b1a5b452".parse().unwrap()).unwrap(), listener_address: ethcore_secretstore::NodeAddress {
ethkey::KeyPair::from_secret("5ab6ed2a52c33142380032c39a03a86b12eacb3fa4b53bc16d84f51318156f8c".parse().unwrap()).unwrap(), address: conf.http_interface.clone(),
]; port: conf.http_port,
let conf = ethcore_secretstore::ServiceConfiguration { },
data_path: conf.data_path.clone(),
cluster_config: ethcore_secretstore::ClusterConfiguration {
threads: 4,
self_private: (**self_secret).into(),
listener_address: ethcore_secretstore::NodeAddress { listener_address: ethcore_secretstore::NodeAddress {
address: conf.interface.clone(), address: conf.interface.clone(),
port: conf.port, port: conf.port,
}, },
data_path: conf.data_path.clone(), nodes: conf.nodes.into_iter().map(|(p, (ip, port))| (p, ethcore_secretstore::NodeAddress {
// TODO: this is test configuration. how it will be configured in production? address: ip,
cluster_config: ethcore_secretstore::ClusterConfiguration { port: port,
threads: 4,
self_private: (***key_pairs[(conf.port - 8082) as usize].secret()).into(),
listener_address: ethcore_secretstore::NodeAddress {
address: conf.interface.clone(),
port: conf.port + 10,
},
nodes: key_pairs.iter().enumerate().map(|(i, kp)| (kp.public().clone(),
ethcore_secretstore::NodeAddress {
address: conf.interface.clone(),
port: 8082 + 10 + (i as u16),
})).collect(), })).collect(),
allow_connecting_to_higher_nodes: true, allow_connecting_to_higher_nodes: true,
encryption_config: ethcore_secretstore::EncryptionConfiguration { encryption_config: ethcore_secretstore::EncryptionConfiguration {
key_check_timeout_ms: 1000, key_check_timeout_ms: 1000,
}, },
} },
}; };
let self_key_pair = KeyPair::from_secret(self_secret.clone())
.map_err(|e| format!("valid secret is required when using secretstore. Error: {}", e))?;
conf.cluster_config.nodes.insert(self_key_pair.public().clone(), conf.cluster_config.listener_address.clone());
let key_server = ethcore_secretstore::start(deps.client, conf) let key_server = ethcore_secretstore::start(deps.client, conf)
.map_err(Into::<String>::into)?; .map_err(Into::<String>::into)?;
@ -115,8 +123,12 @@ impl Default for Configuration {
let data_dir = default_data_path(); let data_dir = default_data_path();
Configuration { Configuration {
enabled: true, enabled: true,
self_secret: None,
nodes: BTreeMap::new(),
interface: "127.0.0.1".to_owned(), interface: "127.0.0.1".to_owned(),
port: 8082, port: 8083,
http_interface: "127.0.0.1".to_owned(),
http_port: 8082,
data_path: replace_home(&data_dir, "$BASE/secretstore"), data_path: replace_home(&data_dir, "$BASE/secretstore"),
} }
} }

View File

@ -20,7 +20,8 @@ serde_derive = "0.9"
futures = "0.1" futures = "0.1"
futures-cpupool = "0.1" futures-cpupool = "0.1"
rustc-serialize = "0.3" rustc-serialize = "0.3"
tokio-core = "0.1" tokio-core = "0.1.6"
tokio-io = "0.1.0"
tokio-service = "0.1" tokio-service = "0.1"
tokio-proto = "0.1" tokio-proto = "0.1"
url = "1.0" url = "1.0"

View File

@ -21,11 +21,13 @@ use hyper::method::Method as HttpMethod;
use hyper::status::StatusCode as HttpStatusCode; use hyper::status::StatusCode as HttpStatusCode;
use hyper::server::{Server as HttpServer, Request as HttpRequest, Response as HttpResponse, Handler as HttpHandler, use hyper::server::{Server as HttpServer, Request as HttpRequest, Response as HttpResponse, Handler as HttpHandler,
Listening as HttpListening}; Listening as HttpListening};
use serde_json;
use url::percent_encoding::percent_decode; use url::percent_encoding::percent_decode;
use util::ToPretty; use util::ToPretty;
use traits::KeyServer; use traits::KeyServer;
use types::all::{Error, ServiceConfiguration, RequestSignature, DocumentAddress, DocumentEncryptedKey}; use serialization::SerializableDocumentEncryptedKeyShadow;
use types::all::{Error, ServiceConfiguration, RequestSignature, DocumentAddress, DocumentEncryptedKey, DocumentEncryptedKeyShadow};
/// Key server http-requests listener /// Key server http-requests listener
pub struct KeyServerHttpListener<T: KeyServer + 'static> { pub struct KeyServerHttpListener<T: KeyServer + 'static> {
@ -42,6 +44,8 @@ enum Request {
GenerateDocumentKey(DocumentAddress, RequestSignature, usize), GenerateDocumentKey(DocumentAddress, RequestSignature, usize),
/// Request encryption key of given document for given requestor. /// Request encryption key of given document for given requestor.
GetDocumentKey(DocumentAddress, RequestSignature), GetDocumentKey(DocumentAddress, RequestSignature),
/// Request shadow of encryption key of given document for given requestor.
GetDocumentKeyShadow(DocumentAddress, RequestSignature),
} }
/// Cloneable http handler /// Cloneable http handler
@ -83,6 +87,10 @@ impl<T> KeyServer for KeyServerHttpListener<T> where T: KeyServer + 'static {
fn document_key(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKey, Error> { fn document_key(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKey, Error> {
self.handler.key_server.document_key(signature, document) self.handler.key_server.document_key(signature, document)
} }
fn document_key_shadow(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKeyShadow, Error> {
self.handler.key_server.document_key_shadow(signature, document)
}
} }
impl<T> HttpHandler for KeyServerHttpHandler<T> where T: KeyServer + 'static { impl<T> HttpHandler for KeyServerHttpHandler<T> where T: KeyServer + 'static {
@ -111,6 +119,34 @@ impl<T> HttpHandler for KeyServerHttpHandler<T> where T: KeyServer + 'static {
err err
})); }));
}, },
Request::GetDocumentKeyShadow(document, signature) => {
match self.handler.key_server.document_key_shadow(&signature, &document)
.map_err(|err| {
warn!(target: "secretstore", "GetDocumentKeyShadow request {} has failed with: {}", req_uri, err);
err
}) {
Ok(document_key_shadow) => {
let document_key_shadow = SerializableDocumentEncryptedKeyShadow {
decrypted_secret: document_key_shadow.decrypted_secret.into(),
common_point: document_key_shadow.common_point.expect("always filled when requesting document_key_shadow; qed").into(),
decrypt_shadows: document_key_shadow.decrypt_shadows.expect("always filled when requesting document_key_shadow; qed").into_iter().map(Into::into).collect(),
};
match serde_json::to_vec(&document_key_shadow) {
Ok(document_key) => {
res.headers_mut().set(header::ContentType::json());
if let Err(err) = res.send(&document_key) {
// nothing to do, but to log an error
warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err);
}
},
Err(err) => {
warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err);
}
}
},
Err(err) => return_error(res, err),
}
},
Request::Invalid => { Request::Invalid => {
warn!(target: "secretstore", "Ignoring invalid {}-request {}", req_method, req_uri); warn!(target: "secretstore", "Ignoring invalid {}-request {}", req_method, req_uri);
*res.status_mut() = HttpStatusCode::BadRequest; *res.status_mut() = HttpStatusCode::BadRequest;
@ -134,11 +170,17 @@ fn return_document_key(req: HttpRequest, mut res: HttpResponse, document_key: Re
warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err); warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err);
} }
}, },
Err(Error::BadSignature) => *res.status_mut() = HttpStatusCode::BadRequest, Err(err) => return_error(res, err),
Err(Error::AccessDenied) => *res.status_mut() = HttpStatusCode::Forbidden, }
Err(Error::DocumentNotFound) => *res.status_mut() = HttpStatusCode::NotFound, }
Err(Error::Database(_)) => *res.status_mut() = HttpStatusCode::InternalServerError,
Err(Error::Internal(_)) => *res.status_mut() = HttpStatusCode::InternalServerError, fn return_error(mut res: HttpResponse, err: Error) {
match err {
Error::BadSignature => *res.status_mut() = HttpStatusCode::BadRequest,
Error::AccessDenied => *res.status_mut() = HttpStatusCode::Forbidden,
Error::DocumentNotFound => *res.status_mut() = HttpStatusCode::NotFound,
Error::Database(_) => *res.status_mut() = HttpStatusCode::InternalServerError,
Error::Internal(_) => *res.status_mut() = HttpStatusCode::InternalServerError,
} }
} }
@ -149,17 +191,27 @@ fn parse_request(method: &HttpMethod, uri_path: &str) -> Request {
}; };
let path: Vec<String> = uri_path.trim_left_matches('/').split('/').map(Into::into).collect(); let path: Vec<String> = uri_path.trim_left_matches('/').split('/').map(Into::into).collect();
if path.len() < 2 || path[0].is_empty() || path[1].is_empty() { if path.len() == 0 {
return Request::Invalid;
}
let (args_prefix, args_offset) = if &path[0] == "shadow" {
("shadow", 1)
} else {
("", 0)
};
if path.len() < 2 + args_offset || path[args_offset].is_empty() || path[args_offset + 1].is_empty() {
return Request::Invalid; return Request::Invalid;
} }
let args_len = path.len(); let args_len = path.len();
let document = path[0].parse(); let document = path[args_offset].parse();
let signature = path[1].parse(); let signature = path[args_offset + 1].parse();
let threshold = (if args_len > 2 { &path[2] } else { "" }).parse(); let threshold = (if args_len > args_offset + 2 { &path[args_offset + 2] } else { "" }).parse();
match (args_len, method, document, signature, threshold) { match (args_prefix, args_len, method, document, signature, threshold) {
(3, &HttpMethod::Post, Ok(document), Ok(signature), Ok(threshold)) => Request::GenerateDocumentKey(document, signature, threshold), ("", 3, &HttpMethod::Post, Ok(document), Ok(signature), Ok(threshold)) => Request::GenerateDocumentKey(document, signature, threshold),
(2, &HttpMethod::Get, Ok(document), Ok(signature), _) => Request::GetDocumentKey(document, signature), ("", 2, &HttpMethod::Get, Ok(document), Ok(signature), _) => Request::GetDocumentKey(document, signature),
("shadow", 3, &HttpMethod::Get, Ok(document), Ok(signature), _) => Request::GetDocumentKeyShadow(document, signature),
_ => Request::Invalid, _ => Request::Invalid,
} }
} }

View File

@ -26,7 +26,7 @@ use super::acl_storage::AclStorage;
use super::key_storage::KeyStorage; use super::key_storage::KeyStorage;
use key_server_cluster::ClusterCore; use key_server_cluster::ClusterCore;
use traits::KeyServer; use traits::KeyServer;
use types::all::{Error, RequestSignature, DocumentAddress, DocumentEncryptedKey, ClusterConfiguration}; use types::all::{Error, RequestSignature, DocumentAddress, DocumentEncryptedKey, DocumentEncryptedKeyShadow, ClusterConfiguration};
use key_server_cluster::{ClusterClient, ClusterConfiguration as NetClusterConfiguration}; use key_server_cluster::{ClusterClient, ClusterConfiguration as NetClusterConfiguration};
/// Secret store key server implementation /// Secret store key server implementation
@ -38,7 +38,7 @@ pub struct KeyServerImpl {
pub struct KeyServerCore { pub struct KeyServerCore {
close: Option<futures::Complete<()>>, close: Option<futures::Complete<()>>,
handle: Option<thread::JoinHandle<()>>, handle: Option<thread::JoinHandle<()>>,
cluster: Option<Arc<ClusterClient>>, cluster: Arc<ClusterClient>,
} }
impl KeyServerImpl { impl KeyServerImpl {
@ -53,7 +53,6 @@ impl KeyServerImpl {
/// Get cluster client reference. /// Get cluster client reference.
pub fn cluster(&self) -> Arc<ClusterClient> { pub fn cluster(&self) -> Arc<ClusterClient> {
self.data.lock().cluster.clone() self.data.lock().cluster.clone()
.expect("cluster can be None in test cfg only; test cfg is for correct tests; qed")
} }
} }
@ -64,9 +63,7 @@ impl KeyServer for KeyServerImpl {
.map_err(|_| Error::BadSignature)?; .map_err(|_| Error::BadSignature)?;
// generate document key // generate document key
let data = self.data.lock(); let encryption_session = self.data.lock().cluster.new_encryption_session(document.clone(), threshold)?;
let encryption_session = data.cluster.as_ref().expect("cluster can be None in test cfg only; test cfg is for correct tests; qed")
.new_encryption_session(document.clone(), threshold)?;
let document_key = encryption_session.wait()?; let document_key = encryption_session.wait()?;
// encrypt document key with requestor public key // encrypt document key with requestor public key
@ -80,17 +77,21 @@ impl KeyServer for KeyServerImpl {
let public = ethkey::recover(signature, document) let public = ethkey::recover(signature, document)
.map_err(|_| Error::BadSignature)?; .map_err(|_| Error::BadSignature)?;
// decrypt document key // decrypt document key
let data = self.data.lock(); let decryption_session = self.data.lock().cluster.new_decryption_session(document.clone(), signature.clone(), false)?;
let decryption_session = data.cluster.as_ref().expect("cluster can be None in test cfg only; test cfg is for correct tests; qed") let document_key = decryption_session.wait()?.decrypted_secret;
.new_decryption_session(document.clone(), signature.clone())?;
let document_key = decryption_session.wait()?;
// encrypt document key with requestor public key // encrypt document key with requestor public key
let document_key = ethcrypto::ecies::encrypt_single_message(&public, &document_key) let document_key = ethcrypto::ecies::encrypt_single_message(&public, &document_key)
.map_err(|err| Error::Internal(format!("Error encrypting document key: {}", err)))?; .map_err(|err| Error::Internal(format!("Error encrypting document key: {}", err)))?;
Ok(document_key) Ok(document_key)
} }
fn document_key_shadow(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKeyShadow, Error> {
let decryption_session = self.data.lock().cluster.new_decryption_session(document.clone(), signature.clone(), false)?;
decryption_session.wait().map_err(Into::into)
}
} }
impl KeyServerCore { impl KeyServerCore {
@ -129,7 +130,7 @@ impl KeyServerCore {
Ok(KeyServerCore { Ok(KeyServerCore {
close: Some(stop), close: Some(stop),
handle: Some(handle), handle: Some(handle),
cluster: Some(cluster), cluster: cluster,
}) })
} }
} }
@ -149,24 +150,9 @@ mod tests {
use ethkey::{self, Random, Generator}; use ethkey::{self, Random, Generator};
use acl_storage::tests::DummyAclStorage; use acl_storage::tests::DummyAclStorage;
use key_storage::tests::DummyKeyStorage; use key_storage::tests::DummyKeyStorage;
use types::all::{ClusterConfiguration, NodeAddress, EncryptionConfiguration, DocumentEncryptedKey, DocumentKey}; use types::all::{ClusterConfiguration, NodeAddress, EncryptionConfiguration};
use super::super::{RequestSignature, DocumentAddress};
use super::{KeyServer, KeyServerImpl}; use super::{KeyServer, KeyServerImpl};
const DOCUMENT1: &'static str = "0000000000000000000000000000000000000000000000000000000000000001";
const PRIVATE1: &'static str = "03055e18a8434dcc9061cc1b81c4ef84dc7cf4574d755e52cdcf0c8898b25b11";
fn make_signature(secret: &str, document: &'static str) -> RequestSignature {
let secret = secret.parse().unwrap();
let document: DocumentAddress = document.into();
ethkey::sign(&secret, &document).unwrap()
}
fn decrypt_document_key(secret: &str, document_key: DocumentEncryptedKey) -> DocumentKey {
let secret = secret.parse().unwrap();
ethcrypto::ecies::decrypt_single_message(&secret, &document_key).unwrap()
}
#[test] #[test]
fn document_key_generation_and_retrievement_works_over_network() { fn document_key_generation_and_retrievement_works_over_network() {
//::util::log::init_log(); //::util::log::init_log();
@ -208,15 +194,16 @@ mod tests {
let test_cases = [0, 1, 2]; let test_cases = [0, 1, 2];
for threshold in &test_cases { for threshold in &test_cases {
// generate document key // generate document key
// TODO: it is an error that we can regenerate key for the same DOCUMENT let document = Random.generate().unwrap().secret().clone();
let signature = make_signature(PRIVATE1, DOCUMENT1); let secret = Random.generate().unwrap().secret().clone();
let generated_key = key_servers[0].generate_document_key(&signature, &DOCUMENT1.into(), *threshold).unwrap(); let signature = ethkey::sign(&secret, &document).unwrap();
let generated_key = decrypt_document_key(PRIVATE1, generated_key); let generated_key = key_servers[0].generate_document_key(&signature, &document, *threshold).unwrap();
let generated_key = ethcrypto::ecies::decrypt_single_message(&secret, &generated_key).unwrap();
// now let's try to retrieve key back // now let's try to retrieve key back
for key_server in key_servers.iter() { for key_server in key_servers.iter() {
let retrieved_key = key_server.document_key(&signature, &DOCUMENT1.into()).unwrap(); let retrieved_key = key_server.document_key(&signature, &document).unwrap();
let retrieved_key = decrypt_document_key(PRIVATE1, retrieved_key); let retrieved_key = ethcrypto::ecies::decrypt_single_message(&secret, &retrieved_key).unwrap();
assert_eq!(retrieved_key, generated_key); assert_eq!(retrieved_key, generated_key);
} }
} }

View File

@ -23,7 +23,7 @@ use std::net::{SocketAddr, IpAddr};
use futures::{finished, failed, Future, Stream, BoxFuture}; use futures::{finished, failed, Future, Stream, BoxFuture};
use futures_cpupool::CpuPool; use futures_cpupool::CpuPool;
use parking_lot::{RwLock, Mutex}; use parking_lot::{RwLock, Mutex};
use tokio_core::io::IoFuture; use tokio_io::IoFuture;
use tokio_core::reactor::{Handle, Remote, Timeout, Interval}; use tokio_core::reactor::{Handle, Remote, Timeout, Interval};
use tokio_core::net::{TcpListener, TcpStream}; use tokio_core::net::{TcpListener, TcpStream};
use ethkey::{Secret, KeyPair, Signature, Random, Generator}; use ethkey::{Secret, KeyPair, Signature, Random, Generator};
@ -45,7 +45,7 @@ pub trait ClusterClient: Send + Sync {
/// Start new encryption session. /// Start new encryption session.
fn new_encryption_session(&self, session_id: SessionId, threshold: usize) -> Result<Arc<EncryptionSession>, Error>; fn new_encryption_session(&self, session_id: SessionId, threshold: usize) -> Result<Arc<EncryptionSession>, Error>;
/// Start new decryption session. /// Start new decryption session.
fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature) -> Result<Arc<DecryptionSession>, Error>; fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature, is_shadow_decryption: bool) -> Result<Arc<DecryptionSession>, Error>;
} }
/// Cluster access for single encryption/decryption participant. /// Cluster access for single encryption/decryption participant.
@ -181,7 +181,7 @@ pub struct Connection {
/// Tcp stream. /// Tcp stream.
stream: SharedTcpStream, stream: SharedTcpStream,
/// Connection key. /// Connection key.
key: Secret, key: KeyPair,
/// Last message time. /// Last message time.
last_message_time: Mutex<time::Instant>, last_message_time: Mutex<time::Instant>,
} }
@ -649,9 +649,14 @@ impl ClusterSessions {
pub fn new_encryption_session(&self, _master: NodeId, session_id: SessionId, cluster: Arc<Cluster>) -> Result<Arc<EncryptionSessionImpl>, Error> { pub fn new_encryption_session(&self, _master: NodeId, session_id: SessionId, cluster: Arc<Cluster>) -> Result<Arc<EncryptionSessionImpl>, Error> {
let mut encryption_sessions = self.encryption_sessions.write(); let mut encryption_sessions = self.encryption_sessions.write();
// check that there's no active encryption session with the same id
if encryption_sessions.contains_key(&session_id) { if encryption_sessions.contains_key(&session_id) {
return Err(Error::DuplicateSessionId); return Err(Error::DuplicateSessionId);
} }
// check that there's no finished encryption session with the same id
if self.key_storage.contains(&session_id) {
return Err(Error::DuplicateSessionId);
}
let session = Arc::new(EncryptionSessionImpl::new(EncryptionSessionParams { let session = Arc::new(EncryptionSessionImpl::new(EncryptionSessionParams {
id: session_id.clone(), id: session_id.clone(),
@ -865,14 +870,14 @@ impl ClusterClient for ClusterClientImpl {
Ok(session) Ok(session)
} }
fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature) -> Result<Arc<DecryptionSession>, Error> { fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature, is_shadow_decryption: bool) -> Result<Arc<DecryptionSession>, Error> {
let mut connected_nodes = self.data.connections.connected_nodes(); let mut connected_nodes = self.data.connections.connected_nodes();
connected_nodes.insert(self.data.self_key_pair.public().clone()); connected_nodes.insert(self.data.self_key_pair.public().clone());
let access_key = Random.generate()?.secret().clone(); let access_key = Random.generate()?.secret().clone();
let cluster = Arc::new(ClusterView::new(self.data.clone(), connected_nodes.clone())); let cluster = Arc::new(ClusterView::new(self.data.clone(), connected_nodes.clone()));
let session = self.data.sessions.new_decryption_session(self.data.self_key_pair.public().clone(), session_id, access_key, cluster)?; let session = self.data.sessions.new_decryption_session(self.data.self_key_pair.public().clone(), session_id, access_key, cluster)?;
session.initialize(requestor_signature)?; session.initialize(requestor_signature, is_shadow_decryption)?;
Ok(session) Ok(session)
} }
} }

View File

@ -18,8 +18,9 @@ use std::cmp::{Ord, PartialOrd, Ordering};
use std::collections::{BTreeSet, BTreeMap}; use std::collections::{BTreeSet, BTreeMap};
use std::sync::Arc; use std::sync::Arc;
use parking_lot::{Mutex, Condvar}; use parking_lot::{Mutex, Condvar};
use ethcrypto::ecies::encrypt_single_message;
use ethkey::{self, Secret, Public, Signature}; use ethkey::{self, Secret, Public, Signature};
use key_server_cluster::{Error, AclStorage, DocumentKeyShare, NodeId, SessionId}; use key_server_cluster::{Error, AclStorage, DocumentKeyShare, NodeId, SessionId, DocumentEncryptedKeyShadow};
use key_server_cluster::cluster::Cluster; use key_server_cluster::cluster::Cluster;
use key_server_cluster::math; use key_server_cluster::math;
use key_server_cluster::message::{Message, DecryptionMessage, InitializeDecryptionSession, ConfirmDecryptionInitialization, use key_server_cluster::message::{Message, DecryptionMessage, InitializeDecryptionSession, ConfirmDecryptionInitialization,
@ -28,7 +29,7 @@ use key_server_cluster::message::{Message, DecryptionMessage, InitializeDecrypti
/// Decryption session API. /// Decryption session API.
pub trait Session: Send + Sync + 'static { pub trait Session: Send + Sync + 'static {
/// Wait until session is completed. Returns distributely restored secret key. /// Wait until session is completed. Returns distributely restored secret key.
fn wait(&self) -> Result<Public, Error>; fn wait(&self) -> Result<DocumentEncryptedKeyShadow, Error>;
} }
/// Distributed decryption session. /// Distributed decryption session.
@ -83,6 +84,15 @@ pub struct SessionParams {
pub cluster: Arc<Cluster>, pub cluster: Arc<Cluster>,
} }
#[derive(Debug)]
/// Partial decryption result.
struct PartialDecryptionResult {
/// Shadow point.
pub shadow_point: Public,
/// Decryption shadow coefficient, if requested.
pub decrypt_shadow: Option<Vec<u8>>,
}
#[derive(Debug)] #[derive(Debug)]
/// Mutable data of encryption (distributed key generation) session. /// Mutable data of encryption (distributed key generation) session.
struct SessionData { struct SessionData {
@ -94,6 +104,8 @@ struct SessionData {
master: Option<NodeId>, master: Option<NodeId>,
/// Public key of requestor. /// Public key of requestor.
requestor: Option<Public>, requestor: Option<Public>,
/// Is shadow decryption requested?
is_shadow_decryption: Option<bool>,
// === Values, filled during session initialization === // === Values, filled during session initialization ===
/// Nodes, which have been requested for decryption initialization. /// Nodes, which have been requested for decryption initialization.
@ -105,11 +117,11 @@ struct SessionData {
// === Values, filled during partial decryption === // === Values, filled during partial decryption ===
/// Shadow points, received from nodes as a response to partial decryption request. /// Shadow points, received from nodes as a response to partial decryption request.
shadow_points: BTreeMap<NodeId, Public>, shadow_points: BTreeMap<NodeId, PartialDecryptionResult>,
/// === Values, filled during final decryption === /// === Values, filled during final decryption ===
/// Decrypted secret /// Decrypted secret
decrypted_secret: Option<Result<Public, Error>>, decrypted_secret: Option<Result<DocumentEncryptedKeyShadow, Error>>,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -146,6 +158,7 @@ impl SessionImpl {
state: SessionState::WaitingForInitialization, state: SessionState::WaitingForInitialization,
master: None, master: None,
requestor: None, requestor: None,
is_shadow_decryption: None,
requested_nodes: BTreeSet::new(), requested_nodes: BTreeSet::new(),
rejected_nodes: BTreeSet::new(), rejected_nodes: BTreeSet::new(),
confirmed_nodes: BTreeSet::new(), confirmed_nodes: BTreeSet::new(),
@ -174,12 +187,12 @@ impl SessionImpl {
#[cfg(test)] #[cfg(test)]
/// Get decrypted secret /// Get decrypted secret
pub fn decrypted_secret(&self) -> Option<Public> { pub fn decrypted_secret(&self) -> Option<DocumentEncryptedKeyShadow> {
self.data.lock().decrypted_secret.clone().and_then(|r| r.ok()) self.data.lock().decrypted_secret.clone().and_then(|r| r.ok())
} }
/// Initialize decryption session. /// Initialize decryption session.
pub fn initialize(&self, requestor_signature: Signature) -> Result<(), Error> { pub fn initialize(&self, requestor_signature: Signature, is_shadow_decryption: bool) -> Result<(), Error> {
let mut data = self.data.lock(); let mut data = self.data.lock();
// check state // check state
@ -194,6 +207,7 @@ impl SessionImpl {
data.master = Some(self.node().clone()); data.master = Some(self.node().clone());
data.state = SessionState::WaitingForInitializationConfirm; data.state = SessionState::WaitingForInitializationConfirm;
data.requestor = Some(requestor_public.clone()); data.requestor = Some(requestor_public.clone());
data.is_shadow_decryption = Some(is_shadow_decryption);
data.requested_nodes.extend(self.encrypted_data.id_numbers.keys().cloned()); data.requested_nodes.extend(self.encrypted_data.id_numbers.keys().cloned());
// ..and finally check access on our's own // ..and finally check access on our's own
@ -209,6 +223,7 @@ impl SessionImpl {
session: self.id.clone().into(), session: self.id.clone().into(),
sub_session: self.access_key.clone().into(), sub_session: self.access_key.clone().into(),
requestor_signature: requestor_signature.clone().into(), requestor_signature: requestor_signature.clone().into(),
is_shadow_decryption: is_shadow_decryption,
})))?; })))?;
} }
}, },
@ -249,6 +264,7 @@ impl SessionImpl {
data.state = if is_requestor_allowed_to_read { SessionState::WaitingForPartialDecryptionRequest } data.state = if is_requestor_allowed_to_read { SessionState::WaitingForPartialDecryptionRequest }
else { SessionState::Failed }; else { SessionState::Failed };
data.requestor = Some(requestor_public); data.requestor = Some(requestor_public);
data.is_shadow_decryption = Some(message.is_shadow_decryption);
// respond to master node // respond to master node
data.master = Some(sender.clone()); data.master = Some(sender.clone());
@ -316,14 +332,17 @@ impl SessionImpl {
} }
// calculate shadow point // calculate shadow point
let shadow_point = { let decryption_result = {
let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryptionRequest follows initialization; qed"); let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryptionRequest follows initialization; qed");
do_partial_decryption(self.node(), &requestor, &message.nodes.iter().cloned().map(Into::into).collect(), &self.access_key, &self.encrypted_data)? let is_shadow_decryption = data.is_shadow_decryption.expect("is_shadow_decryption is filled during initialization; WaitingForPartialDecryptionRequest follows initialization; qed");
let nodes = message.nodes.iter().cloned().map(Into::into).collect();
do_partial_decryption(self.node(), &requestor, is_shadow_decryption, &nodes, &self.access_key, &self.encrypted_data)?
}; };
self.cluster.send(&sender, Message::Decryption(DecryptionMessage::PartialDecryption(PartialDecryption { self.cluster.send(&sender, Message::Decryption(DecryptionMessage::PartialDecryption(PartialDecryption {
session: self.id.clone().into(), session: self.id.clone().into(),
sub_session: self.access_key.clone().into(), sub_session: self.access_key.clone().into(),
shadow_point: shadow_point.into(), shadow_point: decryption_result.shadow_point.into(),
decrypt_shadow: decryption_result.decrypt_shadow,
})))?; })))?;
// update sate // update sate
@ -348,7 +367,10 @@ impl SessionImpl {
if !data.confirmed_nodes.remove(&sender) { if !data.confirmed_nodes.remove(&sender) {
return Err(Error::InvalidStateForRequest); return Err(Error::InvalidStateForRequest);
} }
data.shadow_points.insert(sender, message.shadow_point.clone().into()); data.shadow_points.insert(sender, PartialDecryptionResult {
shadow_point: message.shadow_point.clone().into(),
decrypt_shadow: message.decrypt_shadow.clone(),
});
// check if we have enough shadow points to decrypt the secret // check if we have enough shadow points to decrypt the secret
if data.shadow_points.len() != self.encrypted_data.threshold + 1 { if data.shadow_points.len() != self.encrypted_data.threshold + 1 {
@ -390,22 +412,38 @@ impl SessionImpl {
})))?; })))?;
} }
assert!(data.confirmed_nodes.remove(&self_node_id)); if data.confirmed_nodes.remove(&self_node_id) {
let decryption_result = {
let shadow_point = {
let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryption follows initialization; qed"); let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryption follows initialization; qed");
do_partial_decryption(&self_node_id, &requestor, &data.confirmed_nodes, &access_key, &encrypted_data)? let is_shadow_decryption = data.is_shadow_decryption.expect("is_shadow_decryption is filled during initialization; WaitingForPartialDecryption follows initialization; qed");
do_partial_decryption(&self_node_id, &requestor, is_shadow_decryption, &data.confirmed_nodes, &access_key, &encrypted_data)?
}; };
data.shadow_points.insert(self_node_id.clone(), shadow_point); data.shadow_points.insert(self_node_id.clone(), decryption_result);
}
Ok(()) Ok(())
} }
fn do_decryption(access_key: Secret, encrypted_data: &DocumentKeyShare, data: &mut SessionData) -> Result<(), Error> { fn do_decryption(access_key: Secret, encrypted_data: &DocumentKeyShare, data: &mut SessionData) -> Result<(), Error> {
// decrypt the secret using shadow points // decrypt the secret using shadow points
let joint_shadow_point = math::compute_joint_shadow_point(data.shadow_points.values())?; let joint_shadow_point = math::compute_joint_shadow_point(data.shadow_points.values().map(|s| &s.shadow_point))?;
let decrypted_secret = math::decrypt_with_joint_shadow(encrypted_data.threshold, &access_key, &encrypted_data.encrypted_point, &joint_shadow_point)?; let decrypted_secret = math::decrypt_with_joint_shadow(encrypted_data.threshold, &access_key, &encrypted_data.encrypted_point, &joint_shadow_point)?;
data.decrypted_secret = Some(Ok(decrypted_secret)); let is_shadow_decryption = data.is_shadow_decryption.expect("is_shadow_decryption is filled during initialization; decryption follows initialization; qed");
let (common_point, decrypt_shadows) = if is_shadow_decryption {
(
Some(math::make_common_shadow_point(encrypted_data.threshold, encrypted_data.common_point.clone())?),
Some(data.shadow_points.values()
.map(|s| s.decrypt_shadow.as_ref().expect("decrypt_shadow is filled during partial decryption; decryption follows partial decryption; qed").clone())
.collect())
)
} else {
(None, None)
};
data.decrypted_secret = Some(Ok(DocumentEncryptedKeyShadow {
decrypted_secret: decrypted_secret,
common_point: common_point,
decrypt_shadows: decrypt_shadows,
}));
// switch to completed state // switch to completed state
data.state = SessionState::Finished; data.state = SessionState::Finished;
@ -415,7 +453,7 @@ impl SessionImpl {
} }
impl Session for SessionImpl { impl Session for SessionImpl {
fn wait(&self) -> Result<Public, Error> { fn wait(&self) -> Result<DocumentEncryptedKeyShadow, Error> {
let mut data = self.data.lock(); let mut data = self.data.lock();
if !data.decrypted_secret.is_some() { if !data.decrypted_secret.is_some() {
self.completed.wait(&mut data); self.completed.wait(&mut data);
@ -492,15 +530,22 @@ fn process_initialization_response(encrypted_data: &DocumentKeyShare, data: &mut
Ok(()) Ok(())
} }
fn do_partial_decryption(node: &NodeId, _requestor_public: &Public, participants: &BTreeSet<NodeId>, access_key: &Secret, encrypted_data: &DocumentKeyShare) -> Result<Public, Error> { fn do_partial_decryption(node: &NodeId, requestor_public: &Public, is_shadow_decryption: bool, participants: &BTreeSet<NodeId>, access_key: &Secret, encrypted_data: &DocumentKeyShare) -> Result<PartialDecryptionResult, Error> {
let node_id_number = &encrypted_data.id_numbers[node]; let node_id_number = &encrypted_data.id_numbers[node];
let node_secret_share = &encrypted_data.secret_share; let node_secret_share = &encrypted_data.secret_share;
let other_id_numbers = participants.iter() let other_id_numbers = participants.iter()
.filter(|id| *id != node) .filter(|id| *id != node)
.map(|id| &encrypted_data.id_numbers[id]); .map(|id| &encrypted_data.id_numbers[id]);
// TODO: commutative encryption using _requestor_public
let node_shadow = math::compute_node_shadow(node_id_number, node_secret_share, other_id_numbers)?; let node_shadow = math::compute_node_shadow(node_id_number, node_secret_share, other_id_numbers)?;
math::compute_node_shadow_point(access_key, &encrypted_data.common_point, &node_shadow) let decrypt_shadow = if is_shadow_decryption { Some(math::generate_random_scalar()?) } else { None };
let (shadow_point, decrypt_shadow) = math::compute_node_shadow_point(access_key, &encrypted_data.common_point, &node_shadow, decrypt_shadow)?;
Ok(PartialDecryptionResult {
shadow_point: shadow_point,
decrypt_shadow: match decrypt_shadow {
None => None,
Some(decrypt_shadow) => Some(encrypt_single_message(requestor_public, &**decrypt_shadow)?),
},
})
} }
#[cfg(test)] #[cfg(test)]
@ -509,10 +554,11 @@ mod tests {
use std::collections::BTreeMap; use std::collections::BTreeMap;
use super::super::super::acl_storage::tests::DummyAclStorage; use super::super::super::acl_storage::tests::DummyAclStorage;
use ethkey::{self, Random, Generator, Public, Secret}; use ethkey::{self, Random, Generator, Public, Secret};
use key_server_cluster::{NodeId, DocumentKeyShare, SessionId, Error}; use key_server_cluster::{NodeId, DocumentKeyShare, SessionId, Error, DocumentEncryptedKeyShadow};
use key_server_cluster::cluster::tests::DummyCluster; use key_server_cluster::cluster::tests::DummyCluster;
use key_server_cluster::decryption_session::{SessionImpl, SessionParams, SessionState}; use key_server_cluster::decryption_session::{SessionImpl, SessionParams, SessionState};
use key_server_cluster::message::{self, Message, DecryptionMessage}; use key_server_cluster::message::{self, Message, DecryptionMessage};
use key_server_cluster::math;
const SECRET_PLAIN: &'static str = "d2b57ae7619e070af0af6bc8c703c0cd27814c54d5d6a999cacac0da34ede279ca0d9216e85991029e54e2f0c92ee0bd30237725fa765cbdbfc4529489864c5f"; const SECRET_PLAIN: &'static str = "d2b57ae7619e070af0af6bc8c703c0cd27814c54d5d6a999cacac0da34ede279ca0d9216e85991029e54e2f0c92ee0bd30237725fa765cbdbfc4529489864c5f";
@ -660,18 +706,19 @@ mod tests {
#[test] #[test]
fn fails_to_initialize_when_already_initialized() { fn fails_to_initialize_when_already_initialized() {
let (_, _, sessions) = prepare_decryption_sessions(); let (_, _, sessions) = prepare_decryption_sessions();
assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(), ()); assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), false).unwrap(), ());
assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap_err(), Error::InvalidStateForRequest); assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), false).unwrap_err(), Error::InvalidStateForRequest);
} }
#[test] #[test]
fn fails_to_accept_initialization_when_already_initialized() { fn fails_to_accept_initialization_when_already_initialized() {
let (_, _, sessions) = prepare_decryption_sessions(); let (_, _, sessions) = prepare_decryption_sessions();
assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(), ()); assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), false).unwrap(), ());
assert_eq!(sessions[0].on_initialize_session(sessions[1].node().clone(), &message::InitializeDecryptionSession { assert_eq!(sessions[0].on_initialize_session(sessions[1].node().clone(), &message::InitializeDecryptionSession {
session: SessionId::default().into(), session: SessionId::default().into(),
sub_session: sessions[0].access_key().clone().into(), sub_session: sessions[0].access_key().clone().into(),
requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(),
is_shadow_decryption: false,
}).unwrap_err(), Error::InvalidStateForRequest); }).unwrap_err(), Error::InvalidStateForRequest);
} }
@ -682,6 +729,7 @@ mod tests {
session: SessionId::default().into(), session: SessionId::default().into(),
sub_session: sessions[0].access_key().clone().into(), sub_session: sessions[0].access_key().clone().into(),
requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(),
is_shadow_decryption: false,
}).unwrap(), ()); }).unwrap(), ());
assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), &message::RequestPartialDecryption { assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), &message::RequestPartialDecryption {
session: SessionId::default().into(), session: SessionId::default().into(),
@ -702,6 +750,7 @@ mod tests {
session: SessionId::default().into(), session: SessionId::default().into(),
sub_session: sessions[0].access_key().clone().into(), sub_session: sessions[0].access_key().clone().into(),
requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(),
is_shadow_decryption: false,
}).unwrap(), ()); }).unwrap(), ());
assert_eq!(sessions[1].on_partial_decryption_requested(sessions[2].node().clone(), &message::RequestPartialDecryption { assert_eq!(sessions[1].on_partial_decryption_requested(sessions[2].node().clone(), &message::RequestPartialDecryption {
session: SessionId::default().into(), session: SessionId::default().into(),
@ -717,6 +766,7 @@ mod tests {
session: SessionId::default().into(), session: SessionId::default().into(),
sub_session: sessions[0].access_key().clone().into(), sub_session: sessions[0].access_key().clone().into(),
requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(),
is_shadow_decryption: false,
}).unwrap(), ()); }).unwrap(), ());
assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), &message::RequestPartialDecryption { assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), &message::RequestPartialDecryption {
session: SessionId::default().into(), session: SessionId::default().into(),
@ -732,13 +782,14 @@ mod tests {
session: SessionId::default().into(), session: SessionId::default().into(),
sub_session: sessions[0].access_key().clone().into(), sub_session: sessions[0].access_key().clone().into(),
shadow_point: Random.generate().unwrap().public().clone().into(), shadow_point: Random.generate().unwrap().public().clone().into(),
decrypt_shadow: None,
}).unwrap_err(), Error::InvalidStateForRequest); }).unwrap_err(), Error::InvalidStateForRequest);
} }
#[test] #[test]
fn fails_to_accept_partial_decrypt_twice() { fn fails_to_accept_partial_decrypt_twice() {
let (clusters, _, sessions) = prepare_decryption_sessions(); let (clusters, _, sessions) = prepare_decryption_sessions();
sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(); sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), false).unwrap();
let mut pd_from = None; let mut pd_from = None;
let mut pd_msg = None; let mut pd_msg = None;
@ -762,7 +813,7 @@ mod tests {
// now let's try to do a decryption // now let's try to do a decryption
let key_pair = Random.generate().unwrap(); let key_pair = Random.generate().unwrap();
let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap(); let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap();
sessions[0].initialize(signature).unwrap(); sessions[0].initialize(signature, false).unwrap();
do_messages_exchange(&clusters, &sessions); do_messages_exchange(&clusters, &sessions);
@ -773,7 +824,45 @@ mod tests {
assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::WaitingForPartialDecryptionRequest).count(), 1); assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::WaitingForPartialDecryptionRequest).count(), 1);
// 3) 1 session has decrypted key value // 3) 1 session has decrypted key value
assert!(sessions.iter().skip(1).all(|s| s.decrypted_secret().is_none())); assert!(sessions.iter().skip(1).all(|s| s.decrypted_secret().is_none()));
assert_eq!(sessions[0].decrypted_secret(), Some(SECRET_PLAIN.into())); assert_eq!(sessions[0].decrypted_secret(), Some(DocumentEncryptedKeyShadow {
decrypted_secret: SECRET_PLAIN.into(),
common_point: None,
decrypt_shadows: None,
}));
}
#[test]
fn complete_shadow_dec_session() {
let (clusters, _, sessions) = prepare_decryption_sessions();
// now let's try to do a decryption
let key_pair = Random.generate().unwrap();
let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap();
sessions[0].initialize(signature, true).unwrap();
do_messages_exchange(&clusters, &sessions);
// now check that:
// 1) 4 of 5 sessions are in Finished state
assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::Finished).count(), 4);
// 2) 1 session is in WaitingForPartialDecryptionRequest state
assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::WaitingForPartialDecryptionRequest).count(), 1);
// 3) 1 session has decrypted key value
assert!(sessions.iter().skip(1).all(|s| s.decrypted_secret().is_none()));
let decrypted_secret = sessions[0].decrypted_secret().unwrap();
// check that decrypted_secret != SECRET_PLAIN
assert!(decrypted_secret.decrypted_secret != SECRET_PLAIN.into());
// check that common point && shadow coefficients are returned
assert!(decrypted_secret.common_point.is_some());
assert!(decrypted_secret.decrypt_shadows.is_some());
// check that KS client is able to restore original secret
use ethcrypto::ecies::decrypt_single_message;
let decrypt_shadows: Vec<_> = decrypted_secret.decrypt_shadows.unwrap().into_iter()
.map(|c| Secret::from_slice(&decrypt_single_message(key_pair.secret(), &c).unwrap()).unwrap())
.collect();
let decrypted_secret = math::decrypt_with_shadow_coefficients(decrypted_secret.decrypted_secret, decrypted_secret.common_point.unwrap(), decrypt_shadows).unwrap();
assert_eq!(decrypted_secret, SECRET_PLAIN.into());
} }
#[test] #[test]
@ -783,7 +872,7 @@ mod tests {
// now let's try to do a decryption // now let's try to do a decryption
let key_pair = Random.generate().unwrap(); let key_pair = Random.generate().unwrap();
let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap(); let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap();
sessions[0].initialize(signature).unwrap(); sessions[0].initialize(signature, false).unwrap();
// we need 4 out of 5 nodes to agree to do a decryption // we need 4 out of 5 nodes to agree to do a decryption
// let's say that 2 of these nodes are disagree // let's say that 2 of these nodes are disagree
@ -801,6 +890,33 @@ mod tests {
assert!(sessions.iter().all(|s| s.decrypted_secret().is_none())); assert!(sessions.iter().all(|s| s.decrypted_secret().is_none()));
} }
#[test]
fn complete_dec_session_with_acl_check_failed_on_master() {
let (clusters, acl_storages, sessions) = prepare_decryption_sessions();
// we need 4 out of 5 nodes to agree to do a decryption
// let's say that 1 of these nodes (master) is disagree
let key_pair = Random.generate().unwrap();
acl_storages[0].prohibit(key_pair.public().clone(), SessionId::default());
// now let's try to do a decryption
let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap();
sessions[0].initialize(signature, false).unwrap();
do_messages_exchange(&clusters, &sessions);
// now check that:
// 1) 4 of 5 sessions are in Finished state
assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::Finished).count(), 5);
// 2) 1 session has decrypted key value
assert!(sessions.iter().skip(1).all(|s| s.decrypted_secret().is_none()));
assert_eq!(sessions[0].decrypted_secret(), Some(DocumentEncryptedKeyShadow {
decrypted_secret: SECRET_PLAIN.into(),
common_point: None,
decrypt_shadows: None,
}));
}
#[test] #[test]
fn decryption_session_works_over_network() { fn decryption_session_works_over_network() {
// TODO // TODO

View File

@ -17,21 +17,22 @@
use std::io; use std::io;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use futures::{Future, Poll, Async}; use futures::{Future, Poll, Async};
use tokio_io::{AsyncRead, AsyncWrite};
use ethkey::{Random, Generator, KeyPair, Secret, sign, verify_public}; use ethkey::{Random, Generator, KeyPair, Secret, sign, verify_public};
use util::H256; use util::H256;
use key_server_cluster::{NodeId, Error}; use key_server_cluster::{NodeId, Error};
use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature}; use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature};
use key_server_cluster::io::{write_message, write_encrypted_message, WriteMessage, ReadMessage, use key_server_cluster::io::{write_message, write_encrypted_message, WriteMessage, ReadMessage,
read_message, compute_shared_key}; read_message, read_encrypted_message, compute_shared_key};
/// Start handshake procedure with another node from the cluster. /// Start handshake procedure with another node from the cluster.
pub fn handshake<A>(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: io::Write + io::Read { pub fn handshake<A>(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: AsyncWrite + AsyncRead {
let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into); let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into);
handshake_with_plain_confirmation(a, self_confirmation_plain, self_key_pair, trusted_nodes) handshake_with_plain_confirmation(a, self_confirmation_plain, self_key_pair, trusted_nodes)
} }
/// Start handshake procedure with another node from the cluster and given plain confirmation. /// Start handshake procedure with another node from the cluster and given plain confirmation.
pub fn handshake_with_plain_confirmation<A>(a: A, self_confirmation_plain: Result<H256, Error>, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: io::Write + io::Read { pub fn handshake_with_plain_confirmation<A>(a: A, self_confirmation_plain: Result<H256, Error>, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: AsyncWrite + AsyncRead {
let (error, state) = match self_confirmation_plain.clone() let (error, state) = match self_confirmation_plain.clone()
.and_then(|c| Handshake::<A>::make_public_key_message(self_key_pair.public().clone(), c)) { .and_then(|c| Handshake::<A>::make_public_key_message(self_key_pair.public().clone(), c)) {
Ok(message) => (None, HandshakeState::SendPublicKey(write_message(a, message))), Ok(message) => (None, HandshakeState::SendPublicKey(write_message(a, message))),
@ -52,7 +53,7 @@ pub fn handshake_with_plain_confirmation<A>(a: A, self_confirmation_plain: Resul
} }
/// Wait for handshake procedure to be started by another node from the cluster. /// Wait for handshake procedure to be started by another node from the cluster.
pub fn accept_handshake<A>(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: io::Write + io::Read { pub fn accept_handshake<A>(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: AsyncWrite + AsyncRead {
let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into); let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into);
let (error, state) = match self_confirmation_plain.clone() { let (error, state) = match self_confirmation_plain.clone() {
Ok(_) => (None, HandshakeState::ReceivePublicKey(read_message(a))), Ok(_) => (None, HandshakeState::ReceivePublicKey(read_message(a))),
@ -78,7 +79,7 @@ pub struct HandshakeResult {
/// Node id. /// Node id.
pub node_id: NodeId, pub node_id: NodeId,
/// Shared key. /// Shared key.
pub shared_key: Secret, pub shared_key: KeyPair,
} }
/// Future handshake procedure. /// Future handshake procedure.
@ -91,7 +92,7 @@ pub struct Handshake<A> {
trusted_nodes: BTreeSet<NodeId>, trusted_nodes: BTreeSet<NodeId>,
other_node_id: Option<NodeId>, other_node_id: Option<NodeId>,
other_confirmation_plain: Option<H256>, other_confirmation_plain: Option<H256>,
shared_key: Option<Secret>, shared_key: Option<KeyPair>,
} }
/// Active handshake state. /// Active handshake state.
@ -103,7 +104,7 @@ enum HandshakeState<A> {
Finished, Finished,
} }
impl<A> Handshake<A> where A: io::Read + io::Write { impl<A> Handshake<A> where A: AsyncRead + AsyncWrite {
#[cfg(test)] #[cfg(test)]
pub fn set_self_confirmation_plain(&mut self, self_confirmation_plain: H256) { pub fn set_self_confirmation_plain(&mut self, self_confirmation_plain: H256) {
self.self_confirmation_plain = self_confirmation_plain; self.self_confirmation_plain = self_confirmation_plain;
@ -123,7 +124,7 @@ impl<A> Handshake<A> where A: io::Read + io::Write {
} }
} }
impl<A> Future for Handshake<A> where A: io::Read + io::Write { impl<A> Future for Handshake<A> where A: AsyncRead + AsyncWrite {
type Item = (A, Result<HandshakeResult, Error>); type Item = (A, Result<HandshakeResult, Error>);
type Error = io::Error; type Error = io::Error;
@ -207,7 +208,9 @@ impl<A> Future for Handshake<A> where A: io::Read + io::Write {
let (stream, _) = try_ready!(future.poll()); let (stream, _) = try_ready!(future.poll());
(HandshakeState::ReceivePrivateKeySignature( (HandshakeState::ReceivePrivateKeySignature(
read_message(stream) read_encrypted_message(stream,
self.shared_key.as_ref().expect("shared_key is filled in Send/ReceivePublicKey; SendPrivateKeySignature follows Send/ReceivePublicKey; qed").clone()
)
), Async::NotReady) ), Async::NotReady)
}, },
HandshakeState::ReceivePrivateKeySignature(ref mut future) => { HandshakeState::ReceivePrivateKeySignature(ref mut future) => {
@ -247,9 +250,9 @@ impl<A> Future for Handshake<A> where A: io::Read + io::Write {
mod tests { mod tests {
use std::collections::BTreeSet; use std::collections::BTreeSet;
use futures::Future; use futures::Future;
use ethcrypto::ecdh::agree;
use ethkey::{Random, Generator, sign}; use ethkey::{Random, Generator, sign};
use util::H256; use util::H256;
use key_server_cluster::io::message::compute_shared_key;
use key_server_cluster::io::message::tests::TestIo; use key_server_cluster::io::message::tests::TestIo;
use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature}; use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature};
use super::{handshake_with_plain_confirmation, accept_handshake, HandshakeResult}; use super::{handshake_with_plain_confirmation, accept_handshake, HandshakeResult};
@ -263,24 +266,15 @@ mod tests {
let peer_confirmation_plain = *Random.generate().unwrap().secret().clone(); let peer_confirmation_plain = *Random.generate().unwrap().secret().clone();
let self_confirmation_signed = sign(peer_key_pair.secret(), &self_confirmation_plain).unwrap(); let self_confirmation_signed = sign(peer_key_pair.secret(), &self_confirmation_plain).unwrap();
let peer_confirmation_signed = sign(self_key_pair.secret(), &peer_confirmation_plain).unwrap();
io.add_input_message(Message::Cluster(ClusterMessage::NodePublicKey(NodePublicKey { io.add_input_message(Message::Cluster(ClusterMessage::NodePublicKey(NodePublicKey {
node_id: peer_key_pair.public().clone().into(), node_id: peer_key_pair.public().clone().into(),
confirmation_plain: peer_confirmation_plain.into(), confirmation_plain: peer_confirmation_plain.into(),
}))); })));
io.add_input_message(Message::Cluster(ClusterMessage::NodePrivateKeySignature(NodePrivateKeySignature { io.add_encrypted_input_message(Message::Cluster(ClusterMessage::NodePrivateKeySignature(NodePrivateKeySignature {
confirmation_signed: self_confirmation_signed.into(), confirmation_signed: self_confirmation_signed.into(),
}))); })));
io.add_output_message(Message::Cluster(ClusterMessage::NodePublicKey(NodePublicKey {
node_id: self_key_pair.public().clone().into(),
confirmation_plain: self_confirmation_plain.clone().into(),
})));
io.add_output_message(Message::Cluster(ClusterMessage::NodePrivateKeySignature(NodePrivateKeySignature {
confirmation_signed: peer_confirmation_signed.into(),
})));
(self_confirmation_plain, io) (self_confirmation_plain, io)
} }
@ -289,7 +283,7 @@ mod tests {
let (self_confirmation_plain, io) = prepare_test_io(); let (self_confirmation_plain, io) = prepare_test_io();
let self_key_pair = io.self_key_pair().clone(); let self_key_pair = io.self_key_pair().clone();
let trusted_nodes: BTreeSet<_> = vec![io.peer_public().clone()].into_iter().collect(); let trusted_nodes: BTreeSet<_> = vec![io.peer_public().clone()].into_iter().collect();
let shared_key = agree(self_key_pair.secret(), trusted_nodes.iter().nth(0).unwrap()).unwrap(); let shared_key = compute_shared_key(self_key_pair.secret(), trusted_nodes.iter().nth(0).unwrap()).unwrap();
let handshake = handshake_with_plain_confirmation(io, Ok(self_confirmation_plain), self_key_pair, trusted_nodes); let handshake = handshake_with_plain_confirmation(io, Ok(self_confirmation_plain), self_key_pair, trusted_nodes);
let handshake_result = handshake.wait().unwrap(); let handshake_result = handshake.wait().unwrap();
@ -297,7 +291,6 @@ mod tests {
node_id: handshake_result.0.peer_public().clone(), node_id: handshake_result.0.peer_public().clone(),
shared_key: shared_key, shared_key: shared_key,
})); }));
handshake_result.0.assert_output();
} }
#[test] #[test]
@ -305,7 +298,7 @@ mod tests {
let (self_confirmation_plain, io) = prepare_test_io(); let (self_confirmation_plain, io) = prepare_test_io();
let self_key_pair = io.self_key_pair().clone(); let self_key_pair = io.self_key_pair().clone();
let trusted_nodes: BTreeSet<_> = vec![io.peer_public().clone()].into_iter().collect(); let trusted_nodes: BTreeSet<_> = vec![io.peer_public().clone()].into_iter().collect();
let shared_key = agree(self_key_pair.secret(), io.peer_public()).unwrap(); let shared_key = compute_shared_key(self_key_pair.secret(), trusted_nodes.iter().nth(0).unwrap()).unwrap();
let mut handshake = accept_handshake(io, self_key_pair, trusted_nodes); let mut handshake = accept_handshake(io, self_key_pair, trusted_nodes);
handshake.set_self_confirmation_plain(self_confirmation_plain); handshake.set_self_confirmation_plain(self_confirmation_plain);
@ -315,6 +308,5 @@ mod tests {
node_id: handshake_result.0.peer_public().clone(), node_id: handshake_result.0.peer_public().clone(),
shared_key: shared_key, shared_key: shared_key,
})); }));
handshake_result.0.assert_output();
} }
} }

View File

@ -20,7 +20,10 @@ use std::ops::Deref;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use serde_json; use serde_json;
use ethcrypto::ecdh::agree; use ethcrypto::ecdh::agree;
use ethkey::{Public, Secret}; use ethcrypto::ecies::{encrypt_single_message, decrypt_single_message};
use ethkey::{Public, Secret, KeyPair};
use ethkey::math::curve_order;
use util::{H256, U256};
use key_server_cluster::Error; use key_server_cluster::Error;
use key_server_cluster::message::{Message, ClusterMessage, EncryptionMessage, DecryptionMessage}; use key_server_cluster::message::{Message, ClusterMessage, EncryptionMessage, DecryptionMessage};
@ -82,20 +85,11 @@ pub fn serialize_message(message: Message) -> Result<SerializedMessage, Error> {
}; };
let payload = payload.map_err(|err| Error::Serde(err.to_string()))?; let payload = payload.map_err(|err| Error::Serde(err.to_string()))?;
let payload_len = payload.len(); build_serialized_message(MessageHeader {
if payload_len > u16::MAX as usize {
return Err(Error::InvalidMessage);
}
let header = MessageHeader {
kind: message_kind, kind: message_kind,
version: 1, version: 1,
size: payload_len as u16, size: 0,
}; }, payload)
let mut serialized_message = serialize_header(&header)?;
serialized_message.extend(payload);
Ok(SerializedMessage(serialized_message))
} }
/// Deserialize message. /// Deserialize message.
@ -127,18 +121,30 @@ pub fn deserialize_message(header: &MessageHeader, payload: Vec<u8>) -> Result<M
} }
/// Encrypt serialized message. /// Encrypt serialized message.
pub fn encrypt_message(_key: &Secret, message: SerializedMessage) -> Result<SerializedMessage, Error> { pub fn encrypt_message(key: &KeyPair, message: SerializedMessage) -> Result<SerializedMessage, Error> {
Ok(message) // TODO: implement me let mut header: Vec<_> = message.into();
let payload = header.split_off(MESSAGE_HEADER_SIZE);
let encrypted_payload = encrypt_single_message(key.public(), &payload)?;
let header = deserialize_header(&header)?;
build_serialized_message(header, encrypted_payload)
} }
/// Decrypt serialized message. /// Decrypt serialized message.
pub fn decrypt_message(_key: &Secret, payload: Vec<u8>) -> Result<Vec<u8>, Error> { pub fn decrypt_message(key: &KeyPair, payload: Vec<u8>) -> Result<Vec<u8>, Error> {
Ok(payload) // TODO: implement me Ok(decrypt_single_message(key.secret(), &payload)?)
} }
/// Compute shared encryption key. /// Compute shared encryption key.
pub fn compute_shared_key(self_secret: &Secret, other_public: &Public) -> Result<Secret, Error> { pub fn compute_shared_key(self_secret: &Secret, other_public: &Public) -> Result<KeyPair, Error> {
Ok(agree(self_secret, other_public)?) // secret key created in agree function is invalid, as it is not calculated mod EC.field.n
// => let's do it manually
let shared_secret = agree(self_secret, other_public)?;
let shared_secret: H256 = (*shared_secret).into();
let shared_secret: U256 = shared_secret.into();
let shared_secret: H256 = (shared_secret % curve_order()).into();
let shared_key_pair = KeyPair::from_secret_slice(&*shared_secret)?;
Ok(shared_key_pair)
} }
/// Serialize message header. /// Serialize message header.
@ -160,29 +166,44 @@ pub fn deserialize_header(data: &[u8]) -> Result<MessageHeader, Error> {
}) })
} }
/// Build serialized message from header && payload
fn build_serialized_message(mut header: MessageHeader, payload: Vec<u8>) -> Result<SerializedMessage, Error> {
let payload_len = payload.len();
if payload_len > u16::MAX as usize {
return Err(Error::InvalidMessage);
}
header.size = payload.len() as u16;
let mut message = serialize_header(&header)?;
message.extend(payload);
Ok(SerializedMessage(message))
}
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use std::io; use std::io;
use futures::Poll;
use tokio_io::{AsyncRead, AsyncWrite};
use ethkey::{KeyPair, Public}; use ethkey::{KeyPair, Public};
use key_server_cluster::message::Message; use key_server_cluster::message::Message;
use super::{MESSAGE_HEADER_SIZE, MessageHeader, serialize_message, serialize_header, deserialize_header}; use super::{MESSAGE_HEADER_SIZE, MessageHeader, compute_shared_key, encrypt_message, serialize_message,
serialize_header, deserialize_header};
pub struct TestIo { pub struct TestIo {
self_key_pair: KeyPair, self_key_pair: KeyPair,
peer_public: Public, peer_public: Public,
shared_key_pair: KeyPair,
input_buffer: io::Cursor<Vec<u8>>, input_buffer: io::Cursor<Vec<u8>>,
output_buffer: Vec<u8>,
expected_output_buffer: Vec<u8>,
} }
impl TestIo { impl TestIo {
pub fn new(self_key_pair: KeyPair, peer_public: Public) -> Self { pub fn new(self_key_pair: KeyPair, peer_public: Public) -> Self {
let shared_key_pair = compute_shared_key(self_key_pair.secret(), &peer_public).unwrap();
TestIo { TestIo {
self_key_pair: self_key_pair, self_key_pair: self_key_pair,
peer_public: peer_public, peer_public: peer_public,
shared_key_pair: shared_key_pair,
input_buffer: io::Cursor::new(Vec::new()), input_buffer: io::Cursor::new(Vec::new()),
output_buffer: Vec::new(),
expected_output_buffer: Vec::new(),
} }
} }
@ -203,14 +224,21 @@ pub mod tests {
} }
} }
pub fn add_output_message(&mut self, message: Message) { pub fn add_encrypted_input_message(&mut self, message: Message) {
let serialized_message = serialize_message(message).unwrap(); let serialized_message = encrypt_message(&self.shared_key_pair, serialize_message(message).unwrap()).unwrap();
let serialized_message: Vec<_> = serialized_message.into(); let serialized_message: Vec<_> = serialized_message.into();
self.expected_output_buffer.extend(serialized_message); let input_buffer = self.input_buffer.get_mut();
for b in serialized_message {
input_buffer.push(b);
}
}
} }
pub fn assert_output(&self) { impl AsyncRead for TestIo {}
assert_eq!(self.output_buffer, self.expected_output_buffer);
impl AsyncWrite for TestIo {
fn shutdown(&mut self) -> Poll<(), io::Error> {
Ok(().into())
} }
} }
@ -222,11 +250,11 @@ pub mod tests {
impl io::Write for TestIo { impl io::Write for TestIo {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
io::Write::write(&mut self.output_buffer, buf) Ok(buf.len())
} }
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
io::Write::flush(&mut self.output_buffer) Ok(())
} }
} }

View File

@ -16,12 +16,13 @@
use std::io; use std::io;
use futures::{Future, Poll, Async}; use futures::{Future, Poll, Async};
use tokio_core::io::{ReadExact, read_exact}; use tokio_io::AsyncRead;
use tokio_io::io::{ReadExact, read_exact};
use key_server_cluster::Error; use key_server_cluster::Error;
use key_server_cluster::io::message::{MESSAGE_HEADER_SIZE, MessageHeader, deserialize_header}; use key_server_cluster::io::message::{MESSAGE_HEADER_SIZE, MessageHeader, deserialize_header};
/// Create future for read single message header from the stream. /// Create future for read single message header from the stream.
pub fn read_header<A>(a: A) -> ReadHeader<A> where A: io::Read { pub fn read_header<A>(a: A) -> ReadHeader<A> where A: AsyncRead {
ReadHeader { ReadHeader {
reader: read_exact(a, [0; MESSAGE_HEADER_SIZE]), reader: read_exact(a, [0; MESSAGE_HEADER_SIZE]),
} }
@ -32,7 +33,7 @@ pub struct ReadHeader<A> {
reader: ReadExact<A, [u8; MESSAGE_HEADER_SIZE]>, reader: ReadExact<A, [u8; MESSAGE_HEADER_SIZE]>,
} }
impl<A> Future for ReadHeader<A> where A: io::Read { impl<A> Future for ReadHeader<A> where A: AsyncRead {
type Item = (A, Result<MessageHeader, Error>); type Item = (A, Result<MessageHeader, Error>);
type Error = io::Error; type Error = io::Error;

View File

@ -16,13 +16,14 @@
use std::io; use std::io;
use futures::{Poll, Future, Async}; use futures::{Poll, Future, Async};
use ethkey::Secret; use tokio_io::AsyncRead;
use ethkey::KeyPair;
use key_server_cluster::Error; use key_server_cluster::Error;
use key_server_cluster::message::Message; use key_server_cluster::message::Message;
use key_server_cluster::io::{read_header, ReadHeader, read_payload, read_encrypted_payload, ReadPayload}; use key_server_cluster::io::{read_header, ReadHeader, read_payload, read_encrypted_payload, ReadPayload};
/// Create future for read single message from the stream. /// Create future for read single message from the stream.
pub fn read_message<A>(a: A) -> ReadMessage<A> where A: io::Read { pub fn read_message<A>(a: A) -> ReadMessage<A> where A: AsyncRead {
ReadMessage { ReadMessage {
key: None, key: None,
state: ReadMessageState::ReadHeader(read_header(a)), state: ReadMessageState::ReadHeader(read_header(a)),
@ -30,7 +31,7 @@ pub fn read_message<A>(a: A) -> ReadMessage<A> where A: io::Read {
} }
/// Create future for read single encrypted message from the stream. /// Create future for read single encrypted message from the stream.
pub fn read_encrypted_message<A>(a: A, key: Secret) -> ReadMessage<A> where A: io::Read { pub fn read_encrypted_message<A>(a: A, key: KeyPair) -> ReadMessage<A> where A: AsyncRead {
ReadMessage { ReadMessage {
key: Some(key), key: Some(key),
state: ReadMessageState::ReadHeader(read_header(a)), state: ReadMessageState::ReadHeader(read_header(a)),
@ -45,11 +46,11 @@ enum ReadMessageState<A> {
/// Future for read single message from the stream. /// Future for read single message from the stream.
pub struct ReadMessage<A> { pub struct ReadMessage<A> {
key: Option<Secret>, key: Option<KeyPair>,
state: ReadMessageState<A>, state: ReadMessageState<A>,
} }
impl<A> Future for ReadMessage<A> where A: io::Read { impl<A> Future for ReadMessage<A> where A: AsyncRead {
type Item = (A, Result<Message, Error>); type Item = (A, Result<Message, Error>);
type Error = io::Error; type Error = io::Error;

View File

@ -16,14 +16,15 @@
use std::io; use std::io;
use futures::{Poll, Future}; use futures::{Poll, Future};
use tokio_core::io::{read_exact, ReadExact}; use tokio_io::AsyncRead;
use ethkey::Secret; use tokio_io::io::{read_exact, ReadExact};
use ethkey::KeyPair;
use key_server_cluster::Error; use key_server_cluster::Error;
use key_server_cluster::message::Message; use key_server_cluster::message::Message;
use key_server_cluster::io::message::{MessageHeader, deserialize_message, decrypt_message}; use key_server_cluster::io::message::{MessageHeader, deserialize_message, decrypt_message};
/// Create future for read single message payload from the stream. /// Create future for read single message payload from the stream.
pub fn read_payload<A>(a: A, header: MessageHeader) -> ReadPayload<A> where A: io::Read { pub fn read_payload<A>(a: A, header: MessageHeader) -> ReadPayload<A> where A: AsyncRead {
ReadPayload { ReadPayload {
reader: read_exact(a, vec![0; header.size as usize]), reader: read_exact(a, vec![0; header.size as usize]),
header: header, header: header,
@ -32,7 +33,7 @@ pub fn read_payload<A>(a: A, header: MessageHeader) -> ReadPayload<A> where A: i
} }
/// Create future for read single encrypted message payload from the stream. /// Create future for read single encrypted message payload from the stream.
pub fn read_encrypted_payload<A>(a: A, header: MessageHeader, key: Secret) -> ReadPayload<A> where A: io::Read { pub fn read_encrypted_payload<A>(a: A, header: MessageHeader, key: KeyPair) -> ReadPayload<A> where A: AsyncRead {
ReadPayload { ReadPayload {
reader: read_exact(a, vec![0; header.size as usize]), reader: read_exact(a, vec![0; header.size as usize]),
header: header, header: header,
@ -44,10 +45,10 @@ pub fn read_encrypted_payload<A>(a: A, header: MessageHeader, key: Secret) -> Re
pub struct ReadPayload<A> { pub struct ReadPayload<A> {
reader: ReadExact<A, Vec<u8>>, reader: ReadExact<A, Vec<u8>>,
header: MessageHeader, header: MessageHeader,
key: Option<Secret>, key: Option<KeyPair>,
} }
impl<A> Future for ReadPayload<A> where A: io::Read { impl<A> Future for ReadPayload<A> where A: AsyncRead {
type Item = (A, Result<Message, Error>); type Item = (A, Result<Message, Error>);
type Error = io::Error; type Error = io::Error;

View File

@ -15,7 +15,10 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc; use std::sync::Arc;
use std::net::Shutdown;
use std::io::{Read, Write, Error}; use std::io::{Read, Write, Error};
use futures::Poll;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_core::net::TcpStream; use tokio_core::net::TcpStream;
/// Read+Write implementation for Arc<TcpStream>. /// Read+Write implementation for Arc<TcpStream>.
@ -37,6 +40,14 @@ impl From<TcpStream> for SharedTcpStream {
} }
} }
impl AsyncRead for SharedTcpStream {}
impl AsyncWrite for SharedTcpStream {
fn shutdown(&mut self) -> Poll<(), Error> {
self.io.shutdown(Shutdown::Both).map(Into::into)
}
}
impl Read for SharedTcpStream { impl Read for SharedTcpStream {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
Read::read(&mut (&*self.io as &TcpStream), buf) Read::read(&mut (&*self.io as &TcpStream), buf)

View File

@ -16,13 +16,14 @@
use std::io; use std::io;
use futures::{Future, Poll}; use futures::{Future, Poll};
use tokio_core::io::{WriteAll, write_all}; use tokio_io::AsyncWrite;
use ethkey::Secret; use tokio_io::io::{WriteAll, write_all};
use ethkey::KeyPair;
use key_server_cluster::message::Message; use key_server_cluster::message::Message;
use key_server_cluster::io::{serialize_message, encrypt_message}; use key_server_cluster::io::{serialize_message, encrypt_message};
/// Write plain message to the channel. /// Write plain message to the channel.
pub fn write_message<A>(a: A, message: Message) -> WriteMessage<A> where A: io::Write { pub fn write_message<A>(a: A, message: Message) -> WriteMessage<A> where A: AsyncWrite {
let (error, future) = match serialize_message(message) let (error, future) = match serialize_message(message)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) { .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) {
Ok(message) => (None, write_all(a, message.into())), Ok(message) => (None, write_all(a, message.into())),
@ -35,7 +36,7 @@ pub fn write_message<A>(a: A, message: Message) -> WriteMessage<A> where A: io::
} }
/// Write encrypted message to the channel. /// Write encrypted message to the channel.
pub fn write_encrypted_message<A>(a: A, key: &Secret, message: Message) -> WriteMessage<A> where A: io::Write { pub fn write_encrypted_message<A>(a: A, key: &KeyPair, message: Message) -> WriteMessage<A> where A: AsyncWrite {
let (error, future) = match serialize_message(message) let (error, future) = match serialize_message(message)
.and_then(|message| encrypt_message(key, message)) .and_then(|message| encrypt_message(key, message))
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) { .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) {
@ -56,7 +57,7 @@ pub struct WriteMessage<A> {
future: WriteAll<A, Vec<u8>>, future: WriteAll<A, Vec<u8>>,
} }
impl<A> Future for WriteMessage<A> where A: io::Write { impl<A> Future for WriteMessage<A> where A: AsyncWrite {
type Item = (A, Vec<u8>); type Item = (A, Vec<u8>);
type Error = io::Error; type Error = io::Error;

View File

@ -203,12 +203,24 @@ pub fn compute_node_shadow<'a, I>(node_number: &Secret, node_secret_share: &Secr
} }
/// Compute shadow point for the node. /// Compute shadow point for the node.
pub fn compute_node_shadow_point(access_key: &Secret, common_point: &Public, node_shadow: &Secret) -> Result<Public, Error> { pub fn compute_node_shadow_point(access_key: &Secret, common_point: &Public, node_shadow: &Secret, decrypt_shadow: Option<Secret>) -> Result<(Public, Option<Secret>), Error> {
let mut shadow_key = access_key.clone(); let mut shadow_key = node_shadow.clone();
shadow_key.mul(node_shadow)?; let decrypt_shadow = match decrypt_shadow {
None => None,
Some(mut decrypt_shadow) => {
// update shadow key
shadow_key.mul(&decrypt_shadow)?;
// now udate decrypt shadow itself
decrypt_shadow.dec()?;
decrypt_shadow.mul(node_shadow)?;
Some(decrypt_shadow)
}
};
shadow_key.mul(access_key)?;
let mut node_shadow_point = common_point.clone(); let mut node_shadow_point = common_point.clone();
math::public_mul_secret(&mut node_shadow_point, &shadow_key)?; math::public_mul_secret(&mut node_shadow_point, &shadow_key)?;
Ok(node_shadow_point) Ok((node_shadow_point, decrypt_shadow))
} }
/// Compute joint shadow point. /// Compute joint shadow point.
@ -252,6 +264,28 @@ pub fn decrypt_with_joint_shadow(threshold: usize, access_key: &Secret, encrypte
Ok(decrypted_point) Ok(decrypted_point)
} }
/// Prepare common point for shadow decryption.
pub fn make_common_shadow_point(threshold: usize, mut common_point: Public) -> Result<Public, Error> {
if threshold % 2 != 1 {
Ok(common_point)
} else {
math::public_negate(&mut common_point)?;
Ok(common_point)
}
}
#[cfg(test)]
/// Decrypt shadow-encrypted secret.
pub fn decrypt_with_shadow_coefficients(mut decrypted_shadow: Public, mut common_shadow_point: Public, shadow_coefficients: Vec<Secret>) -> Result<Public, Error> {
let mut shadow_coefficients_sum = shadow_coefficients[0].clone();
for shadow_coefficient in shadow_coefficients.iter().skip(1) {
shadow_coefficients_sum.add(shadow_coefficient)?;
}
math::public_mul_secret(&mut common_shadow_point, &shadow_coefficients_sum)?;
math::public_add(&mut decrypted_shadow, &common_shadow_point)?;
Ok(decrypted_shadow)
}
#[cfg(test)] #[cfg(test)]
/// Decrypt data using joint secret (version for tests). /// Decrypt data using joint secret (version for tests).
pub fn decrypt_with_joint_secret(encrypted_point: &Public, common_point: &Public, joint_secret: &Secret) -> Result<Public, Error> { pub fn decrypt_with_joint_secret(encrypted_point: &Public, common_point: &Public, joint_secret: &Secret) -> Result<Public, Error> {
@ -287,7 +321,10 @@ pub mod tests {
.filter(|&(j, _)| j != i) .filter(|&(j, _)| j != i)
.take(t) .take(t)
.map(|(_, id_number)| id_number)).unwrap()).collect(); .map(|(_, id_number)| id_number)).unwrap()).collect();
let nodes_shadow_points: Vec<_> = nodes_shadows.iter().map(|s| compute_node_shadow_point(&access_key, &encrypted_secret.common_point, s).unwrap()).collect(); let nodes_shadow_points: Vec<_> = nodes_shadows.iter()
.map(|s| compute_node_shadow_point(&access_key, &encrypted_secret.common_point, s, None).unwrap())
.map(|sp| sp.0)
.collect();
assert_eq!(nodes_shadows.len(), t + 1); assert_eq!(nodes_shadows.len(), t + 1);
assert_eq!(nodes_shadow_points.len(), t + 1); assert_eq!(nodes_shadow_points.len(), t + 1);

View File

@ -218,6 +218,9 @@ pub struct InitializeDecryptionSession {
pub sub_session: SerializableSecret, pub sub_session: SerializableSecret,
/// Requestor signature. /// Requestor signature.
pub requestor_signature: SerializableSignature, pub requestor_signature: SerializableSignature,
/// Is shadow decryption requested? When true, decryption result
/// will be visible to the owner of requestor public key only.
pub is_shadow_decryption: bool,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -251,6 +254,8 @@ pub struct PartialDecryption {
pub sub_session: SerializableSecret, pub sub_session: SerializableSecret,
/// Partially decrypted secret. /// Partially decrypted secret.
pub shadow_point: SerializablePublic, pub shadow_point: SerializablePublic,
/// Decrypt shadow coefficient (if requested), encrypted with requestor public.
pub decrypt_shadow: Option<Vec<u8>>,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]

View File

@ -20,7 +20,7 @@ use ethkey;
use ethcrypto; use ethcrypto;
use super::types::all::DocumentAddress; use super::types::all::DocumentAddress;
pub use super::types::all::{NodeId, EncryptionConfiguration}; pub use super::types::all::{NodeId, EncryptionConfiguration, DocumentEncryptedKeyShadow};
pub use super::acl_storage::AclStorage; pub use super::acl_storage::AclStorage;
pub use super::key_storage::{KeyStorage, DocumentKeyShare}; pub use super::key_storage::{KeyStorage, DocumentKeyShare};
pub use super::serialization::{SerializableSignature, SerializableH256, SerializableSecret, SerializablePublic}; pub use super::serialization::{SerializableSignature, SerializableH256, SerializableSecret, SerializablePublic};

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::net; use std::net;
use ethkey::Secret; use ethkey::KeyPair;
use key_server_cluster::NodeId; use key_server_cluster::NodeId;
use key_server_cluster::io::SharedTcpStream; use key_server_cluster::io::SharedTcpStream;
@ -28,5 +28,5 @@ pub struct Connection {
/// Peer node id. /// Peer node id.
pub node_id: NodeId, pub node_id: NodeId,
/// Encryption key. /// Encryption key.
pub key: Secret, pub key: KeyPair,
} }

View File

@ -43,6 +43,8 @@ pub trait KeyStorage: Send + Sync {
fn insert(&self, document: DocumentAddress, key: DocumentKeyShare) -> Result<(), Error>; fn insert(&self, document: DocumentAddress, key: DocumentKeyShare) -> Result<(), Error>;
/// Get document encryption key /// Get document encryption key
fn get(&self, document: &DocumentAddress) -> Result<DocumentKeyShare, Error>; fn get(&self, document: &DocumentAddress) -> Result<DocumentKeyShare, Error>;
/// Check if storage contains document encryption key
fn contains(&self, document: &DocumentAddress) -> bool;
} }
/// Persistent document encryption keys storage /// Persistent document encryption keys storage
@ -95,6 +97,12 @@ impl KeyStorage for PersistentKeyStorage {
.and_then(|key| serde_json::from_slice::<SerializableDocumentKeyShare>(&key).map_err(|e| Error::Database(e.to_string()))) .and_then(|key| serde_json::from_slice::<SerializableDocumentKeyShare>(&key).map_err(|e| Error::Database(e.to_string())))
.map(Into::into) .map(Into::into)
} }
fn contains(&self, document: &DocumentAddress) -> bool {
self.db.get(None, document)
.map(|k| k.is_some())
.unwrap_or(false)
}
} }
impl From<DocumentKeyShare> for SerializableDocumentKeyShare { impl From<DocumentKeyShare> for SerializableDocumentKeyShare {
@ -146,6 +154,10 @@ pub mod tests {
fn get(&self, document: &DocumentAddress) -> Result<DocumentKeyShare, Error> { fn get(&self, document: &DocumentAddress) -> Result<DocumentKeyShare, Error> {
self.keys.read().get(document).cloned().ok_or(Error::DocumentNotFound) self.keys.read().get(document).cloned().ok_or(Error::DocumentNotFound)
} }
fn contains(&self, document: &DocumentAddress) -> bool {
self.keys.read().contains_key(document)
}
} }
#[test] #[test]

View File

@ -27,6 +27,7 @@ extern crate serde;
extern crate serde_json; extern crate serde_json;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate tokio_io;
extern crate tokio_core; extern crate tokio_core;
extern crate tokio_service; extern crate tokio_service;
extern crate tokio_proto; extern crate tokio_proto;

View File

@ -17,11 +17,62 @@
use std::fmt; use std::fmt;
use std::cmp::{Ord, PartialOrd, Ordering}; use std::cmp::{Ord, PartialOrd, Ordering};
use std::ops::Deref; use std::ops::Deref;
use rustc_serialize::hex::ToHex; use rustc_serialize::hex::{ToHex, FromHex};
use serde::{Serialize, Deserialize, Serializer, Deserializer}; use serde::{Serialize, Deserialize, Serializer, Deserializer};
use serde::de::{Visitor, Error as SerdeError}; use serde::de::{Visitor, Error as SerdeError};
use ethkey::{Public, Secret, Signature}; use ethkey::{Public, Secret, Signature};
use util::H256; use util::{H256, Bytes};
#[derive(Clone, Debug, Serialize, Deserialize)]
/// Serializable shadow decryption result.
pub struct SerializableDocumentEncryptedKeyShadow {
/// Decrypted secret point. It is partially decrypted if shadow decrpytion was requested.
pub decrypted_secret: SerializablePublic,
/// Shared common point.
pub common_point: SerializablePublic,
/// If shadow decryption was requested: shadow decryption coefficients, encrypted with requestor public.
pub decrypt_shadows: Vec<SerializableBytes>,
}
#[derive(Clone, Debug)]
/// Serializable Bytes.
pub struct SerializableBytes(Bytes);
impl<T> From<T> for SerializableBytes where Bytes: From<T> {
fn from(s: T) -> SerializableBytes {
SerializableBytes(s.into())
}
}
impl Into<Bytes> for SerializableBytes {
fn into(self) -> Bytes {
self.0
}
}
impl Deref for SerializableBytes {
type Target = Bytes;
fn deref(&self) -> &Bytes {
&self.0
}
}
impl Serialize for SerializableBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
serializer.serialize_str(&(*self.0).to_hex())
}
}
impl Deserialize for SerializableBytes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer
{
let s = String::deserialize(deserializer)?;
let data = s.from_hex().map_err(SerdeError::custom)?;
Ok(SerializableBytes(data))
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Serializable Signature. /// Serializable Signature.

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use types::all::{Error, RequestSignature, DocumentAddress, DocumentEncryptedKey}; use types::all::{Error, RequestSignature, DocumentAddress, DocumentEncryptedKey, DocumentEncryptedKeyShadow};
#[ipc(client_ident="RemoteKeyServer")] #[ipc(client_ident="RemoteKeyServer")]
/// Secret store key server /// Secret store key server
@ -23,4 +23,12 @@ pub trait KeyServer: Send + Sync {
fn generate_document_key(&self, signature: &RequestSignature, document: &DocumentAddress, threshold: usize) -> Result<DocumentEncryptedKey, Error>; fn generate_document_key(&self, signature: &RequestSignature, document: &DocumentAddress, threshold: usize) -> Result<DocumentEncryptedKey, Error>;
/// Request encryption key of given document for given requestor /// Request encryption key of given document for given requestor
fn document_key(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKey, Error>; fn document_key(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKey, Error>;
/// Request encryption key of given document for given requestor.
/// This method does not reveal document_key to any KeyServer, but it requires additional actions on client.
/// To calculate decrypted key on client:
/// 1) use requestor secret key to decrypt secret coefficients from result.decrypt_shadows
/// 2) calculate decrypt_shadows_sum = sum of all secrets from (1)
/// 3) calculate decrypt_shadow_point: decrypt_shadows_sum * result.common_point
/// 4) calculate decrypted_secret: result.decrypted_secret + decrypt_shadow_point
fn document_key_shadow(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKeyShadow, Error>;
} }

View File

@ -50,7 +50,7 @@ pub enum Error {
Internal(String), Internal(String),
} }
#[derive(Debug)] #[derive(Debug, Clone)]
#[binary] #[binary]
/// Secret store configuration /// Secret store configuration
pub struct NodeAddress { pub struct NodeAddress {
@ -99,6 +99,18 @@ pub struct EncryptionConfiguration {
pub key_check_timeout_ms: u64, pub key_check_timeout_ms: u64,
} }
#[derive(Clone, Debug, PartialEq)]
#[binary]
/// Shadow decryption result.
pub struct DocumentEncryptedKeyShadow {
/// Decrypted secret point. It is partially decrypted if shadow decrpytion was requested.
pub decrypted_secret: ethkey::Public,
/// Shared common point.
pub common_point: Option<ethkey::Public>,
/// If shadow decryption was requested: shadow decryption coefficients, encrypted with requestor public.
pub decrypt_shadows: Option<Vec<Vec<u8>>>,
}
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self { match *self {