1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! Error type.

use std::fmt;
use std::io;

/// The various errors that can be returned during the decryption process.
#[derive(Debug)]
pub enum Error {
    /// Seeking was attempted on an ASCII-armored encrypted message, which is unsupported.
    ArmoredWhenSeeking,
    /// The message failed to decrypt.
    DecryptionFailed,
    /// The message used an excessive work factor for passphrase encryption.
    ExcessiveWork {
        /// The work factor required to decrypt.
        required: u8,
        /// The target work factor for this device (around 1 second of work).
        target: u8,
    },
    /// The MAC in the message header was invalid.
    InvalidMac,
    /// An I/O error occurred during decryption.
    Io(io::Error),
    /// Failed to decrypt an encrypted key.
    KeyDecryptionFailed,
    /// The provided message requires keys to decrypt.
    MessageRequiresKeys,
    /// The provided message requires a passphrase to decrypt.
    MessageRequiresPassphrase,
    /// None of the provided keys could be used to decrypt the message.
    NoMatchingKeys,
    /// An unknown age format, probably from a newer version.
    UnknownFormat,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::ArmoredWhenSeeking => write!(f, "Armored messages not supported for seeking"),
            Error::DecryptionFailed => write!(f, "Decryption failed"),
            Error::ExcessiveWork { required, target } => {
                writeln!(f, "Excessive work parameter for passphrase.")?;
                write!(
                    f,
                    "Decryption would take around {} seconds.",
                    1 << (required - target)
                )
            }
            Error::InvalidMac => write!(f, "Header MAC is invalid"),
            Error::Io(e) => e.fmt(f),
            Error::KeyDecryptionFailed => write!(f, "Failed to decrypt an encrypted key"),
            Error::MessageRequiresKeys => write!(f, "This message requires keys to decrypt"),
            Error::MessageRequiresPassphrase => {
                write!(f, "This message requires a passphrase to decrypt")
            }
            Error::NoMatchingKeys => write!(f, "No matching keys found"),
            Error::UnknownFormat => {
                writeln!(f, "Unknown age format.")?;
                write!(f, "Have you tried upgrading to the latest version?")
            }
        }
    }
}

impl From<chacha20poly1305::aead::Error> for Error {
    fn from(_: chacha20poly1305::aead::Error) -> Self {
        Error::DecryptionFailed
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<hmac::crypto_mac::MacError> for Error {
    fn from(_: hmac::crypto_mac::MacError) -> Self {
        Error::InvalidMac
    }
}

#[cfg(feature = "unstable")]
impl From<rsa::errors::Error> for Error {
    fn from(_: rsa::errors::Error) -> Self {
        Error::DecryptionFailed
    }
}

impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Error::Io(inner) => Some(inner),
            _ => None,
        }
    }
}