From 201f65571cf728f9b86c5a60362a74589e710e22 Mon Sep 17 00:00:00 2001 From: Alexey Proshutinskiy Date: Mon, 27 Sep 2021 16:04:59 +0300 Subject: [PATCH] service: expose revoke api --- aqua/trust-graph.aqua | 24 +++++++++++ service/src/dto.rs | 86 ++++++++++++++++++++++++++++++++----- service/src/results.rs | 71 +++++++++++++++++++++++++++++- service/src/service_api.rs | 38 +++++++++++++--- service/src/service_impl.rs | 41 +++++++++++++++++- service/src/tests.rs | 7 +-- src/revoke.rs | 22 +++++----- 7 files changed, 256 insertions(+), 33 deletions(-) diff --git a/aqua/trust-graph.aqua b/aqua/trust-graph.aqua index 9f9c371..bb59c9c 100644 --- a/aqua/trust-graph.aqua +++ b/aqua/trust-graph.aqua @@ -24,6 +24,11 @@ data AllCertsResult: certificates: []Certificate error: string +data GetRevokeBytesResult: + success: bool + error: string + result: []u8 + data GetTrustBytesResult: success: bool error: string @@ -33,11 +38,27 @@ data InsertResult: success: bool error: string +data Revoke: + revoked_peer_id: string + revoked_at: u64 + signature: string + sig_type: string + revoked_by: string + +data IssueRevocationResult: + success: bool + error: string + revoke: Revoke + data IssueTrustResult: success: bool error: string trust: Trust +data RevokeResult: + success: bool + error: string + data VerifyTrustResult: success: bool error: string @@ -52,9 +73,12 @@ service TrustGraph("trust-graph"): add_root(peer_id: string, weight_factor: u32) -> AddRootResult add_trust(trust: Trust, issuer_peer_id: string, timestamp_sec: u64) -> AddTrustResult get_all_certs(issued_for: string, timestamp_sec: u64) -> AllCertsResult + get_revoke_bytes(revoked_peer_id: string, revoked_at: u64) -> GetRevokeBytesResult get_trust_bytes(issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64) -> GetTrustBytesResult get_weight(peer_id: string, timestamp_sec: u64) -> WeightResult insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult insert_cert_raw(certificate: string, timestamp_sec: u64) -> InsertResult + issue_revocation(revoked_peer_id: string, revoked_by_peer_id: string, revoked_at_sec: u64, signature_bytes: []u8) -> IssueRevocationResult issue_trust(issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64, trust_bytes: []u8) -> IssueTrustResult + revoke(revoke: Revoke, timestamp_sec: u64) -> RevokeResult verify_trust(trust: Trust, issuer_peer_id: string, timestamp_sec: u64) -> VerifyTrustResult diff --git a/service/src/dto.rs b/service/src/dto.rs index 22b97b5..6e9fe40 100644 --- a/service/src/dto.rs +++ b/service/src/dto.rs @@ -1,14 +1,14 @@ -use marine_rs_sdk::marine; +use crate::dto::DtoConversionError::PeerIdDecodeError; use fluence_keypair::error::DecodingError; -use fluence_keypair::{Signature}; +use fluence_keypair::public_key::peer_id_to_fluence_pk; +use fluence_keypair::signature::RawSignature; +use fluence_keypair::Signature; +use libp2p_core::PeerId; +use marine_rs_sdk::marine; use std::convert::TryFrom; +use std::str::FromStr; use std::time::Duration; use thiserror::Error as ThisError; -use libp2p_core::PeerId; -use fluence_keypair::public_key::peer_id_to_fluence_pk; -use std::str::FromStr; -use fluence_keypair::signature::RawSignature; -use crate::dto::DtoConversionError::PeerIdDecodeError; #[derive(ThisError, Debug)] pub enum DtoConversionError { @@ -73,11 +73,15 @@ impl TryFrom for trust_graph::Trust { type Error = DtoConversionError; fn try_from(t: Trust) -> Result { - let issued_for = peer_id_to_fluence_pk(PeerId::from_str(&t.issued_for) - .map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?) - .map_err(|e| DtoConversionError::PeerIdDecodeError(e.to_string()))?; + let issued_for = peer_id_to_fluence_pk( + PeerId::from_str(&t.issued_for).map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?, + ) + .map_err(|e| DtoConversionError::PeerIdDecodeError(e.to_string()))?; let signature = bs58::decode(&t.signature).into_vec()?; - let signature = Signature::from_raw_signature(RawSignature { bytes: signature, sig_type: t.sig_type })?; + let signature = Signature::from_raw_signature(RawSignature { + bytes: signature, + sig_type: t.sig_type, + })?; let expires_at = Duration::from_secs(t.expires_at); let issued_at = Duration::from_secs(t.issued_at); return Ok(trust_graph::Trust { @@ -105,3 +109,63 @@ impl From for Trust { }; } } + +#[marine] +#[derive(Default)] +pub struct Revoke { + /// who is revoked + pub revoked_peer_id: String, + /// date when revocation was created + pub revoked_at: u64, + /// Signature of a previous trust in a chain. + /// Signature is self-signed if it is a root trust, base58 + pub signature: String, + pub sig_type: String, + /// the issuer of this revocation, base58 peer id + pub revoked_by: String, +} + +impl TryFrom for trust_graph::Revoke { + type Error = DtoConversionError; + + fn try_from(r: Revoke) -> Result { + let revoked_pk = peer_id_to_fluence_pk( + PeerId::from_str(&r.revoked_peer_id) + .map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?, + ) + .map_err(|e| DtoConversionError::PeerIdDecodeError(e.to_string()))?; + let revoked_by_pk = peer_id_to_fluence_pk( + PeerId::from_str(&r.revoked_by).map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?, + ) + .map_err(|e| DtoConversionError::PeerIdDecodeError(e.to_string()))?; + let signature = bs58::decode(&r.signature).into_vec()?; + let signature = Signature::from_raw_signature(RawSignature { + bytes: signature, + sig_type: r.sig_type, + })?; + let revoked_at = Duration::from_secs(r.revoked_at); + return Ok(trust_graph::Revoke { + pk: revoked_pk, + revoked_at, + revoked_by: revoked_by_pk, + signature, + }); + } +} + +impl From for Revoke { + fn from(r: trust_graph::Revoke) -> Self { + let revoked_by = r.revoked_by.to_peer_id().to_base58(); + let revoked_peer_id = r.pk.to_peer_id().to_base58(); + let raw_signature = r.signature.get_raw_signature(); + let signature = bs58::encode(raw_signature.bytes).into_string(); + let revoked_at = r.revoked_at.as_secs(); + return Revoke { + revoked_peer_id, + revoked_at, + signature, + sig_type: raw_signature.sig_type, + revoked_by, + }; + } +} diff --git a/service/src/results.rs b/service/src/results.rs index 3347c80..fa1b61b 100644 --- a/service/src/results.rs +++ b/service/src/results.rs @@ -1,4 +1,4 @@ -use crate::dto::{Certificate, Trust}; +use crate::dto::{Certificate, Revoke, Trust}; use crate::service_impl::ServiceError; use marine_rs_sdk::marine; @@ -187,3 +187,72 @@ impl From> for AddTrustResult { } } } + +#[marine] +pub struct GetRevokeBytesResult { + pub success: bool, + pub error: String, + pub result: Vec, +} + +impl From, ServiceError>> for GetRevokeBytesResult { + fn from(result: Result, ServiceError>) -> Self { + match result { + Ok(res) => GetRevokeBytesResult { + success: true, + error: "".to_string(), + result: res, + }, + Err(e) => GetRevokeBytesResult { + success: false, + error: format!("{}", e), + result: vec![], + }, + } + } +} + +#[marine] +pub struct IssueRevocationResult { + pub success: bool, + pub error: String, + pub revoke: Revoke, +} + +impl From> for IssueRevocationResult { + fn from(result: Result) -> Self { + match result { + Ok(revoke) => IssueRevocationResult { + success: true, + error: "".to_string(), + revoke, + }, + Err(e) => IssueRevocationResult { + success: false, + error: format!("{}", e), + revoke: Revoke::default(), + }, + } + } +} + +#[marine] +pub struct RevokeResult { + pub success: bool, + pub error: String, +} + +impl From> for RevokeResult { + fn from(result: Result<(), ServiceError>) -> Self { + match result { + Ok(()) => RevokeResult { + success: true, + error: "".to_string(), + }, + Err(e) => RevokeResult { + success: false, + error: format!("{}", e), + }, + } + } +} diff --git a/service/src/service_api.rs b/service/src/service_api.rs index 3874dc5..439651e 100644 --- a/service/src/service_api.rs +++ b/service/src/service_api.rs @@ -1,11 +1,13 @@ -use crate::dto::{Certificate, Trust}; +use crate::dto::{Certificate, Revoke, Trust}; use crate::results::{ - AddRootResult, AddTrustResult, AllCertsResult, GetTrustBytesResult, InsertResult, - IssueTrustResult, VerifyTrustResult, WeightResult, + AddRootResult, AddTrustResult, AllCertsResult, GetRevokeBytesResult, GetTrustBytesResult, + InsertResult, IssueRevocationResult, IssueTrustResult, RevokeResult, VerifyTrustResult, + WeightResult, }; use crate::service_impl::{ - add_root_impl, add_trust_impl, get_all_certs_impl, get_trust_bytes_imp, get_weight_impl, - insert_cert_impl, insert_cert_impl_raw, issue_trust_impl, verify_trust_impl, + add_root_impl, add_trust_impl, get_all_certs_impl, get_revoke_bytes_impl, get_trust_bytes_imp, + get_weight_impl, insert_cert_impl, insert_cert_impl_raw, issue_revocation_impl, + issue_trust_impl, revoke_impl, verify_trust_impl, }; use marine_rs_sdk::{marine, CallParameters}; @@ -85,3 +87,29 @@ fn verify_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> Ver 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 get_revoke_bytes(revoked_peer_id: String, revoked_at: u64) -> GetRevokeBytesResult { + get_revoke_bytes_impl(revoked_peer_id, revoked_at).into() +} + +#[marine] +fn issue_revocation( + revoked_peer_id: String, + revoked_by_peer_id: String, + revoked_at_sec: u64, + signature_bytes: Vec, +) -> IssueRevocationResult { + issue_revocation_impl( + revoked_peer_id, + revoked_by_peer_id, + revoked_at_sec, + signature_bytes, + ) + .into() +} + +#[marine] +fn revoke(revoke: Revoke, timestamp_sec: u64) -> RevokeResult { + revoke_impl(revoke, timestamp_sec).into() +} diff --git a/service/src/service_impl.rs b/service/src/service_impl.rs index 66691d1..c40f47a 100644 --- a/service/src/service_impl.rs +++ b/service/src/service_impl.rs @@ -1,4 +1,4 @@ -use crate::dto::{Certificate, DtoConversionError, Trust}; +use crate::dto::{Certificate, DtoConversionError, Revoke, Trust}; use crate::service_impl::ServiceError::InvalidTimestampTetraplet; use crate::storage_impl::get_data; use fluence_keypair::error::DecodingError; @@ -7,6 +7,7 @@ use fluence_keypair::{PublicKey, Signature}; use libp2p_core::PeerId; use marine_rs_sdk::CallParameters; use std::convert::{Into, TryInto}; +use std::iter::Rev; use std::str::FromStr; use std::time::Duration; use thiserror::Error as ThisError; @@ -199,3 +200,41 @@ pub fn add_trust_impl( ) .map_err(ServiceError::TGError) } + +pub fn get_revoke_bytes_impl( + revoked_peer_id: String, + revoked_at: u64, +) -> Result, ServiceError> { + let public_key = extract_public_key(revoked_peer_id)?; + Ok(trust_graph::Revoke::signature_bytes( + &public_key, + Duration::from_secs(revoked_at), + )) +} + +pub fn issue_revocation_impl( + revoked_peer_id: String, + revoked_by_peer_id: String, + revoked_at_sec: u64, + signature_bytes: Vec, +) -> Result { + let revoked_pk = extract_public_key(revoked_peer_id)?; + let revoked_by_pk = extract_public_key(revoked_by_peer_id)?; + + let revoked_at = Duration::from_secs(revoked_at_sec); + let signature = Signature::from_bytes_with_public_key(&revoked_by_pk, signature_bytes); + Ok(trust_graph::Revoke::new(revoked_pk, revoked_by_pk, revoked_at, signature).into()) +} + +pub fn revoke_impl(revoke: Revoke, timestamp_sec: u64) -> Result<(), ServiceError> { + check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?; + + // TODO: use error for revoke, not trust + if revoke.revoked_at > timestamp_sec { + return Err(ServiceError::InvalidTrustTimestamp); + } + + let mut tg = get_data().lock(); + + tg.revoke(revoke.try_into()?).map_err(ServiceError::TGError) +} diff --git a/service/src/tests.rs b/service/src/tests.rs index f7f0670..4b58c43 100644 --- a/service/src/tests.rs +++ b/service/src/tests.rs @@ -44,11 +44,8 @@ mod tests { macro_rules! issue_trust { ($trust_graph:expr, $issuer_kp:expr, $issued_peer_id: expr, $expires_at:expr, $issued_at: expr) => {{ - let trust_metadata_result = $trust_graph.get_trust_metadata( - $issued_peer_id.to_base58(), - $expires_at, - $issued_at, - ); + let trust_metadata_result = + $trust_graph.get_trust_bytes($issued_peer_id.to_base58(), $expires_at, $issued_at); assert_result!(trust_metadata_result); let metadata = trust_metadata_result.result; diff --git a/src/revoke.rs b/src/revoke.rs index fa69d03..41411fa 100644 --- a/src/revoke.rs +++ b/src/revoke.rs @@ -19,6 +19,7 @@ use fluence_keypair::key_pair::KeyPair; use fluence_keypair::public_key::PublicKey; use fluence_keypair::signature::Signature; use serde::{Deserialize, Serialize}; +use sha2::Digest; use std::time::Duration; use thiserror::Error as ThisError; @@ -28,7 +29,7 @@ pub enum RevokeError { IncorrectSignature( #[from] #[source] - fluence_keypair::error::SigningError + fluence_keypair::error::SigningError, ), } @@ -43,12 +44,12 @@ pub struct Revoke { /// the issuer of this revocation pub revoked_by: PublicKey, /// proof of this revocation - signature: Signature, + pub signature: Signature, } impl Revoke { #[allow(dead_code)] - fn new( + pub fn new( pk: PublicKey, revoked_by: PublicKey, revoked_at: Duration, @@ -71,14 +72,14 @@ impl Revoke { Revoke::new(to_revoke, revoker.public(), revoked_at, signature) } - fn signature_bytes(pk: &PublicKey, revoked_at: Duration) -> Vec { - let mut msg = Vec::new(); + pub fn signature_bytes(pk: &PublicKey, revoked_at: Duration) -> Vec { + let mut metadata = Vec::new(); let pk_bytes = &pk.encode(); - msg.push(pk_bytes.len() as u8); - msg.extend(pk_bytes); - msg.extend_from_slice(&(revoked_at.as_secs() as u64).to_le_bytes()); + metadata.push(pk_bytes.len() as u8); + metadata.extend(pk_bytes); + metadata.extend_from_slice(&(revoked_at.as_secs() as u64).to_le_bytes()); - msg + sha2::Sha256::digest(&metadata).to_vec() } /// Verifies that revocation is cryptographically correct. @@ -87,7 +88,8 @@ impl Revoke { revoke .revoked_by - .verify(msg.as_slice(), &revoke.signature).map_err(IncorrectSignature) + .verify(msg.as_slice(), &revoke.signature) + .map_err(IncorrectSignature) } }