1use std::fmt;
27
28#[derive(Debug)]
32pub enum CryptoError {
33 InvalidKeyLength {
39 algorithm: &'static str,
41 expected: usize,
43 got: usize,
45 },
46
47 InvalidKey(String),
52
53 InvalidNonceLength {
55 algorithm: &'static str,
57 expected: usize,
59 got: usize,
61 },
62
63 AuthenticationFailed,
70
71 Encryption(String),
75
76 Decryption(String),
78
79 Kdf(String),
81
82 Pqc(String),
84
85 ReedSolomon(String),
87
88 InvalidParameter(String),
90
91 Serialization(String),
93
94 Compression(String),
96
97 Io(std::io::Error),
99}
100
101impl fmt::Display for CryptoError {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 match self {
104 CryptoError::InvalidKeyLength {
105 algorithm,
106 expected,
107 got,
108 } => write!(
109 f,
110 "Invalid key length for {algorithm}: expected {expected} bytes, got {got}"
111 ),
112 CryptoError::InvalidKey(msg) => write!(f, "Invalid key: {msg}"),
113 CryptoError::InvalidNonceLength {
114 algorithm,
115 expected,
116 got,
117 } => write!(
118 f,
119 "Invalid nonce length for {algorithm}: expected {expected} bytes, got {got}"
120 ),
121 CryptoError::AuthenticationFailed => write!(
122 f,
123 "Authentication failed (wrong key, tampered data, or invalid signature)"
124 ),
125 CryptoError::Encryption(msg) => write!(f, "Encryption failed: {msg}"),
126 CryptoError::Decryption(msg) => write!(f, "Decryption failed: {msg}"),
127 CryptoError::Kdf(msg) => write!(f, "KDF error: {msg}"),
128 CryptoError::Pqc(msg) => write!(f, "PQC error: {msg}"),
129 CryptoError::ReedSolomon(msg) => write!(f, "Reed-Solomon error: {msg}"),
130 CryptoError::InvalidParameter(msg) => write!(f, "Invalid parameter: {msg}"),
131 CryptoError::Serialization(msg) => write!(f, "Serialization error: {msg}"),
132 CryptoError::Compression(msg) => write!(f, "Compression error: {msg}"),
133 CryptoError::Io(err) => write!(f, "I/O error: {err}"),
134 }
135 }
136}
137
138impl std::error::Error for CryptoError {
139 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
140 match self {
141 CryptoError::Io(err) => Some(err),
142 _ => None,
143 }
144 }
145}
146
147impl From<std::io::Error> for CryptoError {
148 fn from(err: std::io::Error) -> Self {
149 CryptoError::Io(err)
150 }
151}
152
153impl Clone for CryptoError {
154 fn clone(&self) -> Self {
155 match self {
156 CryptoError::InvalidKeyLength {
157 algorithm,
158 expected,
159 got,
160 } => CryptoError::InvalidKeyLength {
161 algorithm,
162 expected: *expected,
163 got: *got,
164 },
165 CryptoError::InvalidKey(msg) => CryptoError::InvalidKey(msg.clone()),
166 CryptoError::InvalidNonceLength {
167 algorithm,
168 expected,
169 got,
170 } => CryptoError::InvalidNonceLength {
171 algorithm,
172 expected: *expected,
173 got: *got,
174 },
175 CryptoError::AuthenticationFailed => CryptoError::AuthenticationFailed,
176 CryptoError::Encryption(msg) => CryptoError::Encryption(msg.clone()),
177 CryptoError::Decryption(msg) => CryptoError::Decryption(msg.clone()),
178 CryptoError::Kdf(msg) => CryptoError::Kdf(msg.clone()),
179 CryptoError::Pqc(msg) => CryptoError::Pqc(msg.clone()),
180 CryptoError::ReedSolomon(msg) => CryptoError::ReedSolomon(msg.clone()),
181 CryptoError::InvalidParameter(msg) => CryptoError::InvalidParameter(msg.clone()),
182 CryptoError::Serialization(msg) => CryptoError::Serialization(msg.clone()),
183 CryptoError::Compression(msg) => CryptoError::Compression(msg.clone()),
184 CryptoError::Io(err) => CryptoError::Io(std::io::Error::new(
185 err.kind(),
186 err.to_string(),
187 )),
188 }
189 }
190}
191
192pub type Result<T> = std::result::Result<T, CryptoError>;
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 #[test]
200 fn test_invalid_key_length_display() {
201 let err = CryptoError::InvalidKeyLength {
202 algorithm: "Falcon-1024",
203 expected: 32,
204 got: 16,
205 };
206 let msg = err.to_string();
207 assert!(msg.contains("Falcon-1024"));
208 assert!(msg.contains("expected 32"));
209 assert!(msg.contains("got 16"));
210 }
211
212 #[test]
213 fn test_auth_failed_display() {
214 let err = CryptoError::AuthenticationFailed;
215 assert!(err.to_string().contains("Authentication failed"));
216 }
217
218 #[test]
219 fn test_clone_roundtrip() {
220 let err = CryptoError::InvalidKeyLength {
221 algorithm: "Ed25519",
222 expected: 32,
223 got: 31,
224 };
225 let cloned = err.clone();
226 assert_eq!(err.to_string(), cloned.to_string());
227 }
228
229 #[test]
230 fn test_io_from() {
231 let io_err = std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "truncated");
232 let crypto_err: CryptoError = io_err.into();
233 assert!(matches!(crypto_err, CryptoError::Io(_)));
234 assert!(crypto_err.to_string().contains("truncated"));
235 }
236}