On-chain ACL checker for secretstore (#5015)
* 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 * fix after merge * fix after merge * moved contract to native-contracts lib
This commit is contained in:
		
							parent
							
								
									ee4f9da385
								
							
						
					
					
						commit
						abec06f50c
					
				
							
								
								
									
										3
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -635,6 +635,8 @@ name = "ethcore-secretstore"
 | 
				
			|||||||
version = "1.0.0"
 | 
					version = "1.0.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
					 "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 | 
					 "ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 | 
					 "ethcore 1.7.0",
 | 
				
			||||||
 "ethcore-devtools 1.7.0",
 | 
					 "ethcore-devtools 1.7.0",
 | 
				
			||||||
 "ethcore-ipc 1.7.0",
 | 
					 "ethcore-ipc 1.7.0",
 | 
				
			||||||
 "ethcore-ipc-codegen 1.7.0",
 | 
					 "ethcore-ipc-codegen 1.7.0",
 | 
				
			||||||
@ -646,6 +648,7 @@ dependencies = [
 | 
				
			|||||||
 "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.6 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 | 
					 "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)",
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@ use std::io::Write;
 | 
				
			|||||||
// TODO: `include!` these from files where they're pretty-printed?
 | 
					// TODO: `include!` these from files where they're pretty-printed?
 | 
				
			||||||
const REGISTRY_ABI: &'static str = r#"[{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"canReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"setData","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getData","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"hasReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getReverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"confirmReverseAs","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}]"#;
 | 
					const REGISTRY_ABI: &'static str = r#"[{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"canReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"setData","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getData","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"hasReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getReverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"confirmReverseAs","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}]"#;
 | 
				
			||||||
const SERVICE_TRANSACTION_ABI: &'static str = r#"[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"certify","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"revoke","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"delegate","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setDelegate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"}]"#;
 | 
					const SERVICE_TRANSACTION_ABI: &'static str = r#"[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"certify","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"revoke","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"delegate","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setDelegate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"}]"#;
 | 
				
			||||||
 | 
					const SECRETSTORE_ACL_STORAGE_ABI: &'static str = r#"[{"constant":true,"inputs":[{"name":"user","type":"address"},{"name":"document","type":"bytes32"}],"name":"checkPermissions","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"}]"#;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn build_file(name: &str, abi: &str, filename: &str) {
 | 
					fn build_file(name: &str, abi: &str, filename: &str) {
 | 
				
			||||||
	let code = ::native_contract_generator::generate_module(name, abi).unwrap();
 | 
						let code = ::native_contract_generator::generate_module(name, abi).unwrap();
 | 
				
			||||||
@ -37,4 +38,5 @@ fn build_file(name: &str, abi: &str, filename: &str) {
 | 
				
			|||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
	build_file("Registry", REGISTRY_ABI, "registry.rs");
 | 
						build_file("Registry", REGISTRY_ABI, "registry.rs");
 | 
				
			||||||
	build_file("ServiceTransactionChecker", SERVICE_TRANSACTION_ABI, "service_transaction.rs");
 | 
						build_file("ServiceTransactionChecker", SERVICE_TRANSACTION_ABI, "service_transaction.rs");
 | 
				
			||||||
 | 
						build_file("SecretStoreAclStorage", SECRETSTORE_ACL_STORAGE_ABI, "secretstore_acl_storage.rs");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,8 @@ extern crate ethcore_util as util;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
mod registry;
 | 
					mod registry;
 | 
				
			||||||
mod service_transaction;
 | 
					mod service_transaction;
 | 
				
			||||||
 | 
					mod secretstore_acl_storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use self::registry::Registry;
 | 
					pub use self::registry::Registry;
 | 
				
			||||||
pub use self::service_transaction::ServiceTransactionChecker;
 | 
					pub use self::service_transaction::ServiceTransactionChecker;
 | 
				
			||||||
 | 
					pub use self::secretstore_acl_storage::SecretStoreAclStorage;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										22
									
								
								ethcore/native_contracts/src/secretstore_acl_storage.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								ethcore/native_contracts/src/secretstore_acl_storage.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					// Copyright 2015-2017 Parity Technologies (UK) Ltd.
 | 
				
			||||||
 | 
					// This file is part of Parity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Parity is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Parity is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#![allow(unused_mut, unused_variables, unused_imports)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Secret store ACL storage contract.
 | 
				
			||||||
 | 
					// TODO: testing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include!(concat!(env!("OUT_DIR"), "/secretstore_acl_storage.rs"));
 | 
				
			||||||
@ -463,7 +463,9 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
 | 
				
			|||||||
	let signer_server = signer::start(cmd.signer_conf.clone(), signer_deps)?;
 | 
						let signer_server = signer::start(cmd.signer_conf.clone(), signer_deps)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// secret store key server
 | 
						// secret store key server
 | 
				
			||||||
	let secretstore_deps = secretstore::Dependencies { };
 | 
						let secretstore_deps = secretstore::Dependencies {
 | 
				
			||||||
 | 
							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
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,9 @@
 | 
				
			|||||||
// 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::sync::Arc;
 | 
				
			||||||
use dir::default_data_path;
 | 
					use dir::default_data_path;
 | 
				
			||||||
 | 
					use ethcore::client::Client;
 | 
				
			||||||
use helpers::replace_home;
 | 
					use helpers::replace_home;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, PartialEq, Clone)]
 | 
					#[derive(Debug, PartialEq, Clone)]
 | 
				
			||||||
@ -30,10 +32,10 @@ pub struct Configuration {
 | 
				
			|||||||
	pub data_path: String,
 | 
						pub data_path: String,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, PartialEq, Clone)]
 | 
					 | 
				
			||||||
/// Secret store dependencies
 | 
					/// Secret store dependencies
 | 
				
			||||||
pub struct Dependencies {
 | 
					pub struct Dependencies {
 | 
				
			||||||
	// the only dependency will be BlockChainClient
 | 
						/// Blockchain client.
 | 
				
			||||||
 | 
						pub client: Arc<Client>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(not(feature = "secretstore"))]
 | 
					#[cfg(not(feature = "secretstore"))]
 | 
				
			||||||
@ -64,7 +66,7 @@ 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 key_pairs = vec![
 | 
				
			||||||
				ethkey::KeyPair::from_secret("6c26a76e9b31048d170873a791401c7e799a11f0cefc0171cc31a49800967509".parse().unwrap()).unwrap(),
 | 
									ethkey::KeyPair::from_secret("6c26a76e9b31048d170873a791401c7e799a11f0cefc0171cc31a49800967509".parse().unwrap()).unwrap(),
 | 
				
			||||||
				ethkey::KeyPair::from_secret("7e94018b3731afdb3b4e6f4c3e179475640166da12e1d1b0c7d80729b1a5b452".parse().unwrap()).unwrap(),
 | 
									ethkey::KeyPair::from_secret("7e94018b3731afdb3b4e6f4c3e179475640166da12e1d1b0c7d80729b1a5b452".parse().unwrap()).unwrap(),
 | 
				
			||||||
@ -96,7 +98,7 @@ mod server {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			let key_server = ethcore_secretstore::start(conf)
 | 
								let key_server = ethcore_secretstore::start(deps.client, conf)
 | 
				
			||||||
				.map_err(Into::<String>::into)?;
 | 
									.map_err(Into::<String>::into)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Ok(KeyServer {
 | 
								Ok(KeyServer {
 | 
				
			||||||
 | 
				
			|||||||
@ -24,12 +24,15 @@ tokio-core = "0.1"
 | 
				
			|||||||
tokio-service = "0.1"
 | 
					tokio-service = "0.1"
 | 
				
			||||||
tokio-proto = "0.1"
 | 
					tokio-proto = "0.1"
 | 
				
			||||||
url = "1.0"
 | 
					url = "1.0"
 | 
				
			||||||
 | 
					ethabi = "1.0.0"
 | 
				
			||||||
 | 
					ethcore = { path = "../ethcore" }
 | 
				
			||||||
ethcore-devtools = { path = "../devtools" }
 | 
					ethcore-devtools = { path = "../devtools" }
 | 
				
			||||||
ethcore-util = { path = "../util" }
 | 
					ethcore-util = { path = "../util" }
 | 
				
			||||||
ethcore-ipc = { path = "../ipc/rpc" }
 | 
					ethcore-ipc = { path = "../ipc/rpc" }
 | 
				
			||||||
ethcore-ipc-nano = { path = "../ipc/nano" }
 | 
					ethcore-ipc-nano = { path = "../ipc/nano" }
 | 
				
			||||||
ethcrypto = { path = "../ethcrypto" }
 | 
					ethcrypto = { path = "../ethcrypto" }
 | 
				
			||||||
ethkey = { path = "../ethkey" }
 | 
					ethkey = { path = "../ethkey" }
 | 
				
			||||||
 | 
					native-contracts = { path = "../ethcore/native_contracts" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[profile.release]
 | 
					[profile.release]
 | 
				
			||||||
debug = true
 | 
					debug = true
 | 
				
			||||||
 | 
				
			|||||||
@ -14,23 +14,76 @@
 | 
				
			|||||||
// 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::{HashMap, HashSet};
 | 
					use std::sync::Arc;
 | 
				
			||||||
use parking_lot::RwLock;
 | 
					use futures::{future, Future};
 | 
				
			||||||
 | 
					use parking_lot::Mutex;
 | 
				
			||||||
 | 
					use ethkey::public_to_address;
 | 
				
			||||||
 | 
					use ethcore::client::{Client, BlockChainClient, BlockId};
 | 
				
			||||||
 | 
					use native_contracts::SecretStoreAclStorage;
 | 
				
			||||||
use types::all::{Error, DocumentAddress, Public};
 | 
					use types::all::{Error, DocumentAddress, Public};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// ACL storage of Secret Store
 | 
					/// ACL storage of Secret Store
 | 
				
			||||||
pub trait AclStorage: Send + Sync {
 | 
					pub trait AclStorage: Send + Sync {
 | 
				
			||||||
	/// Check if requestor with `public` key can access document with hash `document`
 | 
						/// Check if requestor with `public` key can access document with hash `document`
 | 
				
			||||||
	fn check(&self, public: &Public, document: &DocumentAddress) -> Result<bool, Error>;
 | 
						fn check(&self, public: &Public, document: &DocumentAddress) -> Result<bool, Error>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Dummy ACL storage implementation
 | 
					/// On-chain ACL storage implementation.
 | 
				
			||||||
#[derive(Default, Debug)]
 | 
					pub struct OnChainAclStorage {
 | 
				
			||||||
pub struct DummyAclStorage {
 | 
						/// Blockchain client.
 | 
				
			||||||
	prohibited: RwLock<HashMap<Public, HashSet<DocumentAddress>>>,
 | 
						client: Arc<Client>,
 | 
				
			||||||
 | 
						/// On-chain contract.
 | 
				
			||||||
 | 
						contract: Mutex<Option<SecretStoreAclStorage>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl DummyAclStorage {
 | 
					impl OnChainAclStorage {
 | 
				
			||||||
 | 
						pub fn new(client: Arc<Client>) -> Self {
 | 
				
			||||||
 | 
							OnChainAclStorage {
 | 
				
			||||||
 | 
								client: client,
 | 
				
			||||||
 | 
								contract: Mutex::new(None),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl AclStorage for OnChainAclStorage {
 | 
				
			||||||
 | 
						fn check(&self, public: &Public, document: &DocumentAddress) -> Result<bool, Error> {
 | 
				
			||||||
 | 
							let mut contract = self.contract.lock();
 | 
				
			||||||
 | 
							if !contract.is_some() {
 | 
				
			||||||
 | 
								*contract = self.client.registry_address(ACL_CHECKER_CONTRACT_REGISTRY_NAME.to_owned())
 | 
				
			||||||
 | 
									.and_then(|contract_addr| {
 | 
				
			||||||
 | 
										trace!(target: "secretstore", "Configuring for ACL checker contract from {}", contract_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										Some(SecretStoreAclStorage::new(contract_addr))
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if let Some(ref contract) = *contract {
 | 
				
			||||||
 | 
								let address = public_to_address(&public);
 | 
				
			||||||
 | 
								let do_call = |a, d| future::done(self.client.call_contract(BlockId::Latest, a, d));
 | 
				
			||||||
 | 
								contract.check_permissions(do_call, address, document.clone())
 | 
				
			||||||
 | 
									.map_err(|err| Error::Internal(err))
 | 
				
			||||||
 | 
									.wait()
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								Err(Error::Internal("ACL checker contract is not configured".to_owned()))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					pub mod tests {
 | 
				
			||||||
 | 
						use std::collections::{HashMap, HashSet};
 | 
				
			||||||
 | 
						use parking_lot::RwLock;
 | 
				
			||||||
 | 
						use types::all::{Error, DocumentAddress, Public};
 | 
				
			||||||
 | 
						use super::AclStorage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#[derive(Default, Debug)]
 | 
				
			||||||
 | 
						/// Dummy ACL storage implementation
 | 
				
			||||||
 | 
						pub struct DummyAclStorage {
 | 
				
			||||||
 | 
							prohibited: RwLock<HashMap<Public, HashSet<DocumentAddress>>>,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						impl DummyAclStorage {
 | 
				
			||||||
		#[cfg(test)]
 | 
							#[cfg(test)]
 | 
				
			||||||
		/// Prohibit given requestor access to given document
 | 
							/// Prohibit given requestor access to given document
 | 
				
			||||||
		pub fn prohibit(&self, public: Public, document: DocumentAddress) {
 | 
							pub fn prohibit(&self, public: Public, document: DocumentAddress) {
 | 
				
			||||||
@ -39,13 +92,14 @@ impl DummyAclStorage {
 | 
				
			|||||||
				.or_insert_with(Default::default)
 | 
									.or_insert_with(Default::default)
 | 
				
			||||||
				.insert(document);
 | 
									.insert(document);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl AclStorage for DummyAclStorage {
 | 
						impl AclStorage for DummyAclStorage {
 | 
				
			||||||
		fn check(&self, public: &Public, document: &DocumentAddress) -> Result<bool, Error> {
 | 
							fn check(&self, public: &Public, document: &DocumentAddress) -> Result<bool, Error> {
 | 
				
			||||||
			Ok(self.prohibited.read()
 | 
								Ok(self.prohibited.read()
 | 
				
			||||||
				.get(public)
 | 
									.get(public)
 | 
				
			||||||
				.map(|docs| !docs.contains(document))
 | 
									.map(|docs| !docs.contains(document))
 | 
				
			||||||
				.unwrap_or(true))
 | 
									.unwrap_or(true))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -147,7 +147,7 @@ mod tests {
 | 
				
			|||||||
	use std::sync::Arc;
 | 
						use std::sync::Arc;
 | 
				
			||||||
	use ethcrypto;
 | 
						use ethcrypto;
 | 
				
			||||||
	use ethkey::{self, Random, Generator};
 | 
						use ethkey::{self, Random, Generator};
 | 
				
			||||||
	use acl_storage::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, DocumentEncryptedKey, DocumentKey};
 | 
				
			||||||
	use super::super::{RequestSignature, DocumentAddress};
 | 
						use super::super::{RequestSignature, DocumentAddress};
 | 
				
			||||||
 | 
				
			|||||||
@ -220,7 +220,7 @@ impl SessionImpl {
 | 
				
			|||||||
				self.completed.notify_all();
 | 
									self.completed.notify_all();
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			// we can not decrypt data
 | 
								// we can not decrypt data
 | 
				
			||||||
			SessionState::Failed => (),
 | 
								SessionState::Failed => self.completed.notify_all(),
 | 
				
			||||||
			// cannot reach other states
 | 
								// cannot reach other states
 | 
				
			||||||
			_ => unreachable!("process_initialization_response can change state to WaitingForPartialDecryption or Failed; checked that we are in WaitingForInitializationConfirm state above; qed"),
 | 
								_ => unreachable!("process_initialization_response can change state to WaitingForPartialDecryption or Failed; checked that we are in WaitingForInitializationConfirm state above; qed"),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -285,7 +285,10 @@ impl SessionImpl {
 | 
				
			|||||||
			SessionState::WaitingForPartialDecryption =>
 | 
								SessionState::WaitingForPartialDecryption =>
 | 
				
			||||||
				SessionImpl::start_waiting_for_partial_decryption(self.node().clone(), self.id.clone(), self.access_key.clone(), &self.cluster, &self.encrypted_data, &mut *data),
 | 
									SessionImpl::start_waiting_for_partial_decryption(self.node().clone(), self.id.clone(), self.access_key.clone(), &self.cluster, &self.encrypted_data, &mut *data),
 | 
				
			||||||
			// we can not have enough nodes for decryption
 | 
								// we can not have enough nodes for decryption
 | 
				
			||||||
			SessionState::Failed => Ok(()),
 | 
								SessionState::Failed => {
 | 
				
			||||||
 | 
									self.completed.notify_all();
 | 
				
			||||||
 | 
									Ok(())
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
			// cannot reach other states
 | 
								// cannot reach other states
 | 
				
			||||||
			_ => unreachable!("process_initialization_response can change state to WaitingForPartialDecryption or Failed; checked that we are in WaitingForInitializationConfirm state above; qed"),
 | 
								_ => unreachable!("process_initialization_response can change state to WaitingForPartialDecryption or Failed; checked that we are in WaitingForInitializationConfirm state above; qed"),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -480,6 +483,7 @@ fn process_initialization_response(encrypted_data: &DocumentKeyShare, data: &mut
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			// check if we still can receive enough confirmations to do a decryption?
 | 
								// check if we still can receive enough confirmations to do a decryption?
 | 
				
			||||||
			if encrypted_data.id_numbers.len() - data.rejected_nodes.len() < encrypted_data.threshold + 1 {
 | 
								if encrypted_data.id_numbers.len() - data.rejected_nodes.len() < encrypted_data.threshold + 1 {
 | 
				
			||||||
 | 
									data.decrypted_secret = Some(Err(Error::AccessDenied));
 | 
				
			||||||
				data.state = SessionState::Failed;
 | 
									data.state = SessionState::Failed;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@ -503,7 +507,7 @@ fn do_partial_decryption(node: &NodeId, _requestor_public: &Public, participants
 | 
				
			|||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
	use std::sync::Arc;
 | 
						use std::sync::Arc;
 | 
				
			||||||
	use std::collections::BTreeMap;
 | 
						use std::collections::BTreeMap;
 | 
				
			||||||
	use super::super::super::acl_storage::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};
 | 
				
			||||||
	use key_server_cluster::cluster::tests::DummyCluster;
 | 
						use key_server_cluster::cluster::tests::DummyCluster;
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ 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};
 | 
				
			||||||
pub use super::acl_storage::{AclStorage, DummyAclStorage};
 | 
					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};
 | 
				
			||||||
pub use self::cluster::{ClusterCore, ClusterConfiguration, ClusterClient};
 | 
					pub use self::cluster::{ClusterCore, ClusterConfiguration, ClusterClient};
 | 
				
			||||||
@ -30,6 +30,8 @@ pub use self::decryption_session::Session as DecryptionSession;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
pub use super::key_storage::tests::DummyKeyStorage;
 | 
					pub use super::key_storage::tests::DummyKeyStorage;
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					pub use super::acl_storage::tests::DummyAclStorage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type SessionId = DocumentAddress;
 | 
					pub type SessionId = DocumentAddress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -72,6 +74,8 @@ pub enum Error {
 | 
				
			|||||||
	Serde(String),
 | 
						Serde(String),
 | 
				
			||||||
	/// Key storage error.
 | 
						/// Key storage error.
 | 
				
			||||||
	KeyStorage(String),
 | 
						KeyStorage(String),
 | 
				
			||||||
 | 
						/// Acl storage error.
 | 
				
			||||||
 | 
						AccessDenied,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<ethkey::Error> for Error {
 | 
					impl From<ethkey::Error> for Error {
 | 
				
			||||||
@ -110,6 +114,7 @@ impl fmt::Display for Error {
 | 
				
			|||||||
			Error::Io(ref e) => write!(f, "i/o error {}", e),
 | 
								Error::Io(ref e) => write!(f, "i/o error {}", e),
 | 
				
			||||||
			Error::Serde(ref e) => write!(f, "serde error {}", e),
 | 
								Error::Serde(ref e) => write!(f, "serde error {}", e),
 | 
				
			||||||
			Error::KeyStorage(ref e) => write!(f, "key storage error {}", e),
 | 
								Error::KeyStorage(ref e) => write!(f, "key storage error {}", e),
 | 
				
			||||||
 | 
								Error::AccessDenied => write!(f, "Access denied"),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -32,11 +32,14 @@ extern crate tokio_service;
 | 
				
			|||||||
extern crate tokio_proto;
 | 
					extern crate tokio_proto;
 | 
				
			||||||
extern crate url;
 | 
					extern crate url;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern crate ethabi;
 | 
				
			||||||
 | 
					extern crate ethcore;
 | 
				
			||||||
extern crate ethcore_devtools as devtools;
 | 
					extern crate ethcore_devtools as devtools;
 | 
				
			||||||
extern crate ethcore_util as util;
 | 
					extern crate ethcore_util as util;
 | 
				
			||||||
extern crate ethcore_ipc as ipc;
 | 
					extern crate ethcore_ipc as ipc;
 | 
				
			||||||
extern crate ethcrypto;
 | 
					extern crate ethcrypto;
 | 
				
			||||||
extern crate ethkey;
 | 
					extern crate ethkey;
 | 
				
			||||||
 | 
					extern crate native_contracts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod key_server_cluster;
 | 
					mod key_server_cluster;
 | 
				
			||||||
mod types;
 | 
					mod types;
 | 
				
			||||||
@ -52,15 +55,18 @@ mod key_server;
 | 
				
			|||||||
mod key_storage;
 | 
					mod key_storage;
 | 
				
			||||||
mod serialization;
 | 
					mod serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use std::sync::Arc;
 | 
				
			||||||
 | 
					use ethcore::client::Client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use types::all::{DocumentAddress, DocumentKey, DocumentEncryptedKey, RequestSignature, Public,
 | 
					pub use types::all::{DocumentAddress, DocumentKey, DocumentEncryptedKey, RequestSignature, Public,
 | 
				
			||||||
	Error, NodeAddress, ServiceConfiguration, ClusterConfiguration, EncryptionConfiguration};
 | 
						Error, NodeAddress, ServiceConfiguration, ClusterConfiguration, EncryptionConfiguration};
 | 
				
			||||||
pub use traits::{KeyServer};
 | 
					pub use traits::{KeyServer};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Start new key server instance
 | 
					/// Start new key server instance
 | 
				
			||||||
pub fn start(config: ServiceConfiguration) -> Result<Box<KeyServer>, Error> {
 | 
					pub fn start(client: Arc<Client>, config: ServiceConfiguration) -> Result<Box<KeyServer>, Error> {
 | 
				
			||||||
	use std::sync::Arc;
 | 
						use std::sync::Arc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let acl_storage = Arc::new(acl_storage::DummyAclStorage::default());
 | 
						let acl_storage = Arc::new(acl_storage::OnChainAclStorage::new(client));
 | 
				
			||||||
	let key_storage = Arc::new(key_storage::PersistentKeyStorage::new(&config)?);
 | 
						let key_storage = Arc::new(key_storage::PersistentKeyStorage::new(&config)?);
 | 
				
			||||||
	let key_server = key_server::KeyServerImpl::new(&config.cluster_config, acl_storage, key_storage)?;
 | 
						let key_server = key_server::KeyServerImpl::new(&config.cluster_config, acl_storage, key_storage)?;
 | 
				
			||||||
	let listener = http_listener::KeyServerHttpListener::start(config, key_server)?;
 | 
						let listener = http_listener::KeyServerHttpListener::start(config, key_server)?;
 | 
				
			||||||
 | 
				
			|||||||
@ -119,7 +119,10 @@ impl From<ethkey::Error> for Error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl From<key_server_cluster::Error> for Error {
 | 
					impl From<key_server_cluster::Error> for Error {
 | 
				
			||||||
	fn from(err: key_server_cluster::Error) -> Self {
 | 
						fn from(err: key_server_cluster::Error) -> Self {
 | 
				
			||||||
		Error::Internal(err.into())
 | 
							match err {
 | 
				
			||||||
 | 
								key_server_cluster::Error::AccessDenied => Error::AccessDenied,
 | 
				
			||||||
 | 
								_ => Error::Internal(err.into()),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user