Skip to main content

password_hash/
error.rs

1//! Error types.
2
3use core::fmt;
4
5/// Result type.
6pub type Result<T> = core::result::Result<T, Error>;
7
8/// Password hashing errors.
9#[derive(Copy, Clone, Debug, Eq, PartialEq)]
10#[non_exhaustive]
11pub enum Error {
12    /// Unsupported algorithm.
13    Algorithm,
14
15    /// Cryptographic error.
16    Crypto,
17
18    /// Encoding errors (e.g. Base64).
19    EncodingInvalid,
20
21    /// Internal error within a password hashing library.
22    Internal,
23
24    /// Out of memory (heap allocation failure).
25    OutOfMemory,
26
27    /// Output size invalid.
28    OutputSize,
29
30    /// Invalid named parameter.
31    ParamInvalid {
32        /// Parameter name.
33        name: &'static str,
34    },
35
36    /// Invalid parameters.
37    ParamsInvalid,
38
39    /// Invalid password.
40    PasswordInvalid,
41
42    /// Random number generator failure.
43    RngFailure,
44
45    /// Invalid salt.
46    SaltInvalid,
47
48    /// Invalid algorithm version.
49    Version,
50}
51
52impl fmt::Display for Error {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
54        match self {
55            Self::Algorithm => write!(f, "unsupported algorithm"),
56            Self::Crypto => write!(f, "cryptographic error"),
57            Self::EncodingInvalid => write!(f, "invalid encoding"),
58            Self::Internal => write!(f, "internal password hashing algorithm error"),
59            Self::OutOfMemory => write!(f, "out of memory"),
60            Self::OutputSize => write!(f, "password hash output size invalid"),
61            Self::ParamInvalid { name } => write!(f, "invalid parameter: {name:?}"),
62            Self::ParamsInvalid => write!(f, "invalid parameters"),
63            Self::PasswordInvalid => write!(f, "invalid password"),
64            Self::RngFailure => write!(f, "rng failure"),
65            Self::SaltInvalid => write!(f, "invalid salt"),
66            Self::Version => write!(f, "invalid algorithm version"),
67        }
68    }
69}
70
71impl core::error::Error for Error {}
72
73#[cfg(feature = "getrandom")]
74impl From<getrandom::Error> for Error {
75    fn from(_: getrandom::Error) -> Self {
76        Error::RngFailure
77    }
78}
79
80#[cfg(feature = "phc")]
81impl From<phc::Error> for Error {
82    fn from(err: phc::Error) -> Self {
83        match err {
84            phc::Error::Base64(_) | phc::Error::MissingField | phc::Error::TrailingData => {
85                Self::EncodingInvalid
86            }
87            phc::Error::OutputSize { .. } => Self::OutputSize,
88            phc::Error::ParamNameDuplicated
89            | phc::Error::ParamNameInvalid
90            | phc::Error::ParamValueTooLong
91            | phc::Error::ParamsMaxExceeded
92            | phc::Error::ValueTooLong => Self::ParamsInvalid,
93            phc::Error::SaltTooShort | phc::Error::SaltTooLong => Self::SaltInvalid,
94            _ => Self::Internal, // Branch since `phc::Error` is `non_exhaustive`
95        }
96    }
97}