Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit 305fea6

Browse files
svyatonikdvdplm
authored andcommitted
SecretStore: expose restore_key_public in HTTP API (#10241)
1 parent 993bd17 commit 305fea6

File tree

10 files changed

+194
-69
lines changed

10 files changed

+194
-69
lines changed

ethcore/res/ethereum/tests

Submodule tests updated from 725dbc7 to d4f86ec

secret-store/src/key_server.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,22 @@ impl ServerKeyGenerator for KeyServerImpl {
7878
.expect("when wait is called without timeout it always returns Some; qed")
7979
.map_err(Into::into)
8080
}
81+
82+
fn restore_key_public(&self, key_id: &ServerKeyId, author: &Requester) -> Result<Public, Error> {
83+
// recover requestor' public key from signature
84+
let address = author.address(key_id).map_err(Error::InsufficientRequesterData)?;
85+
86+
// negotiate key version && retrieve common key data
87+
let negotiation_session = self.data.lock().cluster.new_key_version_negotiation_session(*key_id)?;
88+
negotiation_session.wait()
89+
.and_then(|_| negotiation_session.common_key_data())
90+
.and_then(|key_share| if key_share.author == address {
91+
Ok(key_share.public)
92+
} else {
93+
Err(Error::AccessDenied)
94+
})
95+
.map_err(Into::into)
96+
}
8197
}
8298

8399
impl DocumentKeyServer for KeyServerImpl {
@@ -237,6 +253,10 @@ pub mod tests {
237253
fn generate_key(&self, _key_id: &ServerKeyId, _author: &Requester, _threshold: usize) -> Result<Public, Error> {
238254
unimplemented!("test-only")
239255
}
256+
257+
fn restore_key_public(&self, _key_id: &ServerKeyId, _author: &Requester) -> Result<Public, Error> {
258+
unimplemented!("test-only")
259+
}
240260
}
241261

242262
impl DocumentKeyServer for DummyKeyServer {

secret-store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs

Lines changed: 119 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use key_server_cluster::decryption_session::SessionImpl as DecryptionSession;
2626
use key_server_cluster::signing_session_ecdsa::SessionImpl as EcdsaSigningSession;
2727
use key_server_cluster::signing_session_schnorr::SessionImpl as SchnorrSigningSession;
2828
use key_server_cluster::message::{Message, KeyVersionNegotiationMessage, RequestKeyVersions,
29-
KeyVersions, KeyVersionsError, FailedKeyVersionContinueAction};
29+
KeyVersions, KeyVersionsError, FailedKeyVersionContinueAction, CommonKeyData};
3030
use key_server_cluster::admin_sessions::ShareChangeSessionMeta;
3131

3232
// TODO [Opt]: change sessions so that versions are sent by chunks.
@@ -97,8 +97,8 @@ struct SessionData {
9797
pub state: SessionState,
9898
/// Initialization confirmations.
9999
pub confirmations: Option<BTreeSet<NodeId>>,
100-
/// Key threshold.
101-
pub threshold: Option<usize>,
100+
/// Common key data that nodes have agreed upon.
101+
pub key_share: Option<DocumentKeyShare>,
102102
/// { Version => Nodes }
103103
pub versions: Option<BTreeMap<H256, BTreeSet<NodeId>>>,
104104
/// Session result.
@@ -167,12 +167,11 @@ pub struct LargestSupportResultComputer;
167167
impl<T> SessionImpl<T> where T: SessionTransport {
168168
/// Create new session.
169169
pub fn new(params: SessionParams<T>) -> Self {
170-
let threshold = params.key_share.as_ref().map(|key_share| key_share.threshold);
171170
SessionImpl {
172171
core: SessionCore {
173172
meta: params.meta,
174173
sub_session: params.sub_session,
175-
key_share: params.key_share,
174+
key_share: params.key_share.clone(),
176175
result_computer: params.result_computer,
177176
transport: params.transport,
178177
nonce: params.nonce,
@@ -181,7 +180,12 @@ impl<T> SessionImpl<T> where T: SessionTransport {
181180
data: Mutex::new(SessionData {
182181
state: SessionState::WaitingForInitialization,
183182
confirmations: None,
184-
threshold: threshold,
183+
key_share: params.key_share.map(|key_share| DocumentKeyShare {
184+
threshold: key_share.threshold,
185+
author: key_share.author,
186+
public: key_share.public,
187+
..Default::default()
188+
}),
185189
versions: None,
186190
result: None,
187191
continue_with: None,
@@ -195,12 +199,6 @@ impl<T> SessionImpl<T> where T: SessionTransport {
195199
&self.core.meta
196200
}
197201

198-
/// Return key threshold.
199-
pub fn key_threshold(&self) -> Result<usize, Error> {
200-
self.data.lock().threshold.clone()
201-
.ok_or(Error::InvalidStateForRequest)
202-
}
203-
204202
/// Return result computer reference.
205203
pub fn version_holders(&self, version: &H256) -> Result<BTreeSet<NodeId>, Error> {
206204
Ok(self.data.lock().versions.as_ref().ok_or(Error::InvalidStateForRequest)?
@@ -229,6 +227,12 @@ impl<T> SessionImpl<T> where T: SessionTransport {
229227
.expect("wait_session returns Some if called without timeout; qed")
230228
}
231229

230+
/// Retrieve common key data (author, threshold, public), if available.
231+
pub fn common_key_data(&self) -> Result<DocumentKeyShare, Error> {
232+
self.data.lock().key_share.clone()
233+
.ok_or(Error::InvalidStateForRequest)
234+
}
235+
232236
/// Initialize session.
233237
pub fn initialize(&self, connected_nodes: BTreeSet<NodeId>) -> Result<(), Error> {
234238
// check state
@@ -322,7 +326,11 @@ impl<T> SessionImpl<T> where T: SessionTransport {
322326
session: self.core.meta.id.clone().into(),
323327
sub_session: self.core.sub_session.clone().into(),
324328
session_nonce: self.core.nonce,
325-
threshold: self.core.key_share.as_ref().map(|key_share| key_share.threshold),
329+
key_common: self.core.key_share.as_ref().map(|key_share| CommonKeyData {
330+
threshold: key_share.threshold,
331+
author: key_share.author.into(),
332+
public: key_share.public.into(),
333+
}),
326334
versions: self.core.key_share.as_ref().map(|key_share|
327335
key_share.versions.iter().rev()
328336
.filter(|v| v.id_numbers.contains_key(sender))
@@ -357,12 +365,25 @@ impl<T> SessionImpl<T> where T: SessionTransport {
357365

358366
// remember versions that sender have
359367
{
360-
match message.threshold.clone() {
361-
Some(threshold) if data.threshold.is_none() => {
362-
data.threshold = Some(threshold);
368+
match message.key_common.as_ref() {
369+
Some(key_common) if data.key_share.is_none() => {
370+
data.key_share = Some(DocumentKeyShare {
371+
threshold: key_common.threshold,
372+
author: key_common.author.clone().into(),
373+
public: key_common.public.clone().into(),
374+
..Default::default()
375+
});
376+
},
377+
Some(key_common) => {
378+
let prev_key_share = data.key_share.as_ref()
379+
.expect("data.key_share.is_none() is matched by previous branch; qed");
380+
if prev_key_share.threshold != key_common.threshold ||
381+
prev_key_share.author.as_bytes() != key_common.author.as_bytes() ||
382+
prev_key_share.public.as_bytes() != key_common.public.as_bytes()
383+
{
384+
return Err(Error::InvalidMessage);
385+
}
363386
},
364-
Some(threshold) if data.threshold.as_ref() == Some(&threshold) => (),
365-
Some(_) => return Err(Error::InvalidMessage),
366387
None if message.versions.is_empty() => (),
367388
None => return Err(Error::InvalidMessage),
368389
}
@@ -388,7 +409,8 @@ impl<T> SessionImpl<T> where T: SessionTransport {
388409
let reason = "this field is filled on master node when initializing; try_complete is only called on initialized master node; qed";
389410
let confirmations = data.confirmations.as_ref().expect(reason);
390411
let versions = data.versions.as_ref().expect(reason);
391-
if let Some(result) = core.result_computer.compute_result(data.threshold.clone(), confirmations, versions) {
412+
let threshold = data.key_share.as_ref().map(|key_share| key_share.threshold);
413+
if let Some(result) = core.result_computer.compute_result(threshold, confirmations, versions) {
392414
// when the master node processing decryption service request, it starts with a key version negotiation session
393415
// if the negotiation fails, only master node knows about it
394416
// => if the error is fatal, only the master will know about it and report it to the contract && the request will never be rejected
@@ -590,6 +612,7 @@ impl SessionResultComputer for LargestSupportResultComputer {
590612
mod tests {
591613
use std::sync::Arc;
592614
use std::collections::{VecDeque, BTreeMap, BTreeSet};
615+
use ethereum_types::{H512, H160, Address};
593616
use ethkey::public_to_address;
594617
use key_server_cluster::{NodeId, SessionId, Error, KeyStorage, DummyKeyStorage,
595618
DocumentKeyShare, DocumentKeyShareVersion};
@@ -599,9 +622,14 @@ mod tests {
599622
use key_server_cluster::cluster_sessions::ClusterSession;
600623
use key_server_cluster::admin_sessions::ShareChangeSessionMeta;
601624
use key_server_cluster::decryption_session::create_default_decryption_session;
602-
use key_server_cluster::message::{Message, KeyVersionNegotiationMessage, RequestKeyVersions, KeyVersions};
603-
use super::{SessionImpl, SessionTransport, SessionParams, FastestResultComputer, LargestSupportResultComputer,
604-
SessionResultComputer, SessionState, ContinueAction, FailedContinueAction};
625+
use key_server_cluster::message::{
626+
Message, KeyVersionNegotiationMessage, RequestKeyVersions,
627+
CommonKeyData, KeyVersions,
628+
};
629+
use super::{
630+
SessionImpl, SessionTransport, SessionParams, FastestResultComputer, LargestSupportResultComputer,
631+
SessionResultComputer, SessionState, ContinueAction, FailedContinueAction,
632+
};
605633

606634
struct DummyTransport {
607635
cluster: Arc<DummyCluster>,
@@ -756,7 +784,11 @@ mod tests {
756784
session: Default::default(),
757785
sub_session: math::generate_random_scalar().unwrap().into(),
758786
session_nonce: 0,
759-
threshold: Some(10),
787+
key_common: Some(CommonKeyData {
788+
threshold: 10,
789+
author: Default::default(),
790+
public: Default::default(),
791+
}),
760792
versions: Vec::new(),
761793
})), Err(Error::InvalidStateForRequest));
762794
}
@@ -772,7 +804,12 @@ mod tests {
772804
session: Default::default(),
773805
sub_session: math::generate_random_scalar().unwrap().into(),
774806
session_nonce: 0,
775-
threshold: Some(0),
807+
key_common: Some(CommonKeyData {
808+
threshold: 0,
809+
author: Default::default(),
810+
public: Default::default(),
811+
}),
812+
776813
versions: vec![version_id.clone().into()]
777814
})), Ok(()));
778815
assert_eq!(ml.session(0).data.lock().state, SessionState::Finished);
@@ -781,32 +818,61 @@ mod tests {
781818
session: Default::default(),
782819
sub_session: math::generate_random_scalar().unwrap().into(),
783820
session_nonce: 0,
784-
threshold: Some(0),
821+
key_common: Some(CommonKeyData {
822+
threshold: 0,
823+
author: Default::default(),
824+
public: Default::default(),
825+
}),
826+
785827
versions: vec![version_id.clone().into()]
786828
})), Ok(()));
787829
assert_eq!(ml.session(0).data.lock().state, SessionState::Finished);
788830
}
789831

790832
#[test]
791-
fn negotiation_fails_if_wrong_threshold_sent() {
792-
let ml = MessageLoop::empty(3);
793-
ml.session(0).initialize(ml.nodes.keys().cloned().collect()).unwrap();
833+
fn negotiation_fails_if_wrong_common_data_sent() {
834+
fn run_test(key_common: CommonKeyData) {
835+
let ml = MessageLoop::empty(3);
836+
ml.session(0).initialize(ml.nodes.keys().cloned().collect()).unwrap();
837+
838+
let version_id = (*math::generate_random_scalar().unwrap()).clone();
839+
assert_eq!(ml.session(0).process_message(ml.node_id(1), &KeyVersionNegotiationMessage::KeyVersions(KeyVersions {
840+
session: Default::default(),
841+
sub_session: math::generate_random_scalar().unwrap().into(),
842+
session_nonce: 0,
843+
key_common: Some(CommonKeyData {
844+
threshold: 1,
845+
author: Default::default(),
846+
public: Default::default(),
847+
}),
848+
versions: vec![version_id.clone().into()]
849+
})), Ok(()));
850+
assert_eq!(ml.session(0).process_message(ml.node_id(2), &KeyVersionNegotiationMessage::KeyVersions(KeyVersions {
851+
session: Default::default(),
852+
sub_session: math::generate_random_scalar().unwrap().into(),
853+
session_nonce: 0,
854+
key_common: Some(key_common),
855+
versions: vec![version_id.clone().into()]
856+
})), Err(Error::InvalidMessage));
857+
}
858+
859+
run_test(CommonKeyData {
860+
threshold: 2,
861+
author: Default::default(),
862+
public: Default::default(),
863+
});
794864

795-
let version_id = (*math::generate_random_scalar().unwrap()).clone();
796-
assert_eq!(ml.session(0).process_message(ml.node_id(1), &KeyVersionNegotiationMessage::KeyVersions(KeyVersions {
797-
session: Default::default(),
798-
sub_session: math::generate_random_scalar().unwrap().into(),
799-
session_nonce: 0,
800-
threshold: Some(1),
801-
versions: vec![version_id.clone().into()]
802-
})), Ok(()));
803-
assert_eq!(ml.session(0).process_message(ml.node_id(2), &KeyVersionNegotiationMessage::KeyVersions(KeyVersions {
804-
session: Default::default(),
805-
sub_session: math::generate_random_scalar().unwrap().into(),
806-
session_nonce: 0,
807-
threshold: Some(2),
808-
versions: vec![version_id.clone().into()]
809-
})), Err(Error::InvalidMessage));
865+
run_test(CommonKeyData {
866+
threshold: 1,
867+
author: H160::from_low_u64_be(1).into(),
868+
public: Default::default(),
869+
});
870+
871+
run_test(CommonKeyData {
872+
threshold: 1,
873+
author: H160::from_low_u64_be(2).into(),
874+
public: Default::default(),
875+
});
810876
}
811877

812878
#[test]
@@ -819,7 +885,7 @@ mod tests {
819885
session: Default::default(),
820886
sub_session: math::generate_random_scalar().unwrap().into(),
821887
session_nonce: 0,
822-
threshold: None,
888+
key_common: None,
823889
versions: vec![version_id.clone().into()]
824890
})), Err(Error::InvalidMessage));
825891
}
@@ -829,9 +895,9 @@ mod tests {
829895
let nodes = MessageLoop::prepare_nodes(2);
830896
let version_id = (*math::generate_random_scalar().unwrap()).clone();
831897
nodes.values().nth(0).unwrap().insert(Default::default(), DocumentKeyShare {
832-
author: Default::default(),
898+
author: H160::from_low_u64_be(2),
833899
threshold: 1,
834-
public: Default::default(),
900+
public: H512::from_low_u64_be(3),
835901
common_point: None,
836902
encrypted_point: None,
837903
versions: vec![DocumentKeyShareVersion {
@@ -845,8 +911,13 @@ mod tests {
845911
// we can't be sure that node has given key version because previous ShareAdd session could fail
846912
assert!(ml.session(0).data.lock().state != SessionState::Finished);
847913

848-
// check that upon completion, threshold is known
849-
assert_eq!(ml.session(0).key_threshold(), Ok(1));
914+
// check that upon completion, commmon key data is known
915+
assert_eq!(ml.session(0).common_key_data(), Ok(DocumentKeyShare {
916+
author: H160::from_low_u64_be(2),
917+
threshold: 1,
918+
public: H512::from_low_u64_be(3),
919+
..Default::default()
920+
}));
850921
}
851922

852923
#[test]

secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ impl SessionImpl {
800800
.wait()?
801801
.expect("initialize_share_change_session is only called on share change master; negotiation session completes with some on master; qed");
802802
let selected_version_holders = negotiation_session.version_holders(&selected_version)?;
803-
let selected_version_threshold = negotiation_session.key_threshold()?;
803+
let selected_version_threshold = negotiation_session.common_key_data()?.threshold;
804804

805805
// prepare session change plan && check if something needs to be changed
806806
let old_nodes_set = selected_version_holders;

secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use key_server_cluster::cluster_sessions::ClusterSession;
2525
use key_server_cluster::math;
2626
use key_server_cluster::message::{Message, ShareAddMessage, ShareAddConsensusMessage, ConsensusMessageOfShareAdd,
2727
InitializeConsensusSessionOfShareAdd, KeyShareCommon, NewKeysDissemination, ShareAddError,
28-
ConfirmConsensusInitialization};
28+
ConfirmConsensusInitialization, CommonKeyData};
2929
use key_server_cluster::jobs::job_session::JobTransport;
3030
use key_server_cluster::jobs::dummy_job::{DummyJob, DummyJobTransport};
3131
use key_server_cluster::jobs::servers_set_change_access_job::{ServersSetChangeAccessJob, ServersSetChangeAccessRequest};
@@ -469,9 +469,9 @@ impl<T> SessionImpl<T> where T: SessionTransport {
469469
// update data
470470
data.state = SessionState::WaitingForKeysDissemination;
471471
data.new_key_share = Some(NewKeyShare {
472-
threshold: message.threshold,
473-
author: message.author.clone().into(),
474-
joint_public: message.joint_public.clone().into(),
472+
threshold: message.key_common.threshold,
473+
author: message.key_common.author.clone().into(),
474+
joint_public: message.key_common.public.clone().into(),
475475
common_point: message.common_point.clone().map(Into::into),
476476
encrypted_point: message.encrypted_point.clone().map(Into::into),
477477
});
@@ -645,9 +645,11 @@ impl<T> SessionImpl<T> where T: SessionTransport {
645645
core.transport.send(new_node, ShareAddMessage::KeyShareCommon(KeyShareCommon {
646646
session: core.meta.id.clone().into(),
647647
session_nonce: core.nonce,
648-
threshold: old_key_share.threshold,
649-
author: old_key_share.author.clone().into(),
650-
joint_public: old_key_share.public.clone().into(),
648+
key_common: CommonKeyData {
649+
threshold: old_key_share.threshold,
650+
author: old_key_share.author.into(),
651+
public: old_key_share.public.into(),
652+
},
651653
common_point: old_key_share.common_point.clone().map(Into::into),
652654
encrypted_point: old_key_share.encrypted_point.clone().map(Into::into),
653655
id_numbers: old_key_version.id_numbers.iter()

0 commit comments

Comments
 (0)