casper_types/crypto/
error.rs

1use alloc::string::String;
2use core::fmt::{self, Display, Formatter};
3#[cfg(any(feature = "std", feature = "testing", test))]
4use std::error::Error as StdError;
5
6#[cfg(feature = "datasize")]
7use datasize::DataSize;
8use ed25519_dalek::ed25519::Error as SignatureError;
9#[cfg(any(feature = "std", test))]
10use pem::PemError;
11use serde::Serialize;
12#[cfg(any(feature = "std", feature = "testing", test))]
13use thiserror::Error;
14
15#[cfg(any(feature = "std-fs-io", test))]
16use crate::file_utils::{ReadFileError, WriteFileError};
17
18/// Cryptographic errors.
19#[derive(Clone, Eq, PartialEq, Debug, Serialize)]
20#[cfg_attr(feature = "datasize", derive(DataSize))]
21#[non_exhaustive]
22//Default is needed only in testing to meet EnumIter needs
23#[cfg_attr(any(feature = "testing", test), derive(Default))]
24pub enum Error {
25    /// Error resulting from creating or using asymmetric key types.
26    AsymmetricKey(String),
27
28    /// Error resulting when decoding a type from a hex-encoded representation.
29    #[serde(with = "serde_helpers::Base16DecodeError")]
30    #[cfg_attr(feature = "datasize", data_size(skip))]
31    FromHex(base16::DecodeError),
32
33    /// Error resulting when decoding a type from a base64 representation.
34    #[serde(with = "serde_helpers::Base64DecodeError")]
35    #[cfg_attr(feature = "datasize", data_size(skip))]
36    FromBase64(base64::DecodeError),
37
38    /// Signature error.
39    #[cfg_attr(any(feature = "testing", test), default)]
40    SignatureError,
41
42    /// Error trying to manipulate the system key.
43    System(String),
44}
45
46impl Display for Error {
47    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
48        match self {
49            Error::AsymmetricKey(error_msg) => {
50                write!(formatter, "asymmetric key error: {}", error_msg)
51            }
52            Error::FromHex(error) => {
53                write!(formatter, "decoding from hex: {}", error)
54            }
55            Error::FromBase64(error) => {
56                write!(formatter, "decoding from base 64: {}", error)
57            }
58            Error::SignatureError => {
59                write!(formatter, "error in signature")
60            }
61            Error::System(error_msg) => {
62                write!(formatter, "invalid operation on system key: {}", error_msg)
63            }
64        }
65    }
66}
67
68impl From<base16::DecodeError> for Error {
69    fn from(error: base16::DecodeError) -> Self {
70        Error::FromHex(error)
71    }
72}
73
74impl From<SignatureError> for Error {
75    fn from(_error: SignatureError) -> Self {
76        Error::SignatureError
77    }
78}
79
80#[cfg(any(feature = "std", feature = "testing", test))]
81impl StdError for Error {
82    fn source(&self) -> Option<&(dyn StdError + 'static)> {
83        match self {
84            Error::FromHex(error) => Some(error),
85            Error::FromBase64(error) => Some(error),
86            Error::AsymmetricKey(_) | Error::SignatureError | Error::System(_) => None,
87        }
88    }
89}
90
91/// Cryptographic errors extended with some additional variants.
92#[cfg(any(feature = "std", feature = "testing", test))]
93#[derive(Debug, Error)]
94#[non_exhaustive]
95pub enum ErrorExt {
96    /// A basic crypto error.
97    #[error("crypto error: {0:?}")]
98    CryptoError(#[from] Error),
99
100    /// Error trying to read a secret key.
101    #[cfg(any(feature = "std-fs-io", test))]
102    #[error("secret key load failed: {0}")]
103    SecretKeyLoad(ReadFileError),
104
105    /// Error trying to read a public key.
106    #[cfg(any(feature = "std-fs-io", test))]
107    #[error("public key load failed: {0}")]
108    PublicKeyLoad(ReadFileError),
109
110    /// Error trying to write a secret key.
111    #[cfg(any(feature = "std-fs-io", test))]
112    #[error("secret key save failed: {0}")]
113    SecretKeySave(WriteFileError),
114
115    /// Error trying to write a public key.
116    #[cfg(any(feature = "std-fs-io", test))]
117    #[error("public key save failed: {0}")]
118    PublicKeySave(WriteFileError),
119
120    /// Pem format error.
121    #[error("pem error: {0}")]
122    FromPem(String),
123
124    /// DER format error.
125    #[error("der error: {0}")]
126    FromDer(#[from] derp::Error),
127
128    /// Error in getting random bytes from the system's preferred random number source.
129    #[error("failed to get random bytes: {0}")]
130    GetRandomBytes(#[from] getrandom::Error),
131}
132
133#[cfg(any(feature = "std", test))]
134impl From<PemError> for ErrorExt {
135    fn from(error: PemError) -> Self {
136        ErrorExt::FromPem(error.to_string())
137    }
138}
139
140/// This module allows us to derive `Serialize` for the third party error types which don't
141/// themselves derive it.
142///
143/// See <https://serde.rs/remote-derive.html> for more info.
144#[allow(clippy::enum_variant_names)]
145mod serde_helpers {
146    use serde::Serialize;
147
148    #[derive(Serialize)]
149    #[serde(remote = "base16::DecodeError")]
150    pub(super) enum Base16DecodeError {
151        InvalidByte { index: usize, byte: u8 },
152        InvalidLength { length: usize },
153    }
154
155    #[derive(Serialize)]
156    #[serde(remote = "base64::DecodeError")]
157    pub(super) enum Base64DecodeError {
158        #[allow(dead_code)]
159        InvalidByte(usize, u8),
160        InvalidLength,
161        #[allow(dead_code)]
162        InvalidLastSymbol(usize, u8),
163    }
164}