//! Signature error types use core::fmt::{self, Debug, Display}; #[cfg(feature = "std")] use std::boxed::Box; /// Result type. /// /// A result with the `signature` crate's [`Error`] type. pub type Result = core::result::Result; /// Signature errors. /// /// This type is deliberately opaque as to avoid sidechannel leakage which /// could potentially be used recover signing private keys or forge signatures /// (e.g. [BB'06]). /// /// When the `std` feature is enabled, it impls [`std::error::Error`] and /// supports an optional [`std::error::Error::source`], which can be used by /// things like remote signers (e.g. HSM, KMS) to report I/O or auth errors. /// /// [BB'06]: https://en.wikipedia.org/wiki/Daniel_Bleichenbacher #[derive(Default)] #[non_exhaustive] pub struct Error { /// Source of the error (if applicable). #[cfg(feature = "std")] source: Option>, } impl Error { /// Create a new error with no associated source pub fn new() -> Self { Self::default() } /// Create a new error with an associated source. /// /// **NOTE:** The "source" should **NOT** be used to propagate cryptographic /// errors e.g. signature parsing or verification errors. The intended use /// cases are for propagating errors related to external signers, e.g. /// communication/authentication errors with HSMs, KMS, etc. #[cfg(feature = "std")] pub fn from_source( source: impl Into>, ) -> Self { Self { source: Some(source.into()), } } } impl Debug for Error { #[cfg(not(feature = "std"))] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("signature::Error {}") } #[cfg(feature = "std")] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("signature::Error { source: ")?; if let Some(source) = &self.source { write!(f, "Some({})", source)?; } else { f.write_str("None")?; } f.write_str(" }") } } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("signature error")?; #[cfg(feature = "std")] { if let Some(source) = &self.source { write!(f, ": {}", source)?; } } Ok(()) } } #[cfg(feature = "std")] impl From> for Error { fn from(source: Box) -> Error { Self::from_source(source) } } #[cfg(feature = "rand_core")] impl From for Error { #[cfg(not(feature = "std"))] fn from(_source: rand_core::Error) -> Error { Error::new() } #[cfg(feature = "std")] fn from(source: rand_core::Error) -> Error { Error::from_source(source) } } #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { self.source .as_ref() .map(|source| source.as_ref() as &(dyn std::error::Error + 'static)) } }