From a91e562021d60acdf4d7a1463bee6f10e9a0c430 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 20 Mar 2018 05:03:51 +0300 Subject: [PATCH] SecretStore: store key author address in db (#7887) * SecretStore: ability to identify requester via Public/Address * SecretStore: store author address instead of public in db --- .../servers_set_change_session.rs | 2 +- .../admin_sessions/share_add_session.rs | 4 +- .../client_sessions/decryption_session.rs | 6 +- .../client_sessions/encryption_session.rs | 8 +- .../client_sessions/generation_session.rs | 22 +-- .../client_sessions/signing_session_ecdsa.rs | 10 +- .../signing_session_schnorr.rs | 15 +- .../src/key_server_cluster/cluster.rs | 4 +- .../src/key_server_cluster/message.rs | 6 +- secret_store/src/key_server_cluster/mod.rs | 2 +- secret_store/src/key_storage.rs | 137 +++++++++++++++--- secret_store/src/types/all.rs | 4 + 12 files changed, 158 insertions(+), 62 deletions(-) diff --git a/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs b/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs index 916b67217..01f339237 100644 --- a/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs +++ b/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs @@ -1166,7 +1166,7 @@ pub mod tests { pub fn generate_key(threshold: usize, nodes_ids: BTreeSet) -> GenerationMessageLoop { let mut gml = GenerationMessageLoop::with_nodes_ids(nodes_ids); - gml.master().initialize(Public::default(), false, threshold, gml.nodes.keys().cloned().collect::>().into()).unwrap(); + gml.master().initialize(Default::default(), false, threshold, gml.nodes.keys().cloned().collect::>().into()).unwrap(); while let Some((from, to, message)) = gml.take_message() { gml.process_message((from, to, message)).unwrap(); } diff --git a/secret_store/src/key_server_cluster/admin_sessions/share_add_session.rs b/secret_store/src/key_server_cluster/admin_sessions/share_add_session.rs index 44e823d6c..7da73543b 100644 --- a/secret_store/src/key_server_cluster/admin_sessions/share_add_session.rs +++ b/secret_store/src/key_server_cluster/admin_sessions/share_add_session.rs @@ -16,7 +16,7 @@ use std::sync::Arc; use std::collections::{BTreeSet, BTreeMap}; -use ethereum_types::H256; +use ethereum_types::{H256, Address}; use ethkey::{Public, Secret, Signature}; use parking_lot::{Mutex, Condvar}; use key_server_cluster::{Error, SessionId, NodeId, DocumentKeyShare, DocumentKeyShareVersion, KeyStorage}; @@ -101,7 +101,7 @@ struct NewKeyShare { /// NewKeyShare: threshold. pub threshold: usize, /// NewKeyShare: author. - pub author: Public, + pub author: Address, /// NewKeyShare: joint public. pub joint_public: Public, /// NewKeyShare: Common (shared) encryption point. diff --git a/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs b/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs index 502a07bbc..c3946f746 100644 --- a/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs @@ -789,7 +789,7 @@ mod tests { let common_point: Public = "6962be696e1bcbba8e64cc7fddf140f854835354b5804f3bb95ae5a2799130371b589a131bd39699ac7174ccb35fc4342dab05331202209582fc8f3a40916ab0".into(); let encrypted_point: Public = "b07031982bde9890e12eff154765f03c56c3ab646ad47431db5dd2d742a9297679c4c65b998557f8008469afd0c43d40b6c5f6c6a1c7354875da4115237ed87a".into(); let encrypted_datas: Vec<_> = (0..5).map(|i| DocumentKeyShare { - author: Public::default(), + author: Default::default(), threshold: 3, public: Default::default(), common_point: Some(common_point.clone()), @@ -882,7 +882,7 @@ mod tests { }, access_key: Random.generate().unwrap().secret().clone(), key_share: Some(DocumentKeyShare { - author: Public::default(), + author: Default::default(), threshold: 0, public: Default::default(), common_point: Some(Random.generate().unwrap().public().clone()), @@ -936,7 +936,7 @@ mod tests { }, access_key: Random.generate().unwrap().secret().clone(), key_share: Some(DocumentKeyShare { - author: Public::default(), + author: Default::default(), threshold: 2, public: Default::default(), common_point: Some(Random.generate().unwrap().public().clone()), diff --git a/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs b/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs index 18b8c53ff..eafac6fd2 100644 --- a/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs @@ -157,8 +157,8 @@ impl SessionImpl { // save encryption data if let Some(mut encrypted_data) = self.encrypted_data.clone() { // check that the requester is the author of the encrypted data - let requester_public = requester.public(&self.id).ok_or(Error::InsufficientRequesterData)?; - if encrypted_data.author != requester_public { + let requester_address = requester.address(&self.id).ok_or(Error::InsufficientRequesterData)?; + if encrypted_data.author != requester_address { return Err(Error::AccessDenied); } @@ -201,8 +201,8 @@ impl SessionImpl { // check that the requester is the author of the encrypted data if let Some(mut encrypted_data) = self.encrypted_data.clone() { let requester: Requester = message.requester.clone().into(); - let requestor_public = requester.public(&self.id).ok_or(Error::InsufficientRequesterData)?; - if encrypted_data.author != requestor_public { + let requestor_address = requester.address(&self.id).ok_or(Error::InsufficientRequesterData)?; + if encrypted_data.author != requestor_address { return Err(Error::AccessDenied); } diff --git a/secret_store/src/key_server_cluster/client_sessions/generation_session.rs b/secret_store/src/key_server_cluster/client_sessions/generation_session.rs index a8b9501e2..1f1df70ce 100644 --- a/secret_store/src/key_server_cluster/client_sessions/generation_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/generation_session.rs @@ -19,6 +19,7 @@ use std::fmt::{Debug, Formatter, Error as FmtError}; use std::time; use std::sync::Arc; use parking_lot::{Condvar, Mutex}; +use ethereum_types::Address; use ethkey::{Public, Secret}; use key_server_cluster::{Error, NodeId, SessionId, KeyStorage, DocumentKeyShare, DocumentKeyShareVersion}; use key_server_cluster::math; @@ -77,8 +78,8 @@ struct SessionData { // === Values, filled when session initialization just starts === /// Reference to the node, which has started this session. master: Option, - /// Public key of the creator of the session. - author: Option, + /// Address of the creator of the session. + author: Option
, // === Values, filled when session initialization is completed === /// Is zero secret generation session? @@ -262,7 +263,7 @@ impl SessionImpl { } /// Start new session initialization. This must be called on master node. - pub fn initialize(&self, author: Public, is_zero: bool, threshold: usize, nodes: InitializationNodes) -> Result<(), Error> { + pub fn initialize(&self, author: Address, is_zero: bool, threshold: usize, nodes: InitializationNodes) -> Result<(), Error> { check_cluster_nodes(self.node(), &nodes.set())?; check_threshold(threshold, &nodes.set())?; @@ -935,6 +936,7 @@ pub mod tests { use std::sync::Arc; use std::collections::{BTreeSet, BTreeMap, VecDeque}; use tokio_core::reactor::Core; + use ethereum_types::Address; use ethkey::{Random, Generator, Public, KeyPair}; use key_server_cluster::{NodeId, SessionId, Error, KeyStorage, DummyKeyStorage}; use key_server_cluster::message::{self, Message, GenerationMessage}; @@ -1063,7 +1065,7 @@ pub mod tests { fn make_simple_cluster(threshold: usize, num_nodes: usize) -> Result<(SessionId, NodeId, NodeId, MessageLoop), Error> { let l = MessageLoop::new(num_nodes); - l.master().initialize(Public::default(), false, threshold, l.nodes.keys().cloned().collect::>().into())?; + l.master().initialize(Default::default(), false, threshold, l.nodes.keys().cloned().collect::>().into())?; let session_id = l.session_id.clone(); let master_id = l.master().node().clone(); @@ -1074,7 +1076,7 @@ pub mod tests { #[test] fn initializes_in_cluster_of_single_node() { let l = MessageLoop::new(1); - assert!(l.master().initialize(Public::default(), false, 0, l.nodes.keys().cloned().collect::>().into()).is_ok()); + assert!(l.master().initialize(Default::default(), false, 0, l.nodes.keys().cloned().collect::>().into()).is_ok()); } #[test] @@ -1089,7 +1091,7 @@ pub mod tests { nonce: Some(0), }); let cluster_nodes: BTreeSet<_> = (0..2).map(|_| math::generate_random_point().unwrap()).collect(); - assert_eq!(session.initialize(Public::default(), false, 0, cluster_nodes.into()).unwrap_err(), Error::InvalidNodesConfiguration); + assert_eq!(session.initialize(Default::default(), false, 0, cluster_nodes.into()).unwrap_err(), Error::InvalidNodesConfiguration); } #[test] @@ -1103,7 +1105,7 @@ pub mod tests { #[test] fn fails_to_initialize_when_already_initialized() { let (_, _, _, l) = make_simple_cluster(0, 2).unwrap(); - assert_eq!(l.master().initialize(Public::default(), false, 0, l.nodes.keys().cloned().collect::>().into()).unwrap_err(), + assert_eq!(l.master().initialize(Default::default(), false, 0, l.nodes.keys().cloned().collect::>().into()).unwrap_err(), Error::InvalidStateForRequest); } @@ -1183,7 +1185,7 @@ pub mod tests { assert_eq!(l.first_slave().on_initialize_session(m, &message::InitializeSession { session: sid.into(), session_nonce: 0, - author: Public::default().into(), + author: Address::default().into(), nodes: nodes.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), is_zero: false, threshold: 0, @@ -1200,7 +1202,7 @@ pub mod tests { assert_eq!(l.first_slave().on_initialize_session(m, &message::InitializeSession { session: sid.into(), session_nonce: 0, - author: Public::default().into(), + author: Address::default().into(), nodes: nodes.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), is_zero: false, threshold: 2, @@ -1343,7 +1345,7 @@ pub mod tests { let test_cases = [(0, 5), (2, 5), (3, 5)]; for &(threshold, num_nodes) in &test_cases { let mut l = MessageLoop::new(num_nodes); - l.master().initialize(Public::default(), false, threshold, l.nodes.keys().cloned().collect::>().into()).unwrap(); + l.master().initialize(Default::default(), false, threshold, l.nodes.keys().cloned().collect::>().into()).unwrap(); assert_eq!(l.nodes.len(), num_nodes); // let nodes do initialization + keys dissemination diff --git a/secret_store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs b/secret_store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs index cd97a1c17..ddd494412 100644 --- a/secret_store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs +++ b/secret_store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs @@ -402,7 +402,7 @@ impl SessionImpl { session_nonce: n, message: m, })); - sig_nonce_generation_session.initialize(Public::default(), false, key_share.threshold, consensus_group_map.clone().into())?; + sig_nonce_generation_session.initialize(Default::default(), false, key_share.threshold, consensus_group_map.clone().into())?; data.sig_nonce_generation_session = Some(sig_nonce_generation_session); // start generation of inversed nonce computation session @@ -414,7 +414,7 @@ impl SessionImpl { session_nonce: n, message: m, })); - inv_nonce_generation_session.initialize(Public::default(), false, key_share.threshold, consensus_group_map.clone().into())?; + inv_nonce_generation_session.initialize(Default::default(), false, key_share.threshold, consensus_group_map.clone().into())?; data.inv_nonce_generation_session = Some(inv_nonce_generation_session); // start generation of zero-secret shares for inversed nonce computation session @@ -426,7 +426,7 @@ impl SessionImpl { session_nonce: n, message: m, })); - inv_zero_generation_session.initialize(Public::default(), true, key_share.threshold * 2, consensus_group_map.clone().into())?; + inv_zero_generation_session.initialize(Default::default(), true, key_share.threshold * 2, consensus_group_map.clone().into())?; data.inv_zero_generation_session = Some(inv_zero_generation_session); data.state = SessionState::NoncesGenerating; @@ -1054,7 +1054,7 @@ mod tests { use std::sync::Arc; use std::collections::{BTreeSet, BTreeMap, VecDeque}; use ethereum_types::H256; - use ethkey::{self, Random, Generator, Public, KeyPair, verify_public}; + use ethkey::{self, Random, Generator, KeyPair, verify_public}; use acl_storage::DummyAclStorage; use key_server_cluster::{NodeId, DummyKeyStorage, SessionId, SessionMeta, Error, KeyStorage}; use key_server_cluster::cluster_sessions::ClusterSession; @@ -1165,7 +1165,7 @@ mod tests { fn prepare_signing_sessions(threshold: usize, num_nodes: usize) -> (KeyGenerationMessageLoop, MessageLoop) { // run key generation sessions let mut gl = KeyGenerationMessageLoop::new(num_nodes); - gl.master().initialize(Public::default(), false, threshold, gl.nodes.keys().cloned().collect::>().into()).unwrap(); + gl.master().initialize(Default::default(), false, threshold, gl.nodes.keys().cloned().collect::>().into()).unwrap(); while let Some((from, to, message)) = gl.take_message() { gl.process_message((from, to, message)).unwrap(); } diff --git a/secret_store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs b/secret_store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs index 625565ac5..4eaf07237 100644 --- a/secret_store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs +++ b/secret_store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs @@ -277,7 +277,7 @@ impl SessionImpl { }), nonce: None, }); - generation_session.initialize(Public::default(), false, 0, vec![self.core.meta.self_node_id.clone()].into_iter().collect::>().into())?; + generation_session.initialize(Default::default(), false, 0, vec![self.core.meta.self_node_id.clone()].into_iter().collect::>().into())?; debug_assert_eq!(generation_session.state(), GenerationSessionState::WaitingForGenerationConfirmation); let joint_public_and_secret = generation_session @@ -405,7 +405,8 @@ impl SessionImpl { }), nonce: None, }); - generation_session.initialize(Public::default(), false, key_share.threshold, consensus_group.into())?; + + generation_session.initialize(Default::default(), false, key_share.threshold, consensus_group.into())?; data.generation_session = Some(generation_session); data.state = SessionState::SessionKeyGeneration; @@ -800,7 +801,7 @@ mod tests { use std::sync::Arc; use std::str::FromStr; use std::collections::{BTreeSet, BTreeMap, VecDeque}; - use ethereum_types::H256; + use ethereum_types::{Address, H256}; use ethkey::{self, Random, Generator, Public, Secret, KeyPair}; use acl_storage::DummyAclStorage; use key_server_cluster::{NodeId, DummyKeyStorage, DocumentKeyShare, DocumentKeyShareVersion, SessionId, @@ -927,7 +928,7 @@ mod tests { fn prepare_signing_sessions(threshold: usize, num_nodes: usize) -> (KeyGenerationMessageLoop, MessageLoop) { // run key generation sessions let mut gl = KeyGenerationMessageLoop::new(num_nodes); - gl.master().initialize(Public::default(), false, threshold, gl.nodes.keys().cloned().collect::>().into()).unwrap(); + gl.master().initialize(Default::default(), false, threshold, gl.nodes.keys().cloned().collect::>().into()).unwrap(); while let Some((from, to, message)) = gl.take_message() { gl.process_message((from, to, message)).unwrap(); } @@ -971,7 +972,7 @@ mod tests { }, access_key: Random.generate().unwrap().secret().clone(), key_share: Some(DocumentKeyShare { - author: Public::default(), + author: Default::default(), threshold: 0, public: Default::default(), common_point: Some(Random.generate().unwrap().public().clone()), @@ -1025,7 +1026,7 @@ mod tests { }, access_key: Random.generate().unwrap().secret().clone(), key_share: Some(DocumentKeyShare { - author: Public::default(), + author: Default::default(), threshold: 2, public: Default::default(), common_point: Some(Random.generate().unwrap().public().clone()), @@ -1113,7 +1114,7 @@ mod tests { message: GenerationMessage::InitializeSession(InitializeSession { session: SessionId::default().into(), session_nonce: 0, - author: Public::default().into(), + author: Address::default().into(), nodes: BTreeMap::new(), is_zero: false, threshold: 1, diff --git a/secret_store/src/key_server_cluster/cluster.rs b/secret_store/src/key_server_cluster/cluster.rs index 62e0dce6a..2dcefea25 100644 --- a/secret_store/src/key_server_cluster/cluster.rs +++ b/secret_store/src/key_server_cluster/cluster.rs @@ -26,7 +26,7 @@ use parking_lot::{RwLock, Mutex}; use tokio_io::IoFuture; use tokio_core::reactor::{Handle, Remote, Interval}; use tokio_core::net::{TcpListener, TcpStream}; -use ethkey::{Public, KeyPair, Signature, Random, Generator}; +use ethkey::{Public, KeyPair, Signature, Random, Generator, public_to_address}; use ethereum_types::H256; use key_server_cluster::{Error, NodeId, SessionId, Requester, AclStorage, KeyStorage, KeyServerSet, NodeKeyPair}; use key_server_cluster::cluster_sessions::{ClusterSession, AdminSession, ClusterSessions, SessionIdWithSubSession, @@ -907,7 +907,7 @@ impl ClusterClient for ClusterClientImpl { let cluster = create_cluster_view(&self.data, true)?; let session = self.data.sessions.generation_sessions.insert(cluster, self.data.self_key_pair.public().clone(), session_id, None, false, None)?; - match session.initialize(author, false, threshold, connected_nodes.into()) { + match session.initialize(public_to_address(&author), false, threshold, connected_nodes.into()) { Ok(()) => Ok(session), Err(error) => { self.data.sessions.generation_sessions.remove(&session.id()); diff --git a/secret_store/src/key_server_cluster/message.rs b/secret_store/src/key_server_cluster/message.rs index 999ed625f..9a93efb03 100644 --- a/secret_store/src/key_server_cluster/message.rs +++ b/secret_store/src/key_server_cluster/message.rs @@ -19,7 +19,7 @@ use std::collections::{BTreeSet, BTreeMap}; use ethkey::Secret; use key_server_cluster::SessionId; use super::{SerializableH256, SerializablePublic, SerializableSecret, SerializableSignature, - SerializableMessageHash, SerializableRequester}; + SerializableMessageHash, SerializableRequester, SerializableAddress}; pub type MessageSessionId = SerializableH256; pub type MessageNodeId = SerializablePublic; @@ -273,7 +273,7 @@ pub struct InitializeSession { /// Session-level nonce. pub session_nonce: u64, /// Session author. - pub author: SerializablePublic, + pub author: SerializableAddress, /// All session participants along with their identification numbers. pub nodes: BTreeMap, /// Is zero secret generation session? @@ -963,7 +963,7 @@ pub struct KeyShareCommon { /// Key threshold. pub threshold: usize, /// Author of key share entry. - pub author: SerializablePublic, + pub author: SerializableAddress, /// Joint public. pub joint_public: SerializablePublic, /// Common (shared) encryption point. diff --git a/secret_store/src/key_server_cluster/mod.rs b/secret_store/src/key_server_cluster/mod.rs index 97c7d414b..17334e838 100644 --- a/secret_store/src/key_server_cluster/mod.rs +++ b/secret_store/src/key_server_cluster/mod.rs @@ -26,7 +26,7 @@ pub use super::acl_storage::AclStorage; pub use super::key_storage::{KeyStorage, DocumentKeyShare, DocumentKeyShareVersion}; pub use super::key_server_set::{is_migration_required, KeyServerSet, KeyServerSetSnapshot, KeyServerSetMigration}; pub use super::serialization::{SerializableSignature, SerializableH256, SerializableSecret, SerializablePublic, - SerializableRequester, SerializableMessageHash}; + SerializableRequester, SerializableMessageHash, SerializableAddress}; pub use self::cluster::{ClusterCore, ClusterConfiguration, ClusterClient}; pub use self::cluster_sessions::{ClusterSession, ClusterSessionsListener}; #[cfg(test)] diff --git a/secret_store/src/key_storage.rs b/secret_store/src/key_storage.rs index f540f357d..4429500db 100644 --- a/secret_store/src/key_storage.rs +++ b/secret_store/src/key_storage.rs @@ -18,27 +18,27 @@ use std::path::PathBuf; use std::collections::BTreeMap; use serde_json; use tiny_keccak::Keccak; -use ethereum_types::H256; -use ethkey::{Secret, Public}; +use ethereum_types::{H256, Address}; +use ethkey::{Secret, Public, public_to_address}; use kvdb_rocksdb::{Database, DatabaseIterator}; use types::all::{Error, ServiceConfiguration, ServerKeyId, NodeId}; -use serialization::{SerializablePublic, SerializableSecret, SerializableH256}; +use serialization::{SerializablePublic, SerializableSecret, SerializableH256, SerializableAddress}; /// Key of version value. const DB_META_KEY_VERSION: &'static [u8; 7] = b"version"; /// Current db version. -const CURRENT_VERSION: u8 = 2; +const CURRENT_VERSION: u8 = 3; /// Current type of serialized key shares. -type CurrentSerializableDocumentKeyShare = SerializableDocumentKeyShareV2; +type CurrentSerializableDocumentKeyShare = SerializableDocumentKeyShareV3; /// Current type of serialized key shares versions. -type CurrentSerializableDocumentKeyVersion = SerializableDocumentKeyShareVersionV2; +type CurrentSerializableDocumentKeyVersion = SerializableDocumentKeyShareVersionV3; /// Encrypted key share, stored by key storage on the single key server. #[derive(Debug, Clone, PartialEq)] #[cfg_attr(test, derive(Default))] pub struct DocumentKeyShare { /// Author of the entry. - pub author: Public, + pub author: Address, /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). pub threshold: usize, /// Server public key. @@ -136,7 +136,8 @@ struct SerializableDocumentKeyShareV2 { /// Encrypted point. pub encrypted_point: Option, /// Versions. - pub versions: Vec} + pub versions: Vec +} /// V2 of encrypted key share version, as it is stored by key storage on the single key server. #[derive(Serialize, Deserialize)] @@ -149,6 +150,26 @@ struct SerializableDocumentKeyShareVersionV2 { pub secret_share: SerializableSecret, } +/// V3 of encrypted key share, as it is stored by key storage on the single key server. +#[derive(Serialize, Deserialize)] +struct SerializableDocumentKeyShareV3 { + /// Author of the entry. + pub author: SerializableAddress, + /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). + pub threshold: usize, + /// Server public. + pub public: SerializablePublic, + /// Common (shared) encryption point. + pub common_point: Option, + /// Encrypted point. + pub encrypted_point: Option, + /// Versions. + pub versions: Vec +} + +/// V3 of encrypted key share version, as it is stored by key storage on the single key server. +type SerializableDocumentKeyShareVersionV3 = SerializableDocumentKeyShareVersionV2; + impl PersistentKeyStorage { /// Create new persistent document encryption keys storage pub fn new(config: &ServiceConfiguration) -> Result { @@ -177,7 +198,7 @@ fn upgrade_db(db: Database) -> Result { let current_key = CurrentSerializableDocumentKeyShare { // author is used in separate generation + encrypt sessions. // in v0 there have been only simultaneous GenEnc sessions. - author: Public::default().into(), // added in v1 + author: Address::default().into(), // added in v1 threshold: v0_key.threshold, public: Public::default().into(), // addded in v2 common_point: Some(v0_key.common_point), @@ -200,7 +221,7 @@ fn upgrade_db(db: Database) -> Result { for (db_key, db_value) in db.iter(None).into_iter().flat_map(|inner| inner).filter(|&(ref k, _)| **k != *DB_META_KEY_VERSION) { let v1_key = serde_json::from_slice::(&db_value).map_err(|e| Error::Database(e.to_string()))?; let current_key = CurrentSerializableDocumentKeyShare { - author: v1_key.author, // added in v1 + author: public_to_address(&v1_key.author).into(), // added in v1 + changed in v3 threshold: v1_key.threshold, public: Public::default().into(), // addded in v2 common_point: v1_key.common_point, @@ -217,7 +238,26 @@ fn upgrade_db(db: Database) -> Result { db.write(batch)?; Ok(db) } - 2 => Ok(db), + 2 => { + let mut batch = db.transaction(); + batch.put(None, DB_META_KEY_VERSION, &[CURRENT_VERSION]); + for (db_key, db_value) in db.iter(None).into_iter().flat_map(|inner| inner).filter(|&(ref k, _)| **k != *DB_META_KEY_VERSION) { + let v2_key = serde_json::from_slice::(&db_value).map_err(|e| Error::Database(e.to_string()))?; + let current_key = CurrentSerializableDocumentKeyShare { + author: public_to_address(&v2_key.author).into(), // changed in v3 + threshold: v2_key.threshold, + public: v2_key.public, + common_point: v2_key.common_point, + encrypted_point: v2_key.encrypted_point, + versions: v2_key.versions, + }; + let db_value = serde_json::to_vec(¤t_key).map_err(|e| Error::Database(e.to_string()))?; + batch.put(None, &*db_key, &*db_value); + } + db.write(batch)?; + Ok(db) + }, + 3 => Ok(db), _ => Err(Error::Database(format!("unsupported SecretStore database version: {}", version))), } } @@ -331,9 +371,9 @@ impl DocumentKeyShareVersion { } } -impl From for SerializableDocumentKeyShareV2 { +impl From for SerializableDocumentKeyShareV3 { fn from(key: DocumentKeyShare) -> Self { - SerializableDocumentKeyShareV2 { + SerializableDocumentKeyShareV3 { author: key.author.into(), threshold: key.threshold, public: key.public.into(), @@ -344,9 +384,9 @@ impl From for SerializableDocumentKeyShareV2 { } } -impl From for SerializableDocumentKeyShareVersionV2 { +impl From for SerializableDocumentKeyShareVersionV3 { fn from(version: DocumentKeyShareVersion) -> Self { - SerializableDocumentKeyShareVersionV2 { + SerializableDocumentKeyShareVersionV3 { hash: version.hash.into(), id_numbers: version.id_numbers.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), secret_share: version.secret_share.into(), @@ -354,8 +394,8 @@ impl From for SerializableDocumentKeyShareVersionV2 { } } -impl From for DocumentKeyShare { - fn from(key: SerializableDocumentKeyShareV2) -> Self { +impl From for DocumentKeyShare { + fn from(key: SerializableDocumentKeyShareV3) -> Self { DocumentKeyShare { author: key.author.into(), threshold: key.threshold, @@ -381,12 +421,13 @@ pub mod tests { use parking_lot::RwLock; use serde_json; use self::tempdir::TempDir; - use ethkey::{Random, Generator, Public, Secret}; + use ethereum_types::{Address, H256}; + use ethkey::{Random, Generator, Public, Secret, public_to_address}; use kvdb_rocksdb::Database; use types::all::{Error, NodeAddress, ServiceConfiguration, ClusterConfiguration, ServerKeyId}; use super::{DB_META_KEY_VERSION, CURRENT_VERSION, KeyStorage, PersistentKeyStorage, DocumentKeyShare, - DocumentKeyShareVersion, SerializableDocumentKeyShareV0, SerializableDocumentKeyShareV1, - CurrentSerializableDocumentKeyShare, upgrade_db}; + DocumentKeyShareVersion, CurrentSerializableDocumentKeyShare, upgrade_db, SerializableDocumentKeyShareV0, + SerializableDocumentKeyShareV1, SerializableDocumentKeyShareV2, SerializableDocumentKeyShareVersionV2}; /// In-memory document encryption keys storage #[derive(Default)] @@ -451,7 +492,7 @@ pub mod tests { let key1 = ServerKeyId::from(1); let value1 = DocumentKeyShare { - author: Public::default(), + author: Default::default(), threshold: 100, public: Public::default(), common_point: Some(Random.generate().unwrap().public().clone()), @@ -466,7 +507,7 @@ pub mod tests { }; let key2 = ServerKeyId::from(2); let value2 = DocumentKeyShare { - author: Public::default(), + author: Default::default(), threshold: 200, public: Public::default(), common_point: Some(Random.generate().unwrap().public().clone()), @@ -523,7 +564,7 @@ pub mod tests { // check upgrade assert_eq!(db.get(None, DB_META_KEY_VERSION).unwrap().unwrap()[0], CURRENT_VERSION); let key = serde_json::from_slice::(&db.get(None, &[7]).unwrap().map(|key| key.to_vec()).unwrap()).unwrap(); - assert_eq!(Public::default(), key.author.clone().into()); + assert_eq!(Address::default(), key.author.clone().into()); assert_eq!(777, key.threshold); assert_eq!(Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".parse::().unwrap()), key.common_point.clone().map(Into::into)); assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::().unwrap()), key.encrypted_point.clone().map(Into::into)); @@ -569,7 +610,55 @@ pub mod tests { assert_eq!(777, key.threshold); assert_eq!(Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".parse::().unwrap()), key.common_point.clone().map(Into::into)); assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::().unwrap()), key.encrypted_point.clone().map(Into::into)); - assert_eq!(key.author, "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into()); + assert_eq!(key.author.0, public_to_address(&"b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into())); + + assert_eq!(key.versions.len(), 1); + assert_eq!(vec![( + "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".parse::().unwrap(), + "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap(), + )], key.versions[0].id_numbers.clone().into_iter().map(|(k, v)| (k.into(), v.into())).collect::>()); + + assert_eq!("00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b".parse::().unwrap(), key.versions[0].secret_share.clone().into()); + } + + #[test] + fn upgrade_db_from_2() { + let tempdir = TempDir::new("").unwrap(); + let db = Database::open_default(&tempdir.path().display().to_string()).unwrap(); + + // prepare v2 database + { + let key = serde_json::to_vec(&SerializableDocumentKeyShareV2 { + author: "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), + threshold: 777, + common_point: Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".into()), + encrypted_point: Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".into()), + public: "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), + versions: vec![SerializableDocumentKeyShareVersionV2 { + hash: "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap().into(), + id_numbers: vec![( + "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), + "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap().into(), + )].into_iter().collect(), + secret_share: "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b".parse::().unwrap().into(), + }], + }).unwrap(); + let mut batch = db.transaction(); + batch.put(None, DB_META_KEY_VERSION, &[2]); + batch.put(None, &[7], &key); + db.write(batch).unwrap(); + } + + // upgrade database + let db = upgrade_db(db).unwrap(); + + // check upgrade + assert_eq!(db.get(None, DB_META_KEY_VERSION).unwrap().unwrap()[0], CURRENT_VERSION); + let key = serde_json::from_slice::(&db.get(None, &[7]).unwrap().map(|key| key.to_vec()).unwrap()).unwrap(); + assert_eq!(777, key.threshold); + assert_eq!(Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".parse::().unwrap()), key.common_point.clone().map(Into::into)); + assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::().unwrap()), key.encrypted_point.clone().map(Into::into)); + assert_eq!(key.author.0, public_to_address(&"b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".parse().unwrap())); assert_eq!(key.versions.len(), 1); assert_eq!(vec![( diff --git a/secret_store/src/types/all.rs b/secret_store/src/types/all.rs index f1afd3da2..9c6f4d172 100644 --- a/secret_store/src/types/all.rs +++ b/secret_store/src/types/all.rs @@ -191,6 +191,10 @@ impl Requester { Requester::Address(_) => None, } } + + pub fn address(&self, server_key_id: &ServerKeyId) -> Option { + self.public(server_key_id).map(|p| ethkey::public_to_address(&p)) + } } impl From for Requester {