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,38 +14,92 @@
|
|||||||
// 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 {
|
||||||
#[cfg(test)]
|
pub fn new(client: Arc<Client>) -> Self {
|
||||||
/// Prohibit given requestor access to given document
|
OnChainAclStorage {
|
||||||
pub fn prohibit(&self, public: Public, document: DocumentAddress) {
|
client: client,
|
||||||
self.prohibited.write()
|
contract: Mutex::new(None),
|
||||||
.entry(public)
|
}
|
||||||
.or_insert_with(Default::default)
|
|
||||||
.insert(document);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AclStorage for DummyAclStorage {
|
impl AclStorage for OnChainAclStorage {
|
||||||
fn check(&self, public: &Public, document: &DocumentAddress) -> Result<bool, Error> {
|
fn check(&self, public: &Public, document: &DocumentAddress) -> Result<bool, Error> {
|
||||||
Ok(self.prohibited.read()
|
let mut contract = self.contract.lock();
|
||||||
.get(public)
|
if !contract.is_some() {
|
||||||
.map(|docs| !docs.contains(document))
|
*contract = self.client.registry_address(ACL_CHECKER_CONTRACT_REGISTRY_NAME.to_owned())
|
||||||
.unwrap_or(true))
|
.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)]
|
||||||
|
/// Prohibit given requestor access to given document
|
||||||
|
pub fn prohibit(&self, public: Public, document: DocumentAddress) {
|
||||||
|
self.prohibited.write()
|
||||||
|
.entry(public)
|
||||||
|
.or_insert_with(Default::default)
|
||||||
|
.insert(document);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AclStorage for DummyAclStorage {
|
||||||
|
fn check(&self, public: &Public, document: &DocumentAddress) -> Result<bool, Error> {
|
||||||
|
Ok(self.prohibited.read()
|
||||||
|
.get(public)
|
||||||
|
.map(|docs| !docs.contains(document))
|
||||||
|
.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