tpfs_krypt 7.1.8

An interface for accessing secrets
Documentation
//! This module contains error related items for the `tpfs_krypt` crate.

use serde::Serialize;
use snafu::Snafu;
use std::error::Error;
use std::fmt::{self, Debug, Display};
use std::sync::Arc;

/// The Errors that can occur when working with KeyManagement in the `tpfs_krypt` crate.
#[derive(Clone, Debug, Serialize, Snafu)]
#[snafu(visibility(pub))]
pub enum KeyManagementError {
    /// An address wasn't found.
    #[snafu(display("Address not found in key manager: {}", address))]
    AddressNotFound {
        /// The address that was not found.
        address: String,
    },

    /// Decoding from base58 caused an error due to characters being not base58.
    #[snafu(display("Error base58 decoding a public key {} due to {}", address, source))]
    Base58FromError {
        /// The source error from base58.
        #[snafu(source(from(base58::FromBase58Error, ExternalErrorWrapper::from_debug)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: ExternalErrorWrapper<String>,

        /// The public key in base58 format.
        address: String,
    },

    /// Decoding from base64 caused an error due to characters being not base64.
    /// Should not print to logs for this since the data is a secret.
    #[snafu(display("Error base64 decoding a secret {}", source))]
    #[snafu(context(false))]
    #[cfg(feature = "hashicorp-vault")]
    Base64DecodeError {
        /// The source error from base64.
        #[snafu(source(from(base64::DecodeError, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<base64::DecodeError>,
    },

    /// Error occurred when converting to entropy to bip39 mnemonic phrase.
    #[snafu(display("Error converting bip39 from entropy, {}, {}", message, source))]
    Bip39EntropyConversionError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(failure::Compat<failure::Error>, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<failure::Compat<failure::Error>>,
        /// A message for where the bip39 entropy conversion occurred.
        message: String,
    },

    /// Error converting from dynamic number of bytes to expected bytes.
    #[snafu(display("Error converting bytes: {}", message))]
    ByteConversionError {
        /// The context for what byte conversion was attempted.
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        message: String,
    },

    /// Error occurred from configuration.
    #[snafu(display("Config Error: {}", source))]
    #[snafu(context(false))]
    ConfigError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(cfg::ConfigError, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<cfg::ConfigError>,
    },

    /// Could not find the config folder.
    #[snafu(display("Config Folder Not Found: {}", path))]
    ConfigFolderNotFound {
        /// The path where the folder was not found.
        path: String,
    },

    /// Error when attempting to deserialize configuration.
    #[snafu(display("Config deserialization Error: {}", message))]
    ConfigDeserializationError {
        /// The message of the error that occurred on deserialization.
        message: String,
    },

    /// For Scenarios where derivations are not supported for a given key type.
    #[snafu(display("Derivations are not supported for this key type {}", key_type))]
    DerivationsNotSupported {
        /// The key_type that is not supported.
        key_type: crate::KeyType,
    },

    /// Characters found to not be utf8.
    /// Should not print to logs for this since the data could be a secret.
    #[snafu(display(
        "Error in converting to a utf8 string after decoding from base64 {}",
        source
    ))]
    #[snafu(context(false))]
    FromUtf8DecodingError {
        /// The originating error in string::FromUtf8Error.
        #[snafu(source(from(std::string::FromUtf8Error, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<std::string::FromUtf8Error>,
    },

    /// An error from the Vault Client.
    #[snafu(display("Hashicorp Vault Client Error: {}", source))]
    #[snafu(context(false))]
    #[cfg(feature = "hashicorp-vault")]
    HashicorpVaultError {
        /// The error from the client.
        #[snafu(source(from(hashicorp_vault::client::error::Error, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<hashicorp_vault::client::error::Error>,
    },

    /// Invalid Directory specified.
    #[snafu(display("Invalid Directory Path: {}", path))]
    InvalidDirectoryPath {
        /// The path that was invalid.
        path: String,
    },

    /// An IO Error occurred most likely due to accessing the file system.
    #[snafu(display("I/O Error"))]
    IoError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(std::io::Error, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<std::io::Error>,
        /// A message for the context of where the io error occurred.
        message: String,
    },

    /// Json Error due to either serialization or deserialization.
    #[snafu(display("JSON Error"))]
    JsonError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(serde_json::Error, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<serde_json::Error>,
        /// A message for the context of where the json serialization or deserialization occurred.
        message: String,
    },

    /// An error from rand core.
    #[snafu(display("Rand crate error."))]
    #[snafu(context(false))]
    RandError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(rand::Error, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<rand::Error>,
    },

    /// Exactly as it sounds and error type in ring that is considered Unspecified.
    #[snafu(display("Ring returned an error, but there is no details associated with it."))]
    #[snafu(context(false))]
    RingUnspecifiedError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(ring::error::Unspecified, ExternalErrorWrapper::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: ExternalErrorWrapper<ring::error::Unspecified>,
    },

    /// Neither address used to create the shared secret was
    /// found in the KeyManager.
    #[snafu(display("At least one of the addresses supplied must be contained within the KeyManager to create a shared key: {} {}", address, other_address))]
    SharedEncryptionAddressesNotFound {
        /// One of the addresses which wasn't found.
        address: String,
        /// The other address which wasn't found.
        other_address: String,
    },

    /// Not All Keys support shared encryption.
    #[snafu(display(
        "Being able to create a shared encryption key is not supported by this key type: {}",
        key_type
    ))]
    SharedEncryptionNotSupported {
        /// The key_type that is not supported.
        key_type: crate::KeyType,
    },

    /// Not All Keys support signing.
    #[snafu(display("Being able to sign is not supported by this key type: {}", key_type))]
    SigningNotSupported {
        /// The key_type that is not supported.
        key_type: crate::KeyType,
    },

    /// Error when attempting to work with derivation paths in ed25519.
    #[snafu(display("Error deriving path substrate ed25519 path: {}", source))]
    #[snafu(context(false))]
    SubstrateEd25519DeriveError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(
            sp_core::ed25519::DeriveError,
            ExternalErrorWrapper::from_ed25519_derive_error
        )))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: ExternalErrorWrapper<String>,
    },

    /// Error when attempting to work with derivation paths in sr25519.
    #[snafu(display("Error deriving path substrate sr25519 path: {}", source))]
    #[snafu(context(false))]
    SubstrateSr25519DeriveError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(
            sp_core::crypto::Infallible,
            ExternalErrorWrapper::from_sr25519_derive_error
        )))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: ExternalErrorWrapper<String>,
    },

    /// Error when working with a secret string from substrate.
    #[snafu(display(
        "Error when attempting to convert the secret string using substrate: {:?}",
        source
    ))]
    #[snafu(context(false))]
    SubstrateSecretStringError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(sp_core::crypto::SecretStringError, ExternalErrorWrapper::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: ExternalErrorWrapper<sp_core::crypto::SecretStringError>,
    },

    /// Error converting to a public address from substrate.
    #[snafu(display("Error attempting to convert public address to ss58."))]
    SubstrateSs58TryFromError,

    /// Error when performing a conversion from ss58 to a public address.
    #[snafu(display("Error converting address {:?} from ss58: {:?}", address, source))]
    SubstrateSs58ConversionError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(sp_core::crypto::PublicError, ExternalErrorWrapper::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: ExternalErrorWrapper<sp_core::crypto::PublicError>,
        /// The address that had issues with a conversion.
        address: Option<String>,
    },

    /// Error when working with substrate bip39 conversion.
    #[snafu(display("Error Invalid Entropy in substrate_bip39 call: {:?}", source))]
    #[snafu(context(false))]
    SubstrateEntropyConversionError {
        /// The encapsulated error from a different package.
        #[snafu(source(from(substrate_bip39::Error, ExternalErrorWrapper::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: ExternalErrorWrapper<substrate_bip39::Error>,
    },

    /// Error when parsing urls for external requests
    #[snafu(display("Error parsing url: {:?}", source))]
    #[snafu(context(false))]
    #[cfg(feature = "hashicorp-vault")]
    UrlParsingError {
        /// The encapsulated error from Url.
        #[snafu(source(from(url::ParseError, Arc::new)))]
        #[serde(serialize_with = "tpfs_logger_extensions::snafu_extensions::debug_serialize")]
        source: Arc<url::ParseError>,
    },

    /// Raised if a pubkey of the wrong size is provided as the "other half" of shared encryption
    #[snafu(display("The provided public key for shared encryption was the wrong size. It was {} bytes but must be {} bytes", length, must_be))]
    SharedEncryptionOtherPublicKeyWrongSize {
        /// The length of the provided pubkey in bytes
        length: usize,
        /// How long it should've been
        must_be: usize,
    },
}

/// The default Result for working with a KeyManagementError.
pub type Result<T, E = KeyManagementError> = std::result::Result<T, E>;

/// The struct helps convert errors that don't support the Error trait from
/// external packages.
#[derive(Clone, Debug)]
pub struct ExternalErrorWrapper<T> {
    /// The value of the external error that is being wrapped here.
    pub value: T,
}

impl<T> ExternalErrorWrapper<T> {
    fn new(value: T) -> Self {
        ExternalErrorWrapper { value }
    }
}

impl ExternalErrorWrapper<String> {
    fn from_debug<T>(value: T) -> Self
    where
        T: Debug,
    {
        ExternalErrorWrapper {
            value: format!("{:?}", value),
        }
    }
}

impl<T: Debug> Display for ExternalErrorWrapper<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Wrapped Error {:?}", self.value)
    }
}

impl<T: Debug> Error for ExternalErrorWrapper<T> {}

/// Special Use Case Handling for Substrate enums that don't have details.
impl ExternalErrorWrapper<String> {
    fn from_ed25519_derive_error(value: sp_core::ed25519::DeriveError) -> Self {
        let value_string = match value {
            sp_core::ed25519::DeriveError::SoftKeyInPath => String::from("SoftKeyInPath"),
        };
        ExternalErrorWrapper {
            value: value_string,
        }
    }

    fn from_sr25519_derive_error(_: sp_core::crypto::Infallible) -> Self {
        ExternalErrorWrapper {
            value: String::from("Substrate Sr25519 fails with Infallible enum."),
        }
    }
}