broken wip wip wip

This commit is contained in:
DieMyst 2021-01-28 11:57:43 +03:00
parent 88b6f5f3fe
commit 0e7f22b6e0
11 changed files with 187 additions and 70 deletions

1
Cargo.lock generated
View File

@ -1428,6 +1428,7 @@ dependencies = [
"serde_json",
"serde_with",
"signature",
"thiserror",
]
[[package]]

View File

@ -21,3 +21,4 @@ ed25519-dalek = { version = "1.0.1", features = ["serde"] }
rand = "0.7.0"
signature = "1.3.0"
serde_with = "1.6.0"
thiserror = "1.0.23"

38
bin/Cargo.lock generated
View File

@ -984,6 +984,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
@ -1415,6 +1421,36 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "sqlite"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35f759dc2e373e1edd0a27da87aa9136416360c5077a23643fcd6fcdc9cb9e31"
dependencies = [
"libc",
"sqlite3-sys",
]
[[package]]
name = "sqlite3-src"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8bb25e66d026488228a97e0ad21e3d15ec5998dcd9ad73c97cc277c56a6b314"
dependencies = [
"cc",
"pkg-config",
]
[[package]]
name = "sqlite3-sys"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71fec807a1534bd13eeaaec396175d67c79bdc68df55e18a452726ec62a8fb08"
dependencies = [
"libc",
"sqlite3-src",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
@ -1537,6 +1573,7 @@ dependencies = [
"serde_json",
"serde_with",
"signature",
"thiserror",
]
[[package]]
@ -1556,6 +1593,7 @@ dependencies = [
"rmp-serde",
"serde_bencode",
"serde_json",
"sqlite",
"trust-graph",
]

View File

@ -25,3 +25,4 @@ bs58 = "0.3.1"
rmp-serde = "0.15.0"
bincode = "1.3.1"
serde_bencode = "^0.2.3"
sqlite = "0.25.3"

View File

@ -1,5 +1,8 @@
#!/bin/bash
#!/usr/bin/env bash
set -euo pipefail
fce build
mv target/wasm32-wasi/debug/trust-graph.wasm artifacts/
rm artifacts/trust-graph.wasm
mv -f target/wasm32-wasi/debug/trust-graph.wasm artifacts/
RUST_LOG="info" fce-repl Config.toml

View File

@ -27,8 +27,12 @@ fn insert_cert(certificate: String, duration: u64) -> InsertResult {
#[fce]
fn looper() {
let second = std::time::Duration::from_millis(1000);
let mut a = 0;
while true {
std::thread::sleep(second);
a = a + 1;
log::info!("{}", a)
}

View File

@ -33,6 +33,17 @@ pub struct Certificate {
pub chain: Vec<Trust>,
}
pub enum CerificateError {
DecodeError(String),
ExpirationError {
expires_at: String,
issued_at: String
},
KeyInCertificateError,
CertificateLengthError,
}
impl Certificate {
pub fn new_unverified(chain: Vec<Trust>) -> Self {
Self { chain }
@ -65,7 +76,7 @@ impl Certificate {
expires_at: Duration,
issued_at: Duration,
cur_time: Duration,
) -> Result<Self, String> {
) -> Result<Self, CerificateError> {
if expires_at.lt(&issued_at) {
return Err("Expiration time should be greater than issued time.".to_string());
}
@ -110,7 +121,7 @@ impl Certificate {
cert: &Certificate,
trusted_roots: &[PublicKey],
cur_time: Duration,
) -> Result<(), String> {
) -> Result<(), CerificateError> {
let chain = &cert.chain;
if chain.is_empty() {
@ -159,7 +170,7 @@ impl Certificate {
}
#[allow(dead_code)]
pub fn decode(arr: &[u8]) -> Result<Self, String> {
pub fn decode(arr: &[u8]) -> Result<Self, CerificateError> {
let trusts_offset = arr.len() - 2 - 4;
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());

View File

@ -16,15 +16,15 @@
#![recursion_limit = "512"]
#![warn(rust_2018_idioms)]
#![deny(
dead_code,
nonstandard_style,
unused_imports,
unused_mut,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
// #![deny(
// dead_code,
// nonstandard_style,
// unused_imports,
// unused_mut,
// unused_variables,
// unused_unsafe,
// unreachable_patterns
// )]
mod certificate;
pub mod certificate_serde;

View File

@ -21,6 +21,8 @@ use fluence_identity::signature::Signature;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use std::time::Duration;
use thiserror::Error as ThisError;
use crate::trust::TrustError::{SignatureError, DecodeError};
pub const SIG_LEN: usize = 64;
pub const PK_LEN: usize = 32;
@ -55,6 +57,21 @@ fn show_sig(sig: &Signature, f: &mut std::fmt::Formatter<'_>) -> Result<(), std:
write!(f, "{}", bs58::encode(&sig.to_bytes()).into_string())
}
#[derive(ThisError, Debug)]
pub enum TrustError {
/// Errors occurred when 'expires_at' date is later then current time.
#[error("Trust is expired at: '{0:?}', current time: '{1:?}'")]
Expired(Duration, Duration),
/// Errors occured on signature verification
#[error("{0:?}")]
SignatureError(String),
/// Errors occured on trust decoding from differrent formats
#[error("{0:?}")]
DecodeError(String)
}
impl Trust {
#[allow(dead_code)]
pub fn new(
@ -90,15 +107,15 @@ impl Trust {
}
/// Verifies that authorization is cryptographically correct.
pub fn verify(trust: &Trust, issued_by: &PublicKey, cur_time: Duration) -> Result<(), String> {
pub fn verify(trust: &Trust, issued_by: &PublicKey, cur_time: Duration) -> Result<(), TrustError> {
if trust.expires_at < cur_time {
return Err("Trust in chain is expired.".to_string());
return TrustError::Expired(trust.expires_at, cur_time);
}
let msg: &[u8] =
&Self::metadata_bytes(&trust.issued_for, trust.expires_at, trust.issued_at);
KeyPair::verify(issued_by, msg, &trust.signature)?;
KeyPair::verify(issued_by, msg, &trust.signature).map_err(|e| SignatureError(e))?;
Ok(())
}
@ -132,17 +149,20 @@ impl Trust {
/// Decode a trust from a byte array as produced by `encode`.
#[allow(dead_code)]
pub fn decode(arr: &[u8]) -> Result<Self, String> {
pub fn decode(arr: &[u8]) -> Result<Self, TrustError> {
if arr.len() != TRUST_LEN {
return Err(
format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}", arr.len()),
return DecodeError(
format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}",
arr.len())
);
}
let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(|err| err.to_string())?;
let pk = PublicKey::from_bytes(&arr[0..PK_LEN])
.map_err(|err| DecodeError(format!("Cannot decode a public key: {}", err.to_string())))?;
let signature = &arr[PK_LEN..PK_LEN + SIG_LEN];
let signature = Signature::from_bytes(signature).map_err(|err| err.to_string())?;
let signature = Signature::from_bytes(signature)
.map_err(|err| 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_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap());
@ -160,7 +180,7 @@ impl Trust {
})
}
fn bs58_str_to_vec(str: &str, field: &str) -> Result<Vec<u8>, String> {
fn bs58_str_to_vec(str: &str, field: &str) -> Result<Vec<u8>, TrustError> {
bs58::decode(str).into_vec().map_err(|e| {
format!(
"Cannot decode `{}` from base58 format in the trust '{}': {}",
@ -169,12 +189,12 @@ impl Trust {
})
}
fn str_to_duration(str: &str, field: &str) -> Result<Duration, String> {
fn str_to_duration(str: &str, field: &str) -> Result<Duration, TrustError> {
let secs = str.parse().map_err(|e| {
format!(
DecodeError(format!(
"Cannot parse `{}` field in the trust '{}': {}",
field, str, e
)
))
})?;
Ok(Duration::from_secs(secs))
}
@ -184,19 +204,19 @@ impl Trust {
signature: &str,
expires_at: &str,
issued_at: &str,
) -> Result<Self, String> {
) -> Result<Self, TrustError> {
// PublicKey
let issued_for_bytes = Self::bs58_str_to_vec(issued_for, "issued_for")?;
let issued_for = PublicKey::from_bytes(issued_for_bytes.as_slice()).map_err(|e| {
format!(
DecodeError(format!(
"Cannot decode the public key: {} in the trust '{}'",
issued_for, e
)
))
})?;
// 64 bytes signature
let signature = Self::bs58_str_to_vec(signature, "signature")?;
let signature = Signature::from_bytes(&signature).map_err(|err| err.to_string())?;
let signature = Signature::from_bytes(&signature).map_err(|err| DecodeError(err.to_string()))?;
// Duration
let expires_at = Self::str_to_duration(expires_at, "expires_at")?;

View File

@ -14,16 +14,17 @@
* limitations under the License.
*/
use crate::certificate::Certificate;
use crate::certificate::{Certificate, CerificateError};
use crate::public_key_hashable::PublicKeyHashable;
use crate::revoke::Revoke;
use crate::trust::Trust;
use crate::trust_graph_storage::Storage;
use crate::trust_graph_storage::{Storage, StorageError};
use crate::trust_node::{Auth, TrustNode};
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};
/// for simplicity, we store `n` where Weight = 1/n^2
pub type Weight = u32;
@ -32,48 +33,60 @@ pub type Weight = u32;
/// TODO serialization/deserialization
/// TODO export a certificate from graph
#[allow(dead_code)]
pub struct TrustGraph {
storage: Box<dyn Storage + Send + Sync>,
pub struct TrustGraph<S> where S: Storage {
storage: Box<S>,
}
pub enum TrustGraphError {
InternalStorageError(String),
CertificateCheckError(CerificateError)
}
impl Into<TrustGraphError> for CerificateError {
fn into(self) -> TrustGraphError {
CertificateCheckError(self)
}
}
#[allow(dead_code)]
impl TrustGraph {
pub fn new(storage: Box<dyn Storage + Send + Sync>) -> Self {
impl<S> TrustGraph<S> where S: Storage {
pub fn new(storage: Box<S>) -> Self {
Self { storage: storage }
}
/// Insert new root weight
pub fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) {
self.storage.add_root_weight(pk, weight)
pub fn add_root_weight(&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
pub fn get(&self, pk: PublicKey) -> Option<TrustNode> {
self.storage.get(&pk.into())
pub fn get(&self, pk: PublicKey) -> Result<Option<TrustNode>, TrustGraphError> {
self.storage.get(&pk.into()).map_err(|e| InternalStorageError(e.into()))
}
// TODO: remove cur_time from api, leave it for tests only
/// Certificate is a chain of trusts, add this chain to graph
pub fn add<C>(&mut self, cert: C, cur_time: Duration) -> Result<(), String>
pub fn add<C>(&mut self, cert: C, cur_time: Duration) -> Result<(), TrustGraphError>
where
C: Borrow<Certificate>,
{
let roots: Vec<PublicKey> = self
.storage
.root_keys()
.map_err(|e| InternalStorageError(e.into()))?
.iter()
.cloned()
.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)?;
Certificate::verify(cert.borrow(), roots.as_slice(), cur_time).map_err(|e| e.into())?;
let mut chain = cert.borrow().chain.iter();
let root_trust = chain.next().ok_or("empty chain")?;
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();
// Insert new TrustNode for this root_pk if there wasn't one
if self.storage.get(&root_pk).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 root_auth = Auth {
trust: root_trust.clone(),
@ -103,31 +116,32 @@ impl TrustGraph {
}
/// Get the maximum weight of trust for one public key.
pub fn weight<P>(&self, pk: P) -> Option<Weight>
pub fn weight<P>(&self, pk: P) -> Result<Option<Weight>, TrustGraphError>
where
P: Borrow<PublicKey>,
{
if let Some(weight) = self.storage.get_root_weight(pk.borrow().as_ref()) {
return Some(weight);
if let Some(weight) = self.storage.get_root_weight(pk.borrow().as_ref()).map_err(|e| InternalStorageError(e.into()))? {
return Ok(Some(weight));
}
let roots: Vec<PublicKey> = self
.storage
.root_keys()
.map_err(|e| InternalStorageError(e.into()))?
.iter()
.map(|pk| pk.clone().into())
.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());
self.certificates_weight(certs)
Ok(self.certificates_weight(certs)?)
}
/// Calculate weight from given certificates
/// Returns None if there is no such public key
/// or some trust between this key and a root key is revoked.
/// TODO handle non-direct revocations
pub fn certificates_weight<C, I>(&self, certs: I) -> Option<Weight>
pub fn certificates_weight<C, I>(&self, certs: I) -> Result<Option<Weight>, TrustGraphError>
where
C: Borrow<Certificate>,
I: IntoIterator<Item = C>,
@ -135,7 +149,9 @@ impl TrustGraph {
let mut certs = certs.into_iter().peekable();
// 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
certs.peek()?;
if certs.peek().is_none() {
return Ok(None)
}
let mut weight = std::u32::MAX;
@ -146,14 +162,14 @@ impl TrustGraph {
.storage
.get_root_weight(cert.chain.first()?.issued_for.as_ref())
// This panic shouldn't happen // TODO: why?
.expect("first trust in chain must be in root_weights");
.map_err(|e| InternalStorageError(e.into()))?;
// 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)
}
Some(weight)
Ok(Some(weight))
}
/// BF search for all converging paths (chains) in the graph

View File

@ -5,22 +5,31 @@ use crate::trust_node::{Auth, TrustNode};
use fluence_identity::public_key::PublicKey;
use std::collections::HashMap;
use std::time::Duration;
use thiserror::Error as ThisError;
use crate::trust_graph_storage::InMemoryStorageError::RevokeError;
pub trait StorageError {}
pub trait Storage {
fn get(&self, pk: &PublicKeyHashable) -> Option<TrustNode>;
fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode);
fn get_root_weight(&self, pk: &PublicKeyHashable) -> Option<Weight>;
fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight);
fn root_keys(&self) -> Vec<PublicKeyHashable>;
fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), String>;
type Error: StorageError + Into<String>;
fn get(&self, pk: &PublicKeyHashable) -> Result<Option<TrustNode>, 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 add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error>;
fn root_keys(&self) -> Result<Vec<PublicKeyHashable>, Self::Error>;
fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error>;
fn update_auth(
&mut self,
pk: &PublicKeyHashable,
auth: Auth,
issued_for: &PublicKey,
cur_time: Duration,
);
) -> Result<(), Self::Error>;
}
#[derive(Debug, Default)]
@ -51,34 +60,47 @@ impl InMemoryStorage {
}
}
#[derive(ThisError, Debug)]
pub enum InMemoryStorageError {
#[error("{0:?}")]
RevokeError(String)
}
impl StorageError for InMemoryStorage {}
impl Storage for InMemoryStorage {
fn get(&self, pk: &PublicKeyHashable) -> Option<TrustNode> {
self.nodes.get(pk).cloned()
type Error = InMemoryStorageError;
fn get(&self, pk: &PublicKeyHashable) -> Result<Option<TrustNode>, Self::Error> {
Ok(self.nodes.get(pk).cloned())
}
fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) {
fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) -> Result<(), Self::Error> {
&self.nodes.insert(pk, node);
Ok(())
}
fn get_root_weight(&self, pk: &PublicKeyHashable) -> Option<Weight> {
self.root_weights.get(pk).cloned()
fn get_root_weight(&self, pk: &PublicKeyHashable) -> Result<Option<Weight>, Self::Error> {
Ok(self.root_weights.get(pk).cloned())
}
fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) {
&self.root_weights.insert(pk, weight);
fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) -> Result<(), Self::Error> {
Ok(&self.root_weights.insert(pk, weight));
}
fn root_keys(&self) -> Vec<PublicKeyHashable> {
self.root_weights.keys().cloned().map(Into::into).collect()
fn root_keys(&self) -> Result<Vec<PublicKeyHashable>, Self::Error> {
Ok(self.root_weights.keys().cloned().map(Into::into).collect())
}
fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), String> {
fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), Self::Error> {
match self.nodes.get_mut(&pk) {
Some(trust_node) => {
trust_node.update_revoke(revoke);
Ok(())
}
None => Err("There is no trust with such PublicKey".to_string()),
None => RevokeError("There is no trust with such PublicKey".to_string()),
}
}