mirror of
https://github.com/fluencelabs/trust-graph
synced 2024-12-04 23:30:19 +00:00
huge mess with errors, but it works!
This commit is contained in:
parent
f359dc5090
commit
e2183b4180
@ -14,11 +14,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use crate::certificate::CerificateError::{
|
||||||
|
CertificateLengthError, DecodeError, ExpirationError, KeyInCertificateError, MalformedRoot,
|
||||||
|
NoTrustedRoot, VerificationError,
|
||||||
|
};
|
||||||
use crate::trust::{Trust, TRUST_LEN};
|
use crate::trust::{Trust, TRUST_LEN};
|
||||||
use fluence_identity::key_pair::KeyPair;
|
use fluence_identity::key_pair::KeyPair;
|
||||||
use fluence_identity::public_key::PublicKey;
|
use fluence_identity::public_key::PublicKey;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use thiserror::Error as ThisError;
|
||||||
|
|
||||||
/// Serialization format of a certificate.
|
/// Serialization format of a certificate.
|
||||||
/// TODO
|
/// TODO
|
||||||
@ -33,16 +38,27 @@ pub struct Certificate {
|
|||||||
pub chain: Vec<Trust>,
|
pub chain: Vec<Trust>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(ThisError, Debug)]
|
||||||
pub enum CerificateError {
|
pub enum CerificateError {
|
||||||
|
#[error("Error while decoding a certificate: {0}")]
|
||||||
DecodeError(String),
|
DecodeError(String),
|
||||||
|
#[error("Certificate is expired. Issued at {issued_at:?} and expired at {expires_at:?}")]
|
||||||
ExpirationError {
|
ExpirationError {
|
||||||
expires_at: String,
|
expires_at: String,
|
||||||
issued_at: String
|
issued_at: String,
|
||||||
},
|
},
|
||||||
|
#[error("Certificate does not contain a trusted root.")]
|
||||||
|
NoTrustedRoot,
|
||||||
|
#[error("Root trust did not pass verification: {0}")]
|
||||||
|
MalformedRoot(String),
|
||||||
|
#[error("There is no `issued_by` public key in a certificate")]
|
||||||
KeyInCertificateError,
|
KeyInCertificateError,
|
||||||
|
#[error("The certificate must have at least 1 trust")]
|
||||||
CertificateLengthError,
|
CertificateLengthError,
|
||||||
Unexpected(String)
|
#[error("Trust {0} in chain did not pass verification: {1}")]
|
||||||
|
VerificationError(usize, String),
|
||||||
|
#[error("Unexpected error: {0}")]
|
||||||
|
Unexpected(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Certificate {
|
impl Certificate {
|
||||||
@ -79,7 +95,10 @@ impl Certificate {
|
|||||||
cur_time: Duration,
|
cur_time: Duration,
|
||||||
) -> Result<Self, CerificateError> {
|
) -> Result<Self, CerificateError> {
|
||||||
if expires_at.lt(&issued_at) {
|
if expires_at.lt(&issued_at) {
|
||||||
return Err("Expiration time should be greater than issued time.".to_string());
|
return Err(ExpirationError {
|
||||||
|
expires_at: format!("{:?}", expires_at),
|
||||||
|
issued_at: format!("{:?}", issued_at),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// first, verify given certificate
|
// first, verify given certificate
|
||||||
@ -100,7 +119,7 @@ impl Certificate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if previous_trust_num == -1 {
|
if previous_trust_num == -1 {
|
||||||
return Err("Your public key should be in certificate.".to_string());
|
return Err(KeyInCertificateError);
|
||||||
};
|
};
|
||||||
|
|
||||||
// splitting old chain to add new trust after given public key
|
// splitting old chain to add new trust after given public key
|
||||||
@ -126,15 +145,15 @@ impl Certificate {
|
|||||||
let chain = &cert.chain;
|
let chain = &cert.chain;
|
||||||
|
|
||||||
if chain.is_empty() {
|
if chain.is_empty() {
|
||||||
return Err("The certificate must have at least 1 trust".to_string());
|
return Err(CertificateLengthError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check root trust and its existence in trusted roots list
|
// check root trust and its existence in trusted roots list
|
||||||
let root = &chain[0];
|
let root = &chain[0];
|
||||||
Trust::verify(root, &root.issued_for, cur_time)
|
Trust::verify(root, &root.issued_for, cur_time)
|
||||||
.map_err(|e| format!("Root trust did not pass verification: {}", e))?;
|
.map_err(|e| MalformedRoot(format!("{}", e)))?;
|
||||||
if !trusted_roots.contains(&root.issued_for) {
|
if !trusted_roots.contains(&root.issued_for) {
|
||||||
return Err("Certificate does not contain a trusted root.".to_string());
|
return Err(NoTrustedRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if every element in a chain is not expired and has the correct signature
|
// check if every element in a chain is not expired and has the correct signature
|
||||||
@ -143,12 +162,8 @@ impl Certificate {
|
|||||||
|
|
||||||
let trust_giver = &chain[trust_id - 1];
|
let trust_giver = &chain[trust_id - 1];
|
||||||
|
|
||||||
Trust::verify(trust, &trust_giver.issued_for, cur_time).map_err(|e| {
|
Trust::verify(trust, &trust_giver.issued_for, cur_time)
|
||||||
format!(
|
.map_err(|e| VerificationError(trust_id, format!("{}", e)))?;
|
||||||
"Trust {} in chain did not pass verification: {}",
|
|
||||||
trust_id, e
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -174,13 +189,13 @@ impl Certificate {
|
|||||||
pub fn decode(arr: &[u8]) -> Result<Self, CerificateError> {
|
pub fn decode(arr: &[u8]) -> Result<Self, CerificateError> {
|
||||||
let trusts_offset = arr.len() - 2 - 4;
|
let trusts_offset = arr.len() - 2 - 4;
|
||||||
if trusts_offset % TRUST_LEN != 0 {
|
if trusts_offset % TRUST_LEN != 0 {
|
||||||
return Err("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust. ".to_string());
|
return Err(DecodeError("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust. ".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let number_of_trusts = trusts_offset / TRUST_LEN;
|
let number_of_trusts = trusts_offset / TRUST_LEN;
|
||||||
|
|
||||||
if number_of_trusts < 2 {
|
if number_of_trusts < 2 {
|
||||||
return Err("The certificate must have at least 2 trusts.".to_string());
|
return Err(CertificateLengthError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO do match different formats and versions
|
// TODO do match different formats and versions
|
||||||
@ -193,7 +208,7 @@ impl Certificate {
|
|||||||
let from = i * TRUST_LEN + 6;
|
let from = i * TRUST_LEN + 6;
|
||||||
let to = (i + 1) * TRUST_LEN + 6;
|
let to = (i + 1) * TRUST_LEN + 6;
|
||||||
let slice = &arr[from..to];
|
let slice = &arr[from..to];
|
||||||
let t = Trust::decode(slice)?;
|
let t = Trust::decode(slice).map_err(|e| DecodeError(format!("{}", e)))?;
|
||||||
chain.push(t);
|
chain.push(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +228,7 @@ impl std::fmt::Display for Certificate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Certificate {
|
impl FromStr for Certificate {
|
||||||
type Err = String;
|
type Err = CerificateError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let str_lines: Vec<&str> = s.lines().collect();
|
let str_lines: Vec<&str> = s.lines().collect();
|
||||||
@ -223,7 +238,10 @@ impl FromStr for Certificate {
|
|||||||
let _version = str_lines[1];
|
let _version = str_lines[1];
|
||||||
|
|
||||||
if (str_lines.len() - 2) % 4 != 0 {
|
if (str_lines.len() - 2) % 4 != 0 {
|
||||||
return Err(format!("Incorrect format of the certificate: {}", s));
|
return Err(DecodeError(format!(
|
||||||
|
"Incorrect format of the certificate: {}",
|
||||||
|
s
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_of_trusts = (str_lines.len() - 2) / 4;
|
let num_of_trusts = (str_lines.len() - 2) / 4;
|
||||||
@ -235,7 +253,13 @@ impl FromStr for Certificate {
|
|||||||
str_lines[i + 1],
|
str_lines[i + 1],
|
||||||
str_lines[i + 2],
|
str_lines[i + 2],
|
||||||
str_lines[i + 3],
|
str_lines[i + 3],
|
||||||
)?;
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
DecodeError(format!(
|
||||||
|
"Cannot convert trust number {} from string: {}",
|
||||||
|
i, e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
trusts.push(trust);
|
trusts.push(trust);
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,18 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use crate::revoke::RevokeError::IncorrectSignature;
|
||||||
use crate::trust::{EXPIRATION_LEN, PK_LEN};
|
use crate::trust::{EXPIRATION_LEN, PK_LEN};
|
||||||
|
use ed25519_dalek::SignatureError;
|
||||||
use fluence_identity::key_pair::KeyPair;
|
use fluence_identity::key_pair::KeyPair;
|
||||||
use fluence_identity::public_key::PublicKey;
|
use fluence_identity::public_key::PublicKey;
|
||||||
use fluence_identity::signature::Signature;
|
use fluence_identity::signature::Signature;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use ed25519_dalek::SignatureError;
|
|
||||||
use crate::revoke::RevokeError::IncorrectSignature;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RevokeError {
|
pub enum RevokeError {
|
||||||
IncorrectSignature(SignatureError)
|
IncorrectSignature(SignatureError),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// "A document" that cancels trust created before.
|
/// "A document" that cancels trust created before.
|
||||||
|
33
src/trust.rs
33
src/trust.rs
@ -14,6 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use crate::trust::TrustError::{DecodeError, SignatureError};
|
||||||
use derivative::Derivative;
|
use derivative::Derivative;
|
||||||
use fluence_identity::key_pair::KeyPair;
|
use fluence_identity::key_pair::KeyPair;
|
||||||
use fluence_identity::public_key::PublicKey;
|
use fluence_identity::public_key::PublicKey;
|
||||||
@ -22,7 +23,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use thiserror::Error as ThisError;
|
use thiserror::Error as ThisError;
|
||||||
use crate::trust::TrustError::{SignatureError, DecodeError};
|
|
||||||
|
|
||||||
pub const SIG_LEN: usize = 64;
|
pub const SIG_LEN: usize = 64;
|
||||||
pub const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 32;
|
||||||
@ -69,7 +69,7 @@ pub enum TrustError {
|
|||||||
|
|
||||||
/// Errors occured on trust decoding from differrent formats
|
/// Errors occured on trust decoding from differrent formats
|
||||||
#[error("{0:?}")]
|
#[error("{0:?}")]
|
||||||
DecodeError(String)
|
DecodeError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trust {
|
impl Trust {
|
||||||
@ -107,9 +107,13 @@ impl Trust {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Verifies that authorization is cryptographically correct.
|
/// Verifies that authorization is cryptographically correct.
|
||||||
pub fn verify(trust: &Trust, issued_by: &PublicKey, cur_time: Duration) -> Result<(), TrustError> {
|
pub fn verify(
|
||||||
|
trust: &Trust,
|
||||||
|
issued_by: &PublicKey,
|
||||||
|
cur_time: Duration,
|
||||||
|
) -> Result<(), TrustError> {
|
||||||
if trust.expires_at < cur_time {
|
if trust.expires_at < cur_time {
|
||||||
return TrustError::Expired(trust.expires_at, cur_time);
|
return Err(TrustError::Expired(trust.expires_at, cur_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
let msg: &[u8] =
|
let msg: &[u8] =
|
||||||
@ -151,18 +155,20 @@ impl Trust {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn decode(arr: &[u8]) -> Result<Self, TrustError> {
|
pub fn decode(arr: &[u8]) -> Result<Self, TrustError> {
|
||||||
if arr.len() != TRUST_LEN {
|
if arr.len() != TRUST_LEN {
|
||||||
return DecodeError(
|
return Err(DecodeError(
|
||||||
format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}",
|
format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}",
|
||||||
arr.len())
|
arr.len())
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let pk = PublicKey::from_bytes(&arr[0..PK_LEN])
|
let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(|err| {
|
||||||
.map_err(|err| DecodeError(format!("Cannot decode a public key: {}", err.to_string())))?;
|
DecodeError(format!("Cannot decode a public key: {}", err.to_string()))
|
||||||
|
})?;
|
||||||
|
|
||||||
let signature = &arr[PK_LEN..PK_LEN + SIG_LEN];
|
let signature = &arr[PK_LEN..PK_LEN + SIG_LEN];
|
||||||
let signature = Signature::from_bytes(signature)
|
let signature = Signature::from_bytes(signature).map_err(|err| {
|
||||||
.map_err(|err| DecodeError(format!("Cannot decode a signature: {}", err.to_string())))?;
|
DecodeError(format!("Cannot decode a signature: {}", err.to_string()))
|
||||||
|
})?;
|
||||||
|
|
||||||
let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN];
|
let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN];
|
||||||
let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap());
|
let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap());
|
||||||
@ -182,10 +188,10 @@ impl Trust {
|
|||||||
|
|
||||||
fn bs58_str_to_vec(str: &str, field: &str) -> Result<Vec<u8>, TrustError> {
|
fn bs58_str_to_vec(str: &str, field: &str) -> Result<Vec<u8>, TrustError> {
|
||||||
bs58::decode(str).into_vec().map_err(|e| {
|
bs58::decode(str).into_vec().map_err(|e| {
|
||||||
format!(
|
DecodeError(format!(
|
||||||
"Cannot decode `{}` from base58 format in the trust '{}': {}",
|
"Cannot decode `{}` from base58 format in the trust '{}': {}",
|
||||||
field, str, e
|
field, str, e
|
||||||
)
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +222,8 @@ impl Trust {
|
|||||||
|
|
||||||
// 64 bytes signature
|
// 64 bytes signature
|
||||||
let signature = Self::bs58_str_to_vec(signature, "signature")?;
|
let signature = Self::bs58_str_to_vec(signature, "signature")?;
|
||||||
let signature = Signature::from_bytes(&signature).map_err(|err| DecodeError(err.to_string()))?;
|
let signature =
|
||||||
|
Signature::from_bytes(&signature).map_err(|err| DecodeError(err.to_string()))?;
|
||||||
|
|
||||||
// Duration
|
// Duration
|
||||||
let expires_at = Self::str_to_duration(expires_at, "expires_at")?;
|
let expires_at = Self::str_to_duration(expires_at, "expires_at")?;
|
||||||
|
@ -14,21 +14,23 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::certificate::{Certificate, CerificateError};
|
use crate::certificate::CerificateError::{CertificateLengthError, Unexpected};
|
||||||
|
use crate::certificate::{CerificateError, Certificate};
|
||||||
use crate::public_key_hashable::PublicKeyHashable;
|
use crate::public_key_hashable::PublicKeyHashable;
|
||||||
use crate::revoke::Revoke;
|
use crate::revoke::Revoke;
|
||||||
|
use crate::revoke::RevokeError;
|
||||||
use crate::trust::Trust;
|
use crate::trust::Trust;
|
||||||
use crate::trust_graph_storage::{Storage, StorageError};
|
use crate::trust_graph::TrustGraphError::{
|
||||||
|
CertificateCheckError, InternalStorageError, NoRoot, RevokeCheckError,
|
||||||
|
};
|
||||||
|
use crate::trust_graph_storage::Storage;
|
||||||
use crate::trust_node::{Auth, TrustNode};
|
use crate::trust_node::{Auth, TrustNode};
|
||||||
use fluence_identity::public_key::PublicKey;
|
use fluence_identity::public_key::PublicKey;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::{HashSet, VecDeque};
|
use std::collections::{HashSet, VecDeque};
|
||||||
use std::time::Duration;
|
|
||||||
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::convert::{From, Into};
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
/// for simplicity, we store `n` where Weight = 1/n^2
|
/// for simplicity, we store `n` where Weight = 1/n^2
|
||||||
pub type Weight = u32;
|
pub type Weight = u32;
|
||||||
@ -37,7 +39,10 @@ pub type Weight = u32;
|
|||||||
/// TODO serialization/deserialization
|
/// TODO serialization/deserialization
|
||||||
/// TODO export a certificate from graph
|
/// TODO export a certificate from graph
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct TrustGraph<S> where S: Storage {
|
pub struct TrustGraph<S>
|
||||||
|
where
|
||||||
|
S: Storage,
|
||||||
|
{
|
||||||
storage: Box<S>,
|
storage: Box<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,19 +67,30 @@ impl From<RevokeError> for TrustGraphError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl<S> TrustGraph<S> where S: Storage {
|
impl<S> TrustGraph<S>
|
||||||
|
where
|
||||||
|
S: Storage,
|
||||||
|
{
|
||||||
pub fn new(storage: Box<S>) -> Self {
|
pub fn new(storage: Box<S>) -> Self {
|
||||||
Self { storage: storage }
|
Self { storage: storage }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert new root weight
|
/// Insert new root weight
|
||||||
pub fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), TrustGraphError> {
|
pub fn add_root_weight(
|
||||||
self.storage.add_root_weight(pk, weight).map_err(|e| InternalStorageError(e.into()))
|
&mut self,
|
||||||
|
pk: PublicKeyHashable,
|
||||||
|
weight: Weight,
|
||||||
|
) -> Result<(), TrustGraphError> {
|
||||||
|
self.storage
|
||||||
|
.add_root_weight(pk, weight)
|
||||||
|
.map_err(|e| InternalStorageError(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get trust by public key
|
/// Get trust by public key
|
||||||
pub fn get(&self, pk: PublicKey) -> Result<Option<TrustNode>, TrustGraphError> {
|
pub fn get(&self, pk: PublicKey) -> Result<Option<TrustNode>, TrustGraphError> {
|
||||||
self.storage.get(&pk.into()).map_err(|e| InternalStorageError(e.into()))
|
self.storage
|
||||||
|
.get(&pk.into())
|
||||||
|
.map_err(|e| InternalStorageError(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove cur_time from api, leave it for tests only
|
// TODO: remove cur_time from api, leave it for tests only
|
||||||
@ -95,18 +111,26 @@ impl<S> TrustGraph<S> where S: Storage {
|
|||||||
Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?;
|
Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?;
|
||||||
|
|
||||||
let mut chain = cert.borrow().chain.iter();
|
let mut chain = cert.borrow().chain.iter();
|
||||||
let root_trust = chain.next().ok_or("empty chain").map_err(|e| InternalStorageError(e.into()))?;
|
let root_trust = chain
|
||||||
|
.next()
|
||||||
|
.ok_or("empty chain")
|
||||||
|
.map_err(|e| InternalStorageError(e.into()))?;
|
||||||
let root_pk: PublicKeyHashable = root_trust.issued_for.clone().into();
|
let root_pk: PublicKeyHashable = root_trust.issued_for.clone().into();
|
||||||
|
|
||||||
// Insert new TrustNode for this root_pk if there wasn't one
|
// Insert new TrustNode for this root_pk if there wasn't one
|
||||||
if self.storage.get(&root_pk).map_err(|e| InternalStorageError(e.into()))?.is_none() {
|
if self
|
||||||
|
.storage
|
||||||
|
.get(&root_pk)
|
||||||
|
.map_err(|e| InternalStorageError(e.into()))?
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time);
|
let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time);
|
||||||
let root_auth = Auth {
|
let root_auth = Auth {
|
||||||
trust: root_trust.clone(),
|
trust: root_trust.clone(),
|
||||||
issued_by: root_trust.issued_for.clone(),
|
issued_by: root_trust.issued_for.clone(),
|
||||||
};
|
};
|
||||||
trust_node.update_auth(root_auth);
|
trust_node.update_auth(root_auth);
|
||||||
self.storage.insert(root_pk, trust_node);
|
self.storage.insert(root_pk, trust_node).map_err(|e| InternalStorageError(e.into()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert remaining trusts to the graph
|
// Insert remaining trusts to the graph
|
||||||
@ -120,7 +144,7 @@ impl<S> TrustGraph<S> where S: Storage {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.storage
|
self.storage
|
||||||
.update_auth(&pk, auth, &root_trust.issued_for, cur_time);
|
.update_auth(&pk, auth, &root_trust.issued_for, cur_time).map_err(|e| InternalStorageError(e.into()))?;
|
||||||
|
|
||||||
previous_trust = trust;
|
previous_trust = trust;
|
||||||
}
|
}
|
||||||
@ -133,7 +157,11 @@ impl<S> TrustGraph<S> where S: Storage {
|
|||||||
where
|
where
|
||||||
P: Borrow<PublicKey>,
|
P: Borrow<PublicKey>,
|
||||||
{
|
{
|
||||||
if let Some(weight) = self.storage.get_root_weight(pk.borrow().as_ref()).map_err(|e| InternalStorageError(e.into()))? {
|
if let Some(weight) = self
|
||||||
|
.storage
|
||||||
|
.get_root_weight(pk.borrow().as_ref())
|
||||||
|
.map_err(|e| InternalStorageError(e.into()))?
|
||||||
|
{
|
||||||
return Ok(Some(weight));
|
return Ok(Some(weight));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +191,7 @@ impl<S> TrustGraph<S> where S: Storage {
|
|||||||
// if there are no certificates for the given public key, there is no info about this public key
|
// if there are no certificates for the given public key, there is no info about this public key
|
||||||
// or some elements of possible certificate chains was revoked
|
// or some elements of possible certificate chains was revoked
|
||||||
if certs.peek().is_none() {
|
if certs.peek().is_none() {
|
||||||
return Ok(None)
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut weight = std::u32::MAX;
|
let mut weight = std::u32::MAX;
|
||||||
@ -171,13 +199,17 @@ impl<S> TrustGraph<S> where S: Storage {
|
|||||||
for cert in certs {
|
for cert in certs {
|
||||||
let c = cert.borrow();
|
let c = cert.borrow();
|
||||||
|
|
||||||
let first = c.chain.first().ok_or(CertificateCheckError(CertificateLengthError))?;
|
let first = c
|
||||||
|
.chain
|
||||||
|
.first()
|
||||||
|
.ok_or(CertificateCheckError(CertificateLengthError))?;
|
||||||
|
|
||||||
let root_weight = self
|
let root_weight = self
|
||||||
.storage
|
.storage
|
||||||
.get_root_weight(first.issued_for.as_ref())
|
.get_root_weight(first.issued_for.as_ref())
|
||||||
// This panic shouldn't happen // TODO: why?
|
// This panic shouldn't happen // TODO: why?
|
||||||
.map_err(|e| InternalStorageError(e.into()))?.ok_or(NoRoot)?;
|
.map_err(|e| InternalStorageError(e.into()))?
|
||||||
|
.ok_or(NoRoot)?;
|
||||||
|
|
||||||
// certificate weight = root weight + 1 * every other element in the chain
|
// certificate weight = root weight + 1 * every other element in the chain
|
||||||
// (except root, so the formula is `root weight + chain length - 1`)
|
// (except root, so the formula is `root weight + chain length - 1`)
|
||||||
@ -220,9 +252,10 @@ impl<S> TrustGraph<S> where S: Storage {
|
|||||||
.storage
|
.storage
|
||||||
.get(&last.issued_by.clone().into())
|
.get(&last.issued_by.clone().into())
|
||||||
.map_err(|e| InternalStorageError(e.into()))?
|
.map_err(|e| InternalStorageError(e.into()))?
|
||||||
.ok_or(
|
.ok_or(CertificateCheckError(Unexpected(
|
||||||
CertificateCheckError(Unexpected("there cannot be paths without any nodes after adding verified certificates".to_string())),
|
"there cannot be paths without any nodes after adding verified certificates"
|
||||||
)?
|
.to_string(),
|
||||||
|
)))?
|
||||||
.authorizations()
|
.authorizations()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
@ -258,15 +291,25 @@ impl<S> TrustGraph<S> where S: Storage {
|
|||||||
// TODO: remove `roots` argument from api, leave it for tests and internal usage only
|
// 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
|
/// 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.
|
/// and one of the destinations is the root of this chain.
|
||||||
pub fn get_all_certs<P>(&self, issued_for: P, roots: &[PublicKey]) -> Result<Vec<Certificate>, TrustGraphError>
|
pub fn get_all_certs<P>(
|
||||||
|
&self,
|
||||||
|
issued_for: P,
|
||||||
|
roots: &[PublicKey],
|
||||||
|
) -> Result<Vec<Certificate>, TrustGraphError>
|
||||||
where
|
where
|
||||||
P: Borrow<PublicKey>,
|
P: Borrow<PublicKey>,
|
||||||
{
|
{
|
||||||
// get all auths (edges) for issued public key
|
// get all auths (edges) for issued public key
|
||||||
let issued_for_node = self.storage.get(issued_for.borrow().as_ref()).map_err(|e| InternalStorageError(e.into()))?;
|
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 roots = roots.iter().map(|pk| pk.as_ref());
|
||||||
let keys = self.storage.root_keys().map_err(|e| InternalStorageError(e.into()))?;
|
let keys = self
|
||||||
|
.storage
|
||||||
|
.root_keys()
|
||||||
|
.map_err(|e| InternalStorageError(e.into()))?;
|
||||||
let roots = keys.iter().chain(roots).collect();
|
let roots = keys.iter().chain(roots).collect();
|
||||||
|
|
||||||
match issued_for_node {
|
match issued_for_node {
|
||||||
@ -299,7 +342,9 @@ impl<S> TrustGraph<S> where S: Storage {
|
|||||||
|
|
||||||
let pk: PublicKeyHashable = revoke.pk.clone().into();
|
let pk: PublicKeyHashable = revoke.pk.clone().into();
|
||||||
|
|
||||||
self.storage.revoke(&pk, revoke).map_err(|e| InternalStorageError(e.into()))
|
self.storage
|
||||||
|
.revoke(&pk, revoke)
|
||||||
|
.map_err(|e| InternalStorageError(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check information about new certificates and about revoked certificates.
|
/// Check information about new certificates and about revoked certificates.
|
||||||
@ -421,7 +466,8 @@ mod tests {
|
|||||||
chain_keys.insert(5, key_pair1.clone());
|
chain_keys.insert(5, key_pair1.clone());
|
||||||
chain_keys.insert(6, key_pair2.clone());
|
chain_keys.insert(6, key_pair2.clone());
|
||||||
|
|
||||||
let (key_pairs1, cert1) = generate_cert_with(10, chain_keys, far_future * 2, far_future).expect("");
|
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
|
// Use key_pair1 and key_pair2 for 7th and 8th trust in the cert chain
|
||||||
let mut chain_keys = HashMap::new();
|
let mut chain_keys = HashMap::new();
|
||||||
@ -550,7 +596,9 @@ mod tests {
|
|||||||
|
|
||||||
graph.add(cert.clone(), current_time()).unwrap();
|
graph.add(cert.clone(), current_time()).unwrap();
|
||||||
|
|
||||||
let certs = graph.get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk]).unwrap();
|
let certs = graph
|
||||||
|
.get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(certs.len(), 1);
|
assert_eq!(certs.len(), 1);
|
||||||
assert_eq!(certs[0], cert);
|
assert_eq!(certs[0], cert);
|
||||||
@ -617,17 +665,23 @@ mod tests {
|
|||||||
|
|
||||||
let roots_values = [root1_pk, root2_pk, root3_pk];
|
let roots_values = [root1_pk, root2_pk, root3_pk];
|
||||||
|
|
||||||
let certs1 = graph.get_all_certs(key_pair1.public_key(), &roots_values).unwrap();
|
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 lenghts1: Vec<usize> = certs1.iter().map(|c| c.chain.len()).collect();
|
||||||
let check_lenghts1: Vec<usize> = vec![3, 4, 4, 5, 5];
|
let check_lenghts1: Vec<usize> = vec![3, 4, 4, 5, 5];
|
||||||
assert_eq!(lenghts1, check_lenghts1);
|
assert_eq!(lenghts1, check_lenghts1);
|
||||||
|
|
||||||
let certs2 = graph.get_all_certs(key_pair2.public_key(), &roots_values).unwrap();
|
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 lenghts2: Vec<usize> = certs2.iter().map(|c| c.chain.len()).collect();
|
||||||
let check_lenghts2: Vec<usize> = vec![4, 4, 4, 5, 5];
|
let check_lenghts2: Vec<usize> = vec![4, 4, 4, 5, 5];
|
||||||
assert_eq!(lenghts2, check_lenghts2);
|
assert_eq!(lenghts2, check_lenghts2);
|
||||||
|
|
||||||
let certs3 = graph.get_all_certs(key_pair3.public_key(), &roots_values).unwrap();
|
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 lenghts3: Vec<usize> = certs3.iter().map(|c| c.chain.len()).collect();
|
||||||
let check_lenghts3: Vec<usize> = vec![3, 3, 5];
|
let check_lenghts3: Vec<usize> = vec![3, 3, 5];
|
||||||
assert_eq!(lenghts3, check_lenghts3);
|
assert_eq!(lenghts3, check_lenghts3);
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
use crate::public_key_hashable::PublicKeyHashable;
|
use crate::public_key_hashable::PublicKeyHashable;
|
||||||
use crate::revoke::Revoke;
|
use crate::revoke::Revoke;
|
||||||
use crate::trust_graph::Weight;
|
use crate::trust_graph::Weight;
|
||||||
|
use crate::trust_graph_storage::InMemoryStorageError::RevokeError;
|
||||||
use crate::trust_node::{Auth, TrustNode};
|
use crate::trust_node::{Auth, TrustNode};
|
||||||
use fluence_identity::public_key::PublicKey;
|
use fluence_identity::public_key::PublicKey;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use thiserror::Error as ThisError;
|
use thiserror::Error as ThisError;
|
||||||
use crate::trust_graph_storage::InMemoryStorageError::RevokeError;
|
|
||||||
|
|
||||||
pub trait StorageError {}
|
|
||||||
|
|
||||||
|
|
||||||
|
pub trait StorageError: std::error::Error {}
|
||||||
|
|
||||||
pub trait Storage {
|
pub trait Storage {
|
||||||
|
|
||||||
type Error: StorageError + Into<String>;
|
type Error: StorageError + Into<String>;
|
||||||
|
|
||||||
fn get(&self, pk: &PublicKeyHashable) -> Result<Option<TrustNode>, Self::Error>;
|
fn get(&self, pk: &PublicKeyHashable) -> Result<Option<TrustNode>, Self::Error>;
|
||||||
fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error>;
|
fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result<Option<Weight>, Self::Error>;
|
fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result<Option<Weight>, Self::Error>;
|
||||||
fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error>;
|
fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight)
|
||||||
|
-> Result<(), Self::Error>;
|
||||||
fn root_keys(&self) -> Result<Vec<PublicKeyHashable>, Self::Error>;
|
fn root_keys(&self) -> Result<Vec<PublicKeyHashable>, Self::Error>;
|
||||||
fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error>;
|
fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error>;
|
||||||
fn update_auth(
|
fn update_auth(
|
||||||
@ -62,15 +60,19 @@ impl InMemoryStorage {
|
|||||||
|
|
||||||
#[derive(ThisError, Debug)]
|
#[derive(ThisError, Debug)]
|
||||||
pub enum InMemoryStorageError {
|
pub enum InMemoryStorageError {
|
||||||
|
#[error("InMemoryStorageError::RevokeError {0:?}")]
|
||||||
#[error("{0:?}")]
|
RevokeError(String),
|
||||||
RevokeError(String)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StorageError for InMemoryStorage {}
|
impl From<InMemoryStorageError> for String {
|
||||||
|
fn from(err: InMemoryStorageError) -> Self {
|
||||||
|
err.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StorageError for InMemoryStorageError {}
|
||||||
|
|
||||||
impl Storage for InMemoryStorage {
|
impl Storage for InMemoryStorage {
|
||||||
|
|
||||||
type Error = InMemoryStorageError;
|
type Error = InMemoryStorageError;
|
||||||
|
|
||||||
fn get(&self, pk: &PublicKeyHashable) -> Result<Option<TrustNode>, Self::Error> {
|
fn get(&self, pk: &PublicKeyHashable) -> Result<Option<TrustNode>, Self::Error> {
|
||||||
@ -86,8 +88,13 @@ impl Storage for InMemoryStorage {
|
|||||||
Ok(self.root_weights.get(pk).cloned())
|
Ok(self.root_weights.get(pk).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error> {
|
fn add_root_weight(
|
||||||
Ok(&self.root_weights.insert(pk, weight));
|
&mut self,
|
||||||
|
pk: PublicKeyHashable,
|
||||||
|
weight: Weight,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
&self.root_weights.insert(pk, weight);
|
||||||
|
Ok({})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root_keys(&self) -> Result<Vec<PublicKeyHashable>, Self::Error> {
|
fn root_keys(&self) -> Result<Vec<PublicKeyHashable>, Self::Error> {
|
||||||
@ -100,7 +107,9 @@ impl Storage for InMemoryStorage {
|
|||||||
trust_node.update_revoke(revoke);
|
trust_node.update_revoke(revoke);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
None => RevokeError("There is no trust with such PublicKey".to_string()),
|
None => Err(RevokeError(
|
||||||
|
"There is no trust with such PublicKey".to_string(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,15 +119,17 @@ impl Storage for InMemoryStorage {
|
|||||||
auth: Auth,
|
auth: Auth,
|
||||||
issued_for: &PublicKey,
|
issued_for: &PublicKey,
|
||||||
cur_time: Duration,
|
cur_time: Duration,
|
||||||
) {
|
) -> Result<(), InMemoryStorageError> {
|
||||||
match self.nodes.get_mut(&pk) {
|
match self.nodes.get_mut(&pk) {
|
||||||
Some(trust_node) => {
|
Some(trust_node) => {
|
||||||
trust_node.update_auth(auth);
|
trust_node.update_auth(auth);
|
||||||
|
Ok({})
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let mut trust_node = TrustNode::new(issued_for.clone(), cur_time);
|
let mut trust_node = TrustNode::new(issued_for.clone(), cur_time);
|
||||||
trust_node.update_auth(auth);
|
trust_node.update_auth(auth);
|
||||||
self.nodes.insert(pk.clone(), trust_node);
|
self.nodes.insert(pk.clone(), trust_node);
|
||||||
|
Ok({})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user