diff --git a/Cargo.lock b/Cargo.lock index 191ca4f..1ec8e00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -406,6 +406,7 @@ dependencies = [ "serde_json", "serde_with", "signature", + "thiserror", ] [[package]] diff --git a/identity/Cargo.lock b/identity/Cargo.lock index 59a3460..244fe4a 100644 --- a/identity/Cargo.lock +++ b/identity/Cargo.lock @@ -344,6 +344,7 @@ dependencies = [ "serde_json", "serde_with", "signature", + "thiserror", ] [[package]] diff --git a/identity/Cargo.toml b/identity/Cargo.toml index fb6f25e..05b335d 100644 --- a/identity/Cargo.toml +++ b/identity/Cargo.toml @@ -16,3 +16,4 @@ rand = "0.7.0" signature = "1.3.0" ed25519 = "1.0.3" serde_with = "1.6.0" +thiserror = "1.0.23" diff --git a/identity/src/key_pair.rs b/identity/src/key_pair.rs index d0e05ce..06a4b54 100644 --- a/identity/src/key_pair.rs +++ b/identity/src/key_pair.rs @@ -79,11 +79,10 @@ impl KeyPair { } /// Verify the Ed25519 signature on a message using the public key. - pub fn verify(pk: &PublicKey, msg: &[u8], signature: &Signature) -> Result<(), String> { + pub fn verify(pk: &PublicKey, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> { // let signature = ed25519_dalek::Signature::from_bytes(signature) // .map_err(|err| format!("Cannot convert bytes to a signature: {:?}", err))?; pk.verify_strict(msg, signature) - .map_err(|err| format!("Signature verification failed: {:?}", err)) } } diff --git a/identity/src/public_key.rs b/identity/src/public_key.rs index be2ffa5..edac73d 100644 --- a/identity/src/public_key.rs +++ b/identity/src/public_key.rs @@ -14,10 +14,20 @@ * limitations under the License. */ +use crate::public_key::PKError::{FromBase58Error, FromBytesError}; use crate::signature::Signature; use core::fmt::Debug; use ed25519_dalek::SignatureError; use serde::{Deserialize, Serialize}; +use thiserror::Error as ThisError; + +#[derive(ThisError, Debug)] +pub enum PKError { + #[error("Cannot decode public key from bytes: {0}")] + FromBytesError(SignatureError), + #[error("Cannot decode public key from base58 format: {0}")] + FromBase58Error(bs58::decode::Error), +} #[derive(Copy, Clone, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct PublicKey(pub(crate) ed25519_dalek::PublicKey); @@ -37,9 +47,13 @@ impl PublicKey { self.0.verify_strict(message, &signature.0) } - pub fn from_bytes(bytes: &[u8]) -> Result { - let pk = ed25519_dalek::PublicKey::from_bytes(bytes)?; + pub fn from_base58(str: &str) -> Result { + let bytes = bs58::decode(str).into_vec().map_err(FromBase58Error)?; + Self::from_bytes(&bytes) + } + pub fn from_bytes(bytes: &[u8]) -> Result { + let pk = ed25519_dalek::PublicKey::from_bytes(bytes).map_err(FromBytesError)?; Ok(PublicKey(pk)) } diff --git a/identity/src/signature.rs b/identity/src/signature.rs index 650f4d4..a65355c 100644 --- a/identity/src/signature.rs +++ b/identity/src/signature.rs @@ -15,6 +15,7 @@ */ use serde::{Deserialize, Serialize}; +use signature::Error as SigError; use signature::Signature as SigSignature; #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -33,8 +34,8 @@ impl Signature { self.0.to_bytes() } - pub fn from_bytes(bytes: &[u8]) -> Result { - let sig = ed25519_dalek::Signature::from_bytes(bytes).map_err(|err| err.to_string())?; + pub fn from_bytes(bytes: &[u8]) -> Result { + let sig = ed25519_dalek::Signature::from_bytes(bytes)?; Ok(Signature(sig)) } } diff --git a/src/lib.rs b/src/lib.rs index 53cce51..3e04635 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,11 +36,11 @@ mod trust_graph; mod trust_graph_storage; mod trust_node; -pub use crate::certificate::Certificate; +pub use crate::certificate::{Certificate, CertificateError}; pub use crate::misc::current_time; pub use crate::public_key_hashable::PublicKeyHashable; pub use crate::revoke::Revoke; pub use crate::trust::Trust; -pub use crate::trust_graph::{TrustGraph, Weight}; +pub use crate::trust_graph::{TrustGraph, TrustGraphError, Weight}; pub use crate::trust_graph_storage::{Storage, StorageError}; pub use crate::trust_node::{Auth, TrustNode}; diff --git a/src/public_key_hashable.rs b/src/public_key_hashable.rs index 0bc0dea..809a37c 100644 --- a/src/public_key_hashable.rs +++ b/src/public_key_hashable.rs @@ -14,11 +14,9 @@ * limitations under the License. */ -use fluence_identity::public_key::PublicKey; +use fluence_identity::public_key::{PKError, PublicKey}; -use crate::public_key_hashable::PkError::{Base58DecodeError, BytesDecodeError}; use core::fmt; -use ed25519_dalek::SignatureError; use ref_cast::RefCast; use serde::ser::Serializer; use std::str::FromStr; @@ -26,7 +24,6 @@ use std::{ fmt::{Display, Formatter}, hash::{Hash, Hasher}, }; -use thiserror::Error as ThisError; /// Wrapper to use PublicKey in HashMap #[derive(PartialEq, Eq, Debug, Clone, RefCast)] @@ -84,23 +81,11 @@ impl Display for PublicKeyHashable { } } -#[derive(ThisError, Debug)] -pub enum PkError { - #[error("Invalid string '{0}': {1}")] - Base58DecodeError(String, bs58::decode::Error), - #[error("Invalid bytes {0:?}: {1}")] - BytesDecodeError(Vec, SignatureError), -} - impl FromStr for PublicKeyHashable { - type Err = PkError; + type Err = PKError; fn from_str(s: &str) -> Result { - let bytes = bs58::decode(s) - .into_vec() - .map_err(|err| Base58DecodeError(s.to_string(), err))?; - - let pk = PublicKey::from_bytes(&bytes).map_err(|err| BytesDecodeError(bytes, err))?; + let pk = PublicKey::from_base58(s)?; Ok(PublicKeyHashable::from(pk)) } } diff --git a/src/trust.rs b/src/trust.rs index df45aa0..5336cd7 100644 --- a/src/trust.rs +++ b/src/trust.rs @@ -14,10 +14,12 @@ * limitations under the License. */ -use crate::trust::TrustError::{DecodeError, SignatureError}; +use crate::trust::TrustError::{ + DecodeError, IncorrectTrustLength, PublicKeyError, SignatureError, SignatureFromBytesError, +}; use derivative::Derivative; use fluence_identity::key_pair::KeyPair; -use fluence_identity::public_key::PublicKey; +use fluence_identity::public_key::{PKError, PublicKey}; use fluence_identity::signature::Signature; use serde::{Deserialize, Serialize}; use std::convert::TryInto; @@ -65,11 +67,22 @@ pub enum TrustError { /// Errors occured on signature verification #[error("{0}")] - SignatureError(String), + SignatureError(ed25519_dalek::SignatureError), /// Errors occured on trust decoding from differrent formats #[error("{0}")] DecodeError(String), + + #[error("Cannot decode a signature from bytes: {0}")] + SignatureFromBytesError(signature::Error), + + #[error("{0}")] + PublicKeyError(PKError), + + #[error( + "Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {0}" + )] + IncorrectTrustLength(usize), } impl Trust { @@ -155,19 +168,13 @@ impl Trust { #[allow(dead_code)] pub fn decode(arr: &[u8]) -> Result { if arr.len() != TRUST_LEN { - return Err(DecodeError( - format!("Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {}", - arr.len()) - )); + return Err(IncorrectTrustLength(arr.len())); } - let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(|err| { - DecodeError(format!("Cannot decode a public key: {}", err.to_string())) - })?; + let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(PublicKeyError)?; let signature = &arr[PK_LEN..PK_LEN + SIG_LEN]; - let signature = Signature::from_bytes(signature) - .map_err(|err| DecodeError(format!("Cannot decode a signature: {}", err)))?; + let signature = Signature::from_bytes(signature).map_err(SignatureFromBytesError)?; 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()); @@ -221,7 +228,7 @@ impl Trust { // 64 bytes signature let signature = Self::bs58_str_to_vec(signature, "signature")?; - let signature = Signature::from_bytes(&signature).map_err(DecodeError)?; + let signature = Signature::from_bytes(&signature).map_err(SignatureFromBytesError)?; // Duration let expires_at = Self::str_to_duration(expires_at, "expires_at")?; diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 2eb3a9f..2e40478 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -441,6 +441,7 @@ dependencies = [ "serde_json", "serde_with", "signature", + "thiserror", ] [[package]] diff --git a/wasm/src/results.rs b/wasm/src/results.rs index fa8cdee..dce4cfd 100644 --- a/wasm/src/results.rs +++ b/wasm/src/results.rs @@ -1,4 +1,5 @@ use crate::dto::Certificate; +use crate::service_api::ServiceError; use fluence::fce; #[fce] @@ -7,8 +8,8 @@ pub struct InsertResult { pub error: String, } -impl From> for InsertResult { - fn from(result: Result<(), String>) -> Self { +impl From> for InsertResult { + fn from(result: Result<(), ServiceError>) -> Self { match result { Ok(()) => InsertResult { ret_code: 0, @@ -16,7 +17,7 @@ impl From> for InsertResult { }, Err(e) => InsertResult { ret_code: 1, - error: e, + error: format!("{}", e), }, } } @@ -29,8 +30,8 @@ pub struct WeightResult { pub error: String, } -impl From, String>> for WeightResult { - fn from(result: Result, String>) -> Self { +impl From, ServiceError>> for WeightResult { + fn from(result: Result, ServiceError>) -> Self { match result { Ok(wo) => WeightResult { ret_code: 0, @@ -40,7 +41,7 @@ impl From, String>> for WeightResult { Err(e) => WeightResult { ret_code: 1, weight: vec![], - error: e, + error: format!("{}", e), }, } } @@ -53,8 +54,8 @@ pub struct AllCertsResult { pub error: String, } -impl From, String>> for AllCertsResult { - fn from(result: Result, String>) -> Self { +impl From, ServiceError>> for AllCertsResult { + fn from(result: Result, ServiceError>) -> Self { match result { Ok(certs) => AllCertsResult { ret_code: 0, @@ -64,7 +65,7 @@ impl From, String>> for AllCertsResult { Err(e) => AllCertsResult { ret_code: 1, certificates: vec![], - error: e, + error: format!("{}", e), }, } } diff --git a/wasm/src/service_api.rs b/wasm/src/service_api.rs index 9ac8de7..e81a925 100644 --- a/wasm/src/service_api.rs +++ b/wasm/src/service_api.rs @@ -1,19 +1,33 @@ use crate::dto::Certificate; use crate::results::{AllCertsResult, InsertResult, WeightResult}; +use crate::service_api::ServiceError::{CertError, PublicKeyDecodeError, TGError}; use crate::storage_impl::get_data; use fluence::fce; +use fluence_identity::public_key::PKError; use fluence_identity::{KeyPair, PublicKey}; use std::convert::Into; use std::str::FromStr; use std::time::Duration; +use thiserror::Error as ThisError; +use trust_graph::{CertificateError, TrustGraphError}; -fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), String> { +#[derive(ThisError, Debug)] +pub enum ServiceError { + #[error("{0}")] + PublicKeyDecodeError(PKError), + + #[error("{0}")] + TGError(TrustGraphError), + #[error("{0}")] + CertError(CertificateError), +} + +fn insert_cert_impl(certificate: String, duration: u64) -> Result<(), ServiceError> { let duration = Duration::from_millis(duration); - let certificate = - trust_graph::Certificate::from_str(&certificate).map_err(|e| format!("{}", e))?; + let certificate = trust_graph::Certificate::from_str(&certificate).map_err(CertError)?; let mut tg = get_data().lock(); - tg.add(certificate, duration)?; + tg.add(certificate, duration).map_err(TGError)?; Ok(()) } @@ -23,12 +37,12 @@ fn insert_cert(certificate: String, duration: u64) -> InsertResult { insert_cert_impl(certificate, duration).into() } -fn get_weight_impl(public_key: String) -> Result, String> { +fn get_weight_impl(public_key: String) -> Result, ServiceError> { let tg = get_data().lock(); let public_key = string_to_public_key(public_key)?; - let weight = tg.weight(public_key)?; + let weight = tg.weight(public_key).map_err(TGError)?; Ok(weight) } @@ -38,12 +52,8 @@ fn get_weight(public_key: String) -> WeightResult { get_weight_impl(public_key).into() } -fn string_to_public_key(public_key: String) -> Result { - let public_key = bs58::decode(public_key) - .into_vec() - .map_err(|e| format!("Couldn't decode public_key from base58: {}", e))?; - let public_key = PublicKey::from_bytes(&public_key) - .map_err(|e| format!("Couldn't decode public_key: {}", e))?; +fn string_to_public_key(public_key: String) -> Result { + let public_key = PublicKey::from_base58(&public_key).map_err(PublicKeyDecodeError)?; Ok(public_key) } @@ -53,11 +63,11 @@ fn get_all_certs(issued_for: String) -> AllCertsResult { get_all_certs_impl(issued_for).into() } -fn get_all_certs_impl(issued_for: String) -> Result, String> { +fn get_all_certs_impl(issued_for: String) -> Result, ServiceError> { let tg = get_data().lock(); let public_key = string_to_public_key(issued_for)?; - let certs = tg.get_all_certs(public_key, &[])?; + let certs = tg.get_all_certs(public_key, &[]).map_err(TGError)?; Ok(certs.into_iter().map(|c| c.into()).collect()) }