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
This commit is contained in:
parent
d7f690c8ba
commit
a91e562021
@ -1166,7 +1166,7 @@ pub mod tests {
|
||||
|
||||
pub fn generate_key(threshold: usize, nodes_ids: BTreeSet<NodeId>) -> GenerationMessageLoop {
|
||||
let mut gml = GenerationMessageLoop::with_nodes_ids(nodes_ids);
|
||||
gml.master().initialize(Public::default(), false, threshold, gml.nodes.keys().cloned().collect::<BTreeSet<_>>().into()).unwrap();
|
||||
gml.master().initialize(Default::default(), false, threshold, gml.nodes.keys().cloned().collect::<BTreeSet<_>>().into()).unwrap();
|
||||
while let Some((from, to, message)) = gml.take_message() {
|
||||
gml.process_message((from, to, message)).unwrap();
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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()),
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<NodeId>,
|
||||
/// Public key of the creator of the session.
|
||||
author: Option<Public>,
|
||||
/// Address of the creator of the session.
|
||||
author: Option<Address>,
|
||||
|
||||
// === 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::<BTreeSet<_>>().into())?;
|
||||
l.master().initialize(Default::default(), false, threshold, l.nodes.keys().cloned().collect::<BTreeSet<_>>().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::<BTreeSet<_>>().into()).is_ok());
|
||||
assert!(l.master().initialize(Default::default(), false, 0, l.nodes.keys().cloned().collect::<BTreeSet<_>>().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::<BTreeSet<_>>().into()).unwrap_err(),
|
||||
assert_eq!(l.master().initialize(Default::default(), false, 0, l.nodes.keys().cloned().collect::<BTreeSet<_>>().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::<BTreeSet<_>>().into()).unwrap();
|
||||
l.master().initialize(Default::default(), false, threshold, l.nodes.keys().cloned().collect::<BTreeSet<_>>().into()).unwrap();
|
||||
assert_eq!(l.nodes.len(), num_nodes);
|
||||
|
||||
// let nodes do initialization + keys dissemination
|
||||
|
@ -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::<BTreeSet<_>>().into()).unwrap();
|
||||
gl.master().initialize(Default::default(), false, threshold, gl.nodes.keys().cloned().collect::<BTreeSet<_>>().into()).unwrap();
|
||||
while let Some((from, to, message)) = gl.take_message() {
|
||||
gl.process_message((from, to, message)).unwrap();
|
||||
}
|
||||
|
@ -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::<BTreeSet<_>>().into())?;
|
||||
generation_session.initialize(Default::default(), false, 0, vec![self.core.meta.self_node_id.clone()].into_iter().collect::<BTreeSet<_>>().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::<BTreeSet<_>>().into()).unwrap();
|
||||
gl.master().initialize(Default::default(), false, threshold, gl.nodes.keys().cloned().collect::<BTreeSet<_>>().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,
|
||||
|
@ -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());
|
||||
|
@ -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<MessageNodeId, SerializableSecret>,
|
||||
/// 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.
|
||||
|
@ -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)]
|
||||
|
@ -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<SerializablePublic>,
|
||||
/// Versions.
|
||||
pub versions: Vec<SerializableDocumentKeyShareVersionV2>}
|
||||
pub versions: Vec<SerializableDocumentKeyShareVersionV2>
|
||||
}
|
||||
|
||||
/// 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<SerializablePublic>,
|
||||
/// Encrypted point.
|
||||
pub encrypted_point: Option<SerializablePublic>,
|
||||
/// Versions.
|
||||
pub versions: Vec<SerializableDocumentKeyShareVersionV3>
|
||||
}
|
||||
|
||||
/// 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<Self, Error> {
|
||||
@ -177,7 +198,7 @@ fn upgrade_db(db: Database) -> Result<Database, Error> {
|
||||
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<Database, Error> {
|
||||
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::<SerializableDocumentKeyShareV1>(&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<Database, Error> {
|
||||
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::<SerializableDocumentKeyShareV2>(&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<DocumentKeyShare> for SerializableDocumentKeyShareV2 {
|
||||
impl From<DocumentKeyShare> 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<DocumentKeyShare> for SerializableDocumentKeyShareV2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DocumentKeyShareVersion> for SerializableDocumentKeyShareVersionV2 {
|
||||
impl From<DocumentKeyShareVersion> 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<DocumentKeyShareVersion> for SerializableDocumentKeyShareVersionV2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SerializableDocumentKeyShareV2> for DocumentKeyShare {
|
||||
fn from(key: SerializableDocumentKeyShareV2) -> Self {
|
||||
impl From<SerializableDocumentKeyShareV3> 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::<CurrentSerializableDocumentKeyShare>(&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::<Public>().unwrap()), key.common_point.clone().map(Into::into));
|
||||
assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::<Public>().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::<Public>().unwrap()), key.common_point.clone().map(Into::into));
|
||||
assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::<Public>().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::<Public>().unwrap(),
|
||||
"281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::<Secret>().unwrap(),
|
||||
)], key.versions[0].id_numbers.clone().into_iter().map(|(k, v)| (k.into(), v.into())).collect::<Vec<(Public, Secret)>>());
|
||||
|
||||
assert_eq!("00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b".parse::<Secret>().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::<H256>().unwrap().into(),
|
||||
id_numbers: vec![(
|
||||
"b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(),
|
||||
"281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::<Secret>().unwrap().into(),
|
||||
)].into_iter().collect(),
|
||||
secret_share: "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b".parse::<Secret>().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::<CurrentSerializableDocumentKeyShare>(&db.get(None, &[7]).unwrap().map(|key| key.to_vec()).unwrap()).unwrap();
|
||||
assert_eq!(777, key.threshold);
|
||||
assert_eq!(Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".parse::<Public>().unwrap()), key.common_point.clone().map(Into::into));
|
||||
assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::<Public>().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![(
|
||||
|
@ -191,6 +191,10 @@ impl Requester {
|
||||
Requester::Address(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn address(&self, server_key_id: &ServerKeyId) -> Option<ethkey::Address> {
|
||||
self.public(server_key_id).map(|p| ethkey::public_to_address(&p))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ethkey::Signature> for Requester {
|
||||
|
Loading…
Reference in New Issue
Block a user