This commit is contained in:
Alexey Proshutinskiy 2021-09-14 14:21:26 +03:00
parent db4165e663
commit 02406c6426
6 changed files with 212 additions and 96 deletions

View File

@ -23,10 +23,12 @@ impl From<Result<(), ServiceError>> for InsertResult {
}
}
// TODO: add peer id to result
#[marine]
pub struct WeightResult {
pub success: bool,
pub weight: Vec<u32>,
pub weight: u32,
pub peer_id: String,
pub error: String,
}
@ -162,24 +164,24 @@ impl From<Result<(), ServiceError>> for VerifyTrustResult {
}
#[marine]
pub struct IssueCertificateResult {
pub struct AddTrustResult {
pub success: bool,
pub error: String,
pub cert: Certificate,
pub weight: u32,
}
impl From<Result<Certificate, ServiceError>> for IssueCertificateResult {
fn from(result: Result<Certificate, ServiceError>) -> Self {
impl From<Result<u32, ServiceError>> for AddTrustResult {
fn from(result: Result<u32, ServiceError>) -> Self {
match result {
Ok(cert) => IssueCertificateResult {
Ok(weight) => AddTrustResult {
success: true,
error: "".to_string(),
cert,
weight,
},
Err(e) => IssueCertificateResult {
Err(e) => AddTrustResult {
success: false,
error: format!("{}", e),
cert: Certificate { chain: vec![] },
weight: u32::default(),
},
}
}

View File

@ -1,11 +1,11 @@
use crate::dto::{Certificate, Trust};
use crate::results::{
AddRootResult, AllCertsResult, GetTrustMetadataResult, InsertResult, IssueCertificateResult,
IssueTrustResult, VerifyTrustResult, WeightResult,
AddRootResult, AddTrustResult, AllCertsResult, GetTrustMetadataResult, InsertResult,
IssueCertificateResult, IssueTrustResult, VerifyTrustResult, WeightResult,
};
use crate::service_impl::{
add_root_impl, get_all_certs_impl, get_trust_metadata_imp, get_weight_impl, insert_cert_impl,
insert_cert_impl_raw, issue_certificate_with_trust_checked_impl,
add_root_impl, add_trust_impl, get_all_certs_impl, get_trust_metadata_imp, get_weight_impl,
insert_cert_impl, insert_cert_impl_raw, issue_certificate_with_trust_checked_impl,
issue_root_certificate_checked_impl, issue_trust_impl, verify_trust_impl,
};
use marine_rs_sdk::{marine, CallParameters};
@ -13,19 +13,19 @@ use marine_rs_sdk::{marine, CallParameters};
#[marine]
/// add a certificate in string representation to trust graph if it is valid
/// see `trust_graph::Certificate` class for string encoding/decoding
// TODO change `current_time` to time service
fn insert_cert_raw(certificate: String, current_time: u64) -> InsertResult {
insert_cert_impl_raw(certificate, current_time).into()
// TODO change `timestamp_sec` to time service
fn insert_cert_raw(certificate: String, timestamp_sec: u64) -> InsertResult {
insert_cert_impl_raw(certificate, timestamp_sec).into()
}
#[marine]
/// add a certificate in JSON representation to trust graph if it is valid
/// see `dto::Certificate` class for structure
fn insert_cert(certificate: Certificate, current_time: u64) -> InsertResult {
insert_cert_impl(certificate, current_time).into()
fn insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult {
insert_cert_impl(certificate, timestamp_sec).into()
}
// TODO: pass current timestamp, return only valid, delete expired
// TODO: pass current timestamp, return only valid, delete expired, return max weight
#[marine]
fn get_weight(peer_id: String) -> WeightResult {
get_weight_impl(peer_id).into()
@ -37,6 +37,8 @@ fn get_all_certs(issued_for: String) -> AllCertsResult {
get_all_certs_impl(issued_for).into()
}
// todo: add trust method
#[marine]
/// could add only a host of a trust graph service
fn add_root(peer_id: String, weight: u32) -> AddRootResult {
@ -71,27 +73,52 @@ fn issue_trust(
issue_trust_impl(issued_for_peer_id, expires_at, issued_at, signed_metadata).into()
}
// TODO: use "peer" "timestamp_sec" and check tetraplets
#[marine]
fn verify_trust(trust: Trust, issuer_peer_id: String, cur_time: u64) -> VerifyTrustResult {
verify_trust_impl(trust, issuer_peer_id, cur_time).into()
fn verify_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> VerifyTrustResult {
verify_trust_impl(trust, issuer_peer_id, timestamp_sec).into()
}
#[marine]
fn issue_root_certificate_checked(
root_trust: Trust,
issued_trust: Trust,
cur_time: u64,
) -> IssueCertificateResult {
issue_root_certificate_checked_impl(root_trust, issued_trust, cur_time).into()
fn add_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> AddTrustResult {
add_trust_impl(trust, issuer_peer_id, timestamp_sec).into()
}
#[marine]
fn issue_certificate_with_trust_checked(
cert: Certificate,
trust: Trust,
issued_by_peer_id: String,
cur_time: u64,
) -> IssueCertificateResult {
issue_certificate_with_trust_checked_impl(cert, trust, issued_by_peer_id, cur_time).into()
}
// service TrustGraph("trust-graph"):
// -- returns hash of metadata to sign
// get_trust_bytes(issued_for_peer_id: string, expires_at: u64, issued_at: u64) -> GetTrustMetadataResult
//
// -- issued_by needed to identify signature type (ed25519, rsa or secp256k1)
// issue_trust(issued_by_peer_id: string, issued_for_peer_id: string, expires_at: u64, issued_at: u64, signature: []u8) -> IssueTrustResult
//
// -- just verifying signatures, timestamp without inserting into local trust graph
// verify_trust(issued_by_peer_id: string, trust: Trust, timestamp_sec: u64) -> VerifyTrustResult
//
// -- checks signature, timestamp, try to find place to insert, returns max_weight if succeed
// add_trust(issued_by_peer_id: string, trust: Trust, timestamp_sec: u64) -> AddTrustResult
//
// -- add root trust with given weight
// add_root(peer_id: string, trust: Trust, weight: u32) -> AddRootResult
//
// -- return max weight if found, remove expired
// get_weight(issued_for: string, timestamp_sec: u32) -> WeightResult
//
// -- return all certs, remove expired
// get_all_certs(issued_for: string, timestamp_sec) -> AllCertsResult
//
// -- insert full certificate if possible
// insert_cert(certificate: Certificate, current_time: u64) -> InsertResult
// insert_cert_raw(certificate: string, current_time: u64) -> InsertResult
//
// -- returns hash of metadata to sign
// get_revoke_bytes(revoked_peer_id: string, revoked_at: u64, issued_at: u64) -> GetRevokeMetadataResult
//
// -- revoked_by needed to identify signature type (ed25519, rsa or secp256k1)
// issue_revoke(revoked_by_peer_id: string, revoked_peer_id: string, revoked_at: u64, signature: []u8) -> IssueRevokeResult
//
// -- checks signature, checks timestamp
// revoke(revoke: Revoke, timestamp_sec: u64) -> AddRevokeResult
//
// get_all_revocation(revoked_peer_id: string)
//
// -- TODO
// get_trust

View File

@ -1,15 +1,37 @@
use crate::dto::{Certificate, DtoConversionError, Trust};
use crate::service_impl::ServiceError::InvalidTimestampTetraplet;
use crate::storage_impl::get_data;
use fluence_keypair::error::DecodingError;
use fluence_keypair::public_key::peer_id_to_fluence_pk;
use fluence_keypair::{PublicKey, Signature};
use libp2p_core::PeerId;
use marine_rs_sdk::CallParameters;
use std::convert::{Into, TryInto};
use std::str::FromStr;
use std::time::Duration;
use thiserror::Error as ThisError;
use trust_graph::{current_time, CertificateError, TrustError, TrustGraphError};
pub static TRUSTED_TIMESTAMP_SERVICE_ID: &str = "peer";
pub static TRUSTED_TIMESTAMP_FUNCTION_NAME: &str = "timestamp_sec";
/// Check timestamps are generated on the current host with builtin ("peer" "timestamp_sec")
pub(crate) fn check_timestamp_tetraplets(
call_parameters: &CallParameters,
arg_number: usize,
) -> Result<(), ServiceError> {
let tetraplets = call_parameters
.tetraplets
.get(arg_number)
.ok_or(InvalidTimestampTetraplet)?;
let tetraplet = tetraplets.get(0).wrap_err(error_msg)?;
(tetraplet.service_id == TRUSTED_TIMESTAMP_SERVICE_ID
&& tetraplet.function_name == TRUSTED_TIMESTAMP_FUNCTION_NAME
&& tetraplet.peer_pk == call_parameters.host_id)
.then(|| ())
.ok_or(InvalidTimestampTetraplet)
}
#[derive(ThisError, Debug)]
pub enum ServiceError {
#[error("peer id parse error: {0}")]
@ -46,6 +68,8 @@ pub enum ServiceError {
#[source]
TrustError,
),
#[error("you should use host peer.timestamp_sec to pass timestamp")]
InvalidTimestampTetraplet,
}
fn parse_peer_id(peer_id: String) -> Result<PeerId, ServiceError> {
@ -65,17 +89,17 @@ pub fn get_weight_impl(peer_id: String) -> Result<Option<u32>, ServiceError> {
Ok(weight)
}
fn add_cert(certificate: trust_graph::Certificate, duration: u64) -> Result<(), ServiceError> {
let duration = Duration::from_millis(duration);
fn add_cert(certificate: trust_graph::Certificate, timestamp_sec: u64) -> Result<(), ServiceError> {
let timestamp_sec = Duration::from_secs(timestamp_sec);
let mut tg = get_data().lock();
tg.add(certificate, duration)?;
tg.add(certificate, timestamp_sec)?;
Ok(())
}
pub fn insert_cert_impl_raw(certificate: String, duration: u64) -> Result<(), ServiceError> {
pub fn insert_cert_impl_raw(certificate: String, timestamp_sec: u64) -> Result<(), ServiceError> {
let certificate = trust_graph::Certificate::from_str(&certificate)?;
add_cert(certificate, duration)?;
add_cert(certificate, timestamp_sec)?;
Ok(())
}
@ -93,10 +117,10 @@ pub fn get_all_certs_impl(issued_for: String) -> Result<Vec<Certificate>, Servic
Ok(certs.into_iter().map(|c| c.into()).collect())
}
pub fn insert_cert_impl(certificate: Certificate, duration: u64) -> Result<(), ServiceError> {
pub fn insert_cert_impl(certificate: Certificate, timestamp_sec: u64) -> Result<(), ServiceError> {
let certificate: trust_graph::Certificate = certificate.try_into()?;
add_cert(certificate, duration)?;
add_cert(certificate, timestamp_sec)?;
Ok(())
}
@ -138,45 +162,32 @@ pub fn issue_trust_impl(
pub fn verify_trust_impl(
trust: Trust,
issuer_peer_id: String,
cur_time: u64,
timestamp_sec: u64,
) -> Result<(), ServiceError> {
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 2)?;
let public_key = extract_public_key(issuer_peer_id)?;
trust_graph::Trust::verify(
&trust.try_into()?,
&public_key,
Duration::from_secs(cur_time),
Duration::from_secs(timestamp_sec),
)?;
Ok(())
}
pub fn issue_root_certificate_checked_impl(
root_trust: Trust,
issued_trust: Trust,
cur_time: u64,
) -> Result<Certificate, ServiceError> {
trust_graph::Certificate::new_from_root_trust(
root_trust.try_into()?,
issued_trust.try_into()?,
Duration::from_secs(cur_time),
)
.map(|c| c.into())
.map_err(ServiceError::CertError)
}
pub fn issue_certificate_with_trust_checked_impl(
cert: Certificate,
pub fn add_trust_impl(
trust: Trust,
issued_by: String,
cur_time: u64,
) -> Result<Certificate, ServiceError> {
let public_key = extract_public_key(issued_by)?;
trust_graph::Certificate::issue_with_trust(
public_key,
issuer_peer_id: String,
timestamp_sec: u64,
) -> Result<(), ServiceError> {
let public_key = extract_public_key(issuer_peer_id)?;
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 2)?;
let mut tg = get_data().lock();
tg.add_trust(
trust.try_into()?,
&cert.try_into()?,
Duration::from_secs(cur_time),
)
.map(|c| c.into())
.map_err(ServiceError::CertError)
public_key,
Duration::from_secs(timestamp_sec),
)?;
Ok(())
}

View File

@ -40,19 +40,54 @@ data VerifyTrustResult:
success: bool
error: string
data AddTrustResult:
success: bool
error: string
weight: u32
peer_id: u32
data WeightResult:
success: bool
weight: []u32
weight: u32
peer_id: string
error: string
service TrustGraph("trust-graph"):
add_root(peer_id: string, weight: u32) -> AddRootResult
get_all_certs(issued_for: string) -> AllCertsResult
get_trust_metadata(issued_for_peer_id: string, expires_at: u64, issued_at: u64) -> GetTrustMetadataResult
get_weight(peer_id: string) -> WeightResult
-- returns hash of metadata to sign
get_trust_bytes(issued_for_peer_id: string, expires_at: u64, issued_at: u64) -> GetTrustMetadataResult
-- issued_by needed to identify signature type (ed25519, rsa or secp256k1)
issue_trust(issued_by_peer_id: string, issued_for_peer_id: string, expires_at: u64, issued_at: u64, signature: []u8) -> IssueTrustResult
-- just verifying signatures, timestamp without inserting into local trust graph
verify_trust(issued_by_peer_id: string, trust: Trust, timestamp_sec: u64) -> VerifyTrustResult
-- checks signature, timestamp, try to find place to insert, returns max_weight if succeed
add_trust(issued_by_peer_id: string, trust: Trust, timestamp_sec: u64) -> AddTrustResult
-- add root trust with given weight
add_root(peer_id: string, trust: Trust, weight: u32) -> AddRootResult
-- return max weight if found, remove expired
get_weight(issued_for: string, timestamp_sec: u32) -> WeightResult
-- return all certs, remove expired
get_all_certs(issued_for: string, timestamp_sec) -> AllCertsResult
-- insert full certificate if possible
insert_cert(certificate: Certificate, current_time: u64) -> InsertResult
insert_cert_raw(certificate: string, current_time: u64) -> InsertResult
issue_certificate_with_trust_checked(cert: Certificate, trust: Trust, issued_by_peer_id: string, cur_time: u64) -> IssueCertificateResult
issue_root_certificate_checked(root_trust: Trust, issued_trust: Trust, cur_time: u64) -> IssueCertificateResult
issue_trust(issued_for_peer_id: string, expires_at: u64, issued_at: u64, signed_metadata: []u8) -> IssueTrustResult
verify_trust(trust: Trust, issuer_peer_id: string, cur_time: u64) -> VerifyTrustResult
-- returns hash of metadata to sign
get_revoke_bytes(revoked_peer_id: string, revoked_at: u64, issued_at: u64) -> GetRevokeMetadataResult
-- revoked_by needed to identify signature type (ed25519, rsa or secp256k1)
issue_revoke(revoked_by_peer_id: string, revoked_peer_id: string, revoked_at: u64, signature: []u8) -> IssueRevokeResult
-- checks signature, checks timestamp
revoke(revoke: Revoke, timestamp_sec: u64) -> AddRevokeResult
get_all_revocation(revoked_peer_id: string)
-- TODO
get_trust

View File

@ -68,6 +68,8 @@ pub enum TrustGraphError {
#[source]
RevokeError,
),
#[error("Path to {0} not found")]
AddTrustError(String),
}
impl<T: StorageError + 'static> From<T> for TrustGraphError {
@ -92,7 +94,11 @@ where
}
/// Insert new root weight
pub fn add_root_weight(&mut self, pk: PublicKey, weight: Weight) -> Result<(), TrustGraphError> {
pub fn add_root_weight(
&mut self,
pk: PublicKey,
weight: Weight,
) -> Result<(), TrustGraphError> {
Ok(self.storage.add_root_weight(pk.into(), weight)?)
}
@ -101,7 +107,35 @@ where
Ok(self.storage.get(&pk.into())?)
}
// TODO: remove cur_time from api, leave it for tests only
pub fn add_trust<T, P>(
&mut self,
trust: T,
issued_by: P,
cur_time: Duration,
) -> Result<(), TrustGraphError>
where
T: Borrow<Trust>,
P: Borrow<PublicKey>,
{
Trust::verify(trust, issued_by.borrow(), cur_time)?;
let _parent_trust_node =
self.get(issued_by.clone().borrow())?
.ok_or(TrustGraphError::AddTrustError(
issued_by.borrow().to_peer_id().to_base58(),
))?;
let pk = trust.issued_for.clone().into();
let auth = Auth {
trust: trust.clone(),
issued_by,
};
self.storage
.update_auth(&pk, auth, &root_trust.issued_for, cur_time)
}
/// Certificate is a chain of trusts, add this chain to graph
pub fn add<C>(&mut self, cert: C, cur_time: Duration) -> Result<(), TrustGraphError>
where
@ -123,13 +157,13 @@ where
// Insert new TrustNode for this root_pk if there wasn't one
if self.storage.get(&root_pk)?.is_none() {
let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time);
let root_auth = Auth {
trust: root_trust.clone(),
issued_by: root_trust.issued_for.clone(),
};
trust_node.update_auth(root_auth);
self.storage.insert(root_pk, trust_node)?;
self.storage
.update_auth(&root_pk, root_auth, &root_trust.issued_for, cur_time)?;
}
// Insert remaining trusts to the graph
@ -188,7 +222,7 @@ where
return Ok(None);
}
let mut weight = std::u32::MAX;
let mut weight = u32::MAX;
for cert in certs {
let c = cert.borrow();
@ -376,13 +410,15 @@ mod tests {
let root_kp = KeyPair::generate_ed25519();
let second_kp = KeyPair::generate_ed25519();
let mut cert =
Certificate::issue_root(&root_kp, second_kp.public(), expires_at, issued_at);
let mut cert = Certificate::issue_root(&root_kp, second_kp.public(), expires_at, issued_at);
let mut key_pairs = vec![root_kp, second_kp];
for idx in 2..len {
let kp = keys.get(&idx).unwrap_or(&KeyPair::generate_ed25519()).clone();
let kp = keys
.get(&idx)
.unwrap_or(&KeyPair::generate_ed25519())
.clone();
let previous_kp = &key_pairs[idx - 1];
cert = Certificate::issue(
&previous_kp,
@ -591,9 +627,15 @@ mod tests {
let st = InMemoryStorage::new();
let mut graph = TrustGraph::new(st);
// add first and last trusts as roots
graph.add_root_weight(cert.chain[0].clone().issued_for.into(), 1).unwrap();
graph.add_root_weight(cert.chain[3].clone().issued_for.into(), 1).unwrap();
graph.add_root_weight(cert.chain[5].clone().issued_for.into(), 1).unwrap();
graph
.add_root_weight(cert.chain[0].clone().issued_for.into(), 1)
.unwrap();
graph
.add_root_weight(cert.chain[3].clone().issued_for.into(), 1)
.unwrap();
graph
.add_root_weight(cert.chain[5].clone().issued_for.into(), 1)
.unwrap();
graph.add(cert.clone(), current_time()).unwrap();

View File

@ -118,8 +118,7 @@ impl Storage for InMemoryStorage {
None => {
let mut trust_node = TrustNode::new(issued_for.clone(), cur_time);
trust_node.update_auth(auth);
self.nodes.insert(pk.clone(), trust_node);
Ok(())
self.insert(pk.clone(), trust_node)
}
}
}