mirror of
https://github.com/fluencelabs/trust-graph
synced 2024-12-04 23:30:19 +00:00
still wip..
This commit is contained in:
parent
0e7f22b6e0
commit
f359dc5090
@ -33,6 +33,7 @@ pub struct Certificate {
|
||||
pub chain: Vec<Trust>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CerificateError {
|
||||
DecodeError(String),
|
||||
ExpirationError {
|
||||
@ -41,7 +42,7 @@ pub enum CerificateError {
|
||||
},
|
||||
KeyInCertificateError,
|
||||
CertificateLengthError,
|
||||
|
||||
Unexpected(String)
|
||||
}
|
||||
|
||||
impl Certificate {
|
||||
|
@ -20,6 +20,13 @@ use fluence_identity::public_key::PublicKey;
|
||||
use fluence_identity::signature::Signature;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use ed25519_dalek::SignatureError;
|
||||
use crate::revoke::RevokeError::IncorrectSignature;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RevokeError {
|
||||
IncorrectSignature(SignatureError)
|
||||
}
|
||||
|
||||
/// "A document" that cancels trust created before.
|
||||
/// TODO delete pk from Revoke (it is already in a trust node)
|
||||
@ -69,13 +76,13 @@ impl Revoke {
|
||||
}
|
||||
|
||||
/// Verifies that revocation is cryptographically correct.
|
||||
pub fn verify(revoke: &Revoke) -> Result<(), String> {
|
||||
pub fn verify(revoke: &Revoke) -> Result<(), RevokeError> {
|
||||
let msg = Revoke::signature_bytes(&revoke.pk, revoke.revoked_at);
|
||||
|
||||
revoke
|
||||
.revoked_by
|
||||
.verify_strict(msg.as_slice(), &revoke.signature)
|
||||
.map_err(|err| format!("Revoke has incorrect signature: {:?}", err))
|
||||
.map_err(|err| IncorrectSignature(err))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,11 @@ use fluence_identity::public_key::PublicKey;
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
use std::time::Duration;
|
||||
use crate::trust_graph::TrustGraphError::{InternalStorageError, CertificateCheckError};
|
||||
use crate::trust_graph::TrustGraphError::{InternalStorageError, CertificateCheckError, NoRoot, RevokeCheckError};
|
||||
use crate::certificate::CerificateError::{CertificateLengthError, Unexpected};
|
||||
use crate::revoke::RevokeError;
|
||||
use std::convert::{From, Into};
|
||||
use std::result::Result;
|
||||
|
||||
/// for simplicity, we store `n` where Weight = 1/n^2
|
||||
pub type Weight = u32;
|
||||
@ -37,14 +41,23 @@ pub struct TrustGraph<S> where S: Storage {
|
||||
storage: Box<S>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TrustGraphError {
|
||||
InternalStorageError(String),
|
||||
CertificateCheckError(CerificateError)
|
||||
NoRoot,
|
||||
CertificateCheckError(CerificateError),
|
||||
RevokeCheckError(RevokeError),
|
||||
}
|
||||
|
||||
impl Into<TrustGraphError> for CerificateError {
|
||||
fn into(self) -> TrustGraphError {
|
||||
CertificateCheckError(self)
|
||||
impl From<CerificateError> for TrustGraphError {
|
||||
fn from(err: CerificateError) -> Self {
|
||||
CertificateCheckError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RevokeError> for TrustGraphError {
|
||||
fn from(err: RevokeError) -> Self {
|
||||
RevokeCheckError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +92,7 @@ impl<S> TrustGraph<S> where S: Storage {
|
||||
.map(Into::into)
|
||||
.collect();
|
||||
// Check that certificate is valid and converges to one of the known roots
|
||||
Certificate::verify(cert.borrow(), roots.as_slice(), cur_time).map_err(|e| e.into())?;
|
||||
Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?;
|
||||
|
||||
let mut chain = cert.borrow().chain.iter();
|
||||
let root_trust = chain.next().ok_or("empty chain").map_err(|e| InternalStorageError(e.into()))?;
|
||||
@ -133,7 +146,7 @@ impl<S> TrustGraph<S> where S: Storage {
|
||||
.collect();
|
||||
|
||||
// get all possible certificates from the given public key to all roots in the graph
|
||||
let certs = self.get_all_certs(pk, roots.as_slice());
|
||||
let certs = self.get_all_certs(pk, roots.as_slice())?;
|
||||
Ok(self.certificates_weight(certs)?)
|
||||
}
|
||||
|
||||
@ -156,17 +169,19 @@ impl<S> TrustGraph<S> where S: Storage {
|
||||
let mut weight = std::u32::MAX;
|
||||
|
||||
for cert in certs {
|
||||
let cert = cert.borrow();
|
||||
let c = cert.borrow();
|
||||
|
||||
let first = c.chain.first().ok_or(CertificateCheckError(CertificateLengthError))?;
|
||||
|
||||
let root_weight = self
|
||||
.storage
|
||||
.get_root_weight(cert.chain.first()?.issued_for.as_ref())
|
||||
.get_root_weight(first.issued_for.as_ref())
|
||||
// This panic shouldn't happen // TODO: why?
|
||||
.map_err(|e| InternalStorageError(e.into()))?;
|
||||
.map_err(|e| InternalStorageError(e.into()))?.ok_or(NoRoot)?;
|
||||
|
||||
// certificate weight = root weight + 1 * every other element in the chain
|
||||
// (except root, so the formula is `root weight + chain length - 1`)
|
||||
weight = std::cmp::min(weight, root_weight + cert.chain.len() as u32 - 1)
|
||||
weight = std::cmp::min(weight, root_weight + c.chain.len() as u32 - 1)
|
||||
}
|
||||
|
||||
Ok(Some(weight))
|
||||
@ -179,7 +194,7 @@ impl<S> TrustGraph<S> where S: Storage {
|
||||
&self,
|
||||
node: &TrustNode,
|
||||
roots: HashSet<&PublicKeyHashable>,
|
||||
) -> Vec<Vec<Auth>> {
|
||||
) -> Result<Vec<Vec<Auth>>, TrustGraphError> {
|
||||
// queue to collect all chains in the trust graph (each chain is a path in the trust graph)
|
||||
let mut chains_queue: VecDeque<Vec<Auth>> = VecDeque::new();
|
||||
|
||||
@ -204,9 +219,10 @@ impl<S> TrustGraph<S> where S: Storage {
|
||||
let auths: Vec<Auth> = self
|
||||
.storage
|
||||
.get(&last.issued_by.clone().into())
|
||||
.expect(
|
||||
"there cannot be paths without any nodes after adding verified certificates",
|
||||
)
|
||||
.map_err(|e| InternalStorageError(e.into()))?
|
||||
.ok_or(
|
||||
CertificateCheckError(Unexpected("there cannot be paths without any nodes after adding verified certificates".to_string())),
|
||||
)?
|
||||
.authorizations()
|
||||
.cloned()
|
||||
.collect();
|
||||
@ -236,26 +252,26 @@ impl<S> TrustGraph<S> where S: Storage {
|
||||
}
|
||||
}
|
||||
|
||||
terminated_chains
|
||||
Ok(terminated_chains)
|
||||
}
|
||||
|
||||
// TODO: remove `roots` argument from api, leave it for tests and internal usage only
|
||||
/// Get all possible certificates where `issued_for` will be the last element of the chain
|
||||
/// and one of the destinations is the root of this chain.
|
||||
pub fn get_all_certs<P>(&self, issued_for: P, roots: &[PublicKey]) -> Vec<Certificate>
|
||||
pub fn get_all_certs<P>(&self, issued_for: P, roots: &[PublicKey]) -> Result<Vec<Certificate>, TrustGraphError>
|
||||
where
|
||||
P: Borrow<PublicKey>,
|
||||
{
|
||||
// get all auths (edges) for issued public key
|
||||
let issued_for_node = self.storage.get(issued_for.borrow().as_ref());
|
||||
let issued_for_node = self.storage.get(issued_for.borrow().as_ref()).map_err(|e| InternalStorageError(e.into()))?;
|
||||
|
||||
let roots = roots.iter().map(|pk| pk.as_ref());
|
||||
let keys = self.storage.root_keys();
|
||||
let keys = self.storage.root_keys().map_err(|e| InternalStorageError(e.into()))?;
|
||||
let roots = keys.iter().chain(roots).collect();
|
||||
|
||||
match issued_for_node {
|
||||
Some(node) => self
|
||||
.bf_search_paths(&node, roots)
|
||||
Some(node) => Ok(self
|
||||
.bf_search_paths(&node, roots)?
|
||||
.iter()
|
||||
.map(|auths| {
|
||||
// TODO: can avoid cloning here by returning &Certificate
|
||||
@ -272,18 +288,18 @@ impl<S> TrustGraph<S> where S: Storage {
|
||||
);
|
||||
c.chain.len() > 1
|
||||
})
|
||||
.collect(),
|
||||
None => Vec::new(),
|
||||
.collect()),
|
||||
None => Ok(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark public key as revoked.
|
||||
pub fn revoke(&mut self, revoke: Revoke) -> Result<(), String> {
|
||||
pub fn revoke(&mut self, revoke: Revoke) -> Result<(), TrustGraphError> {
|
||||
Revoke::verify(&revoke)?;
|
||||
|
||||
let pk: PublicKeyHashable = revoke.pk.clone().into();
|
||||
|
||||
self.storage.revoke(&pk, revoke)
|
||||
self.storage.revoke(&pk, revoke).map_err(|e| InternalStorageError(e.into()))
|
||||
}
|
||||
|
||||
/// Check information about new certificates and about revoked certificates.
|
||||
@ -329,7 +345,7 @@ mod tests {
|
||||
keys: HashMap<usize, KeyPair>,
|
||||
expires_at: Duration,
|
||||
issued_at: Duration,
|
||||
) -> (Vec<KeyPair>, Certificate) {
|
||||
) -> Result<(Vec<KeyPair>, Certificate), TrustGraphError> {
|
||||
assert!(len > 2);
|
||||
|
||||
let root_kp = KeyPair::generate();
|
||||
@ -351,18 +367,17 @@ mod tests {
|
||||
// TODO: why `issued_at = issued_at - 60 seconds`?
|
||||
issued_at.checked_sub(Duration::from_secs(60)).unwrap(),
|
||||
current_time(),
|
||||
)
|
||||
.unwrap();
|
||||
)?;
|
||||
key_pairs.push(kp);
|
||||
}
|
||||
|
||||
(key_pairs, cert)
|
||||
Ok((key_pairs, cert))
|
||||
}
|
||||
|
||||
fn generate_cert_with_len(
|
||||
len: usize,
|
||||
keys: HashMap<usize, KeyPair>,
|
||||
) -> (Vec<KeyPair>, Certificate) {
|
||||
) -> Result<(Vec<KeyPair>, Certificate), TrustGraphError> {
|
||||
let cur_time = current_time();
|
||||
let far_future = cur_time.checked_add(one_minute()).unwrap();
|
||||
|
||||
@ -406,7 +421,7 @@ mod tests {
|
||||
chain_keys.insert(5, key_pair1.clone());
|
||||
chain_keys.insert(6, key_pair2.clone());
|
||||
|
||||
let (key_pairs1, cert1) = generate_cert_with(10, chain_keys, far_future * 2, far_future);
|
||||
let (key_pairs1, cert1) = generate_cert_with(10, chain_keys, far_future * 2, far_future).expect("");
|
||||
|
||||
// Use key_pair1 and key_pair2 for 7th and 8th trust in the cert chain
|
||||
let mut chain_keys = HashMap::new();
|
||||
@ -414,7 +429,7 @@ mod tests {
|
||||
chain_keys.insert(8, key_pair2.clone());
|
||||
|
||||
let (key_pairs2, cert2) =
|
||||
generate_cert_with(10, chain_keys, far_far_future * 2, far_far_future);
|
||||
generate_cert_with(10, chain_keys, far_far_future * 2, far_far_future).unwrap();
|
||||
|
||||
let st = Box::new(InMemoryStorage::new());
|
||||
let mut graph = TrustGraph::new(st);
|
||||
@ -424,7 +439,7 @@ mod tests {
|
||||
graph.add_root_weight(root2_pk.into(), 0);
|
||||
graph.add(cert1, cur_time).unwrap();
|
||||
|
||||
let node2 = graph.get(key_pair2.public_key()).unwrap();
|
||||
let node2 = graph.get(key_pair2.public_key()).unwrap().unwrap();
|
||||
let auth_by_kp1 = node2
|
||||
.authorizations()
|
||||
.find(|a| a.issued_by == key_pair1.public_key())
|
||||
@ -434,7 +449,7 @@ mod tests {
|
||||
|
||||
graph.add(cert2, cur_time).unwrap();
|
||||
|
||||
let node2 = graph.get(key_pair2.public_key()).unwrap();
|
||||
let node2 = graph.get(key_pair2.public_key()).unwrap().unwrap();
|
||||
let auth_by_kp1 = node2
|
||||
.authorizations()
|
||||
.find(|a| a.issued_by == key_pair1.public_key())
|
||||
@ -445,7 +460,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_one_cert_in_graph() {
|
||||
let (key_pairs, cert1) = generate_cert_with_len(10, HashMap::new());
|
||||
let (key_pairs, cert1) = generate_cert_with_len(10, HashMap::new()).unwrap();
|
||||
let last_trust = cert1.chain[9].clone();
|
||||
|
||||
let st = Box::new(InMemoryStorage::new());
|
||||
@ -456,16 +471,16 @@ mod tests {
|
||||
|
||||
graph.add(cert1, current_time()).unwrap();
|
||||
|
||||
let w1 = graph.weight(key_pairs[0].public_key()).unwrap();
|
||||
let w1 = graph.weight(key_pairs[0].public_key()).unwrap().unwrap();
|
||||
assert_eq!(w1, 1);
|
||||
|
||||
let w2 = graph.weight(key_pairs[1].public_key()).unwrap();
|
||||
let w2 = graph.weight(key_pairs[1].public_key()).unwrap().unwrap();
|
||||
assert_eq!(w2, 2);
|
||||
|
||||
let w3 = graph.weight(key_pairs[9].public_key()).unwrap();
|
||||
let w3 = graph.weight(key_pairs[9].public_key()).unwrap().unwrap();
|
||||
assert_eq!(w3, 10);
|
||||
|
||||
let node = graph.get(key_pairs[9].public_key()).unwrap();
|
||||
let node = graph.get(key_pairs[9].public_key()).unwrap().unwrap();
|
||||
let auths: Vec<&Auth> = node.authorizations().collect();
|
||||
|
||||
assert_eq!(auths.len(), 1);
|
||||
@ -483,14 +498,14 @@ mod tests {
|
||||
chain_keys.insert(5, key_pair2.clone());
|
||||
chain_keys.insert(7, key_pair3.clone());
|
||||
|
||||
let (key_pairs1, cert1) = generate_cert_with_len(10, chain_keys);
|
||||
let (key_pairs1, cert1) = generate_cert_with_len(10, chain_keys).unwrap();
|
||||
|
||||
let mut chain_keys = HashMap::new();
|
||||
chain_keys.insert(7, key_pair1.clone());
|
||||
chain_keys.insert(6, key_pair2.clone());
|
||||
chain_keys.insert(5, key_pair3.clone());
|
||||
|
||||
let (key_pairs2, cert2) = generate_cert_with_len(10, chain_keys);
|
||||
let (key_pairs2, cert2) = generate_cert_with_len(10, chain_keys).unwrap();
|
||||
|
||||
let st = Box::new(InMemoryStorage::new());
|
||||
let mut graph = TrustGraph::new(st);
|
||||
@ -510,12 +525,12 @@ mod tests {
|
||||
let revoke2 = Revoke::create(&key_pairs2[5], key_pairs2[6].public_key(), current_time());
|
||||
graph.revoke(revoke2).unwrap();
|
||||
|
||||
let w1 = graph.weight(key_pair1.public_key()).unwrap();
|
||||
let w1 = graph.weight(key_pair1.public_key()).unwrap().unwrap();
|
||||
// all upper trusts are revoked for this public key
|
||||
let w2 = graph.weight(key_pair2.public_key());
|
||||
let w3 = graph.weight(key_pair3.public_key()).unwrap();
|
||||
let w_last1 = graph.weight(last_pk1).unwrap();
|
||||
let w_last2 = graph.weight(last_pk2).unwrap();
|
||||
let w2 = graph.weight(key_pair2.public_key()).unwrap();
|
||||
let w3 = graph.weight(key_pair3.public_key()).unwrap().unwrap();
|
||||
let w_last1 = graph.weight(last_pk1).unwrap().unwrap();
|
||||
let w_last2 = graph.weight(last_pk2).unwrap().unwrap();
|
||||
|
||||
assert_eq!(w1, 4);
|
||||
assert_eq!(w2.is_none(), true);
|
||||
@ -526,7 +541,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_one_cert() {
|
||||
let (key_pairs, cert) = generate_cert_with_len(5, HashMap::new());
|
||||
let (key_pairs, cert) = generate_cert_with_len(5, HashMap::new()).unwrap();
|
||||
|
||||
let st = Box::new(InMemoryStorage::new());
|
||||
let mut graph = TrustGraph::new(st);
|
||||
@ -535,7 +550,7 @@ mod tests {
|
||||
|
||||
graph.add(cert.clone(), current_time()).unwrap();
|
||||
|
||||
let certs = graph.get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk]);
|
||||
let certs = graph.get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk]).unwrap();
|
||||
|
||||
assert_eq!(certs.len(), 1);
|
||||
assert_eq!(certs[0], cert);
|
||||
@ -543,7 +558,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_chain_from_root_to_another_root() {
|
||||
let (_, cert) = generate_cert_with_len(6, HashMap::new());
|
||||
let (_, cert) = generate_cert_with_len(6, HashMap::new()).unwrap();
|
||||
|
||||
let st = Box::new(InMemoryStorage::new());
|
||||
let mut graph = TrustGraph::new(st);
|
||||
@ -555,7 +570,7 @@ mod tests {
|
||||
graph.add(cert.clone(), current_time()).unwrap();
|
||||
|
||||
let t = cert.chain[5].clone();
|
||||
let certs = graph.get_all_certs(t.issued_for, &[]);
|
||||
let certs = graph.get_all_certs(t.issued_for, &[]).unwrap();
|
||||
|
||||
assert_eq!(certs.len(), 1);
|
||||
}
|
||||
@ -571,21 +586,21 @@ mod tests {
|
||||
chain_keys.insert(3, key_pair2.clone());
|
||||
chain_keys.insert(4, key_pair3.clone());
|
||||
|
||||
let (key_pairs1, cert1) = generate_cert_with_len(5, chain_keys);
|
||||
let (key_pairs1, cert1) = generate_cert_with_len(5, chain_keys).unwrap();
|
||||
|
||||
let mut chain_keys = HashMap::new();
|
||||
chain_keys.insert(4, key_pair1.clone());
|
||||
chain_keys.insert(3, key_pair2.clone());
|
||||
chain_keys.insert(2, key_pair3.clone());
|
||||
|
||||
let (key_pairs2, cert2) = generate_cert_with_len(5, chain_keys);
|
||||
let (key_pairs2, cert2) = generate_cert_with_len(5, chain_keys).unwrap();
|
||||
|
||||
let mut chain_keys = HashMap::new();
|
||||
chain_keys.insert(3, key_pair1.clone());
|
||||
chain_keys.insert(4, key_pair2.clone());
|
||||
chain_keys.insert(2, key_pair3.clone());
|
||||
|
||||
let (key_pairs3, cert3) = generate_cert_with_len(5, chain_keys);
|
||||
let (key_pairs3, cert3) = generate_cert_with_len(5, chain_keys).unwrap();
|
||||
|
||||
let st = Box::new(InMemoryStorage::new());
|
||||
let mut graph = TrustGraph::new(st);
|
||||
@ -602,17 +617,17 @@ mod tests {
|
||||
|
||||
let roots_values = [root1_pk, root2_pk, root3_pk];
|
||||
|
||||
let certs1 = graph.get_all_certs(key_pair1.public_key(), &roots_values);
|
||||
let certs1 = graph.get_all_certs(key_pair1.public_key(), &roots_values).unwrap();
|
||||
let lenghts1: Vec<usize> = certs1.iter().map(|c| c.chain.len()).collect();
|
||||
let check_lenghts1: Vec<usize> = vec![3, 4, 4, 5, 5];
|
||||
assert_eq!(lenghts1, check_lenghts1);
|
||||
|
||||
let certs2 = graph.get_all_certs(key_pair2.public_key(), &roots_values);
|
||||
let certs2 = graph.get_all_certs(key_pair2.public_key(), &roots_values).unwrap();
|
||||
let lenghts2: Vec<usize> = certs2.iter().map(|c| c.chain.len()).collect();
|
||||
let check_lenghts2: Vec<usize> = vec![4, 4, 4, 5, 5];
|
||||
assert_eq!(lenghts2, check_lenghts2);
|
||||
|
||||
let certs3 = graph.get_all_certs(key_pair3.public_key(), &roots_values);
|
||||
let certs3 = graph.get_all_certs(key_pair3.public_key(), &roots_values).unwrap();
|
||||
let lenghts3: Vec<usize> = certs3.iter().map(|c| c.chain.len()).collect();
|
||||
let check_lenghts3: Vec<usize> = vec![3, 3, 5];
|
||||
assert_eq!(lenghts3, check_lenghts3);
|
||||
|
Loading…
Reference in New Issue
Block a user