1use std::{
4 fmt::{self, Display, Formatter},
5 str::FromStr,
6};
7
8use crate::crypto::aead::Variant;
9
10pub struct Cipher {
12 method: Method,
13 cipher: Variant,
14}
15
16impl Cipher {
17 pub fn new(method: Method, key: &[u8]) -> Self {
19 Cipher {
20 method,
21 cipher: Variant::new(method, key),
22 }
23 }
24
25 pub fn encrypt(&self, nonce: &[u8], plaintext: &[u8]) -> aead::Result<Vec<u8>> {
27 self.cipher.encrypt(nonce, plaintext)
28 }
29
30 pub fn decrypt(&self, nonce: &[u8], ciphertext: &[u8]) -> aead::Result<Vec<u8>> {
32 self.cipher.decrypt(nonce, ciphertext)
33 }
34
35 pub fn method(&self) -> Method {
37 self.method
38 }
39}
40
41#[derive(Debug)]
43pub enum Error {
44 Method(String),
46}
47
48impl Display for Error {
49 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
50 match self {
51 Error::Method(name) => write!(f, "{} is unsupported encryption method", name),
52 }
53 }
54}
55
56impl std::error::Error for Error {}
57
58#[derive(Debug, Clone, Copy)]
60pub enum Method {
61 ChaCha20Poly1305,
62 Aes128Gcm,
63 Aes256Gcm,
64}
65
66impl Method {
67 #[inline(always)]
69 pub const fn key_size(&self) -> usize {
70 match self {
71 Method::ChaCha20Poly1305 | Method::Aes256Gcm => 32,
72 Method::Aes128Gcm => 16,
73 }
74 }
75
76 #[inline(always)]
78 pub const fn salt_size(&self) -> usize {
79 match self {
80 Method::ChaCha20Poly1305 | Method::Aes256Gcm => 32,
81 Method::Aes128Gcm => 16,
82 }
83 }
84
85 #[inline(always)]
87 pub const fn iv_size(&self) -> usize {
88 12
89 }
90
91 #[inline(always)]
93 pub const fn tag_size(&self) -> usize {
94 16
95 }
96}
97
98impl Display for Method {
99 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
100 match self {
101 Method::ChaCha20Poly1305 => write!(f, "chacha20-ietf-poly1305"),
102 Method::Aes128Gcm => write!(f, "aes-128-gcm"),
103 Method::Aes256Gcm => write!(f, "aes-256-gcm"),
104 }
105 }
106}
107
108impl FromStr for Method {
109 type Err = Error;
110
111 fn from_str(name: &str) -> Result<Self, Self::Err> {
112 match name {
113 "chacha20-ietf-poly1305" => Ok(Method::ChaCha20Poly1305),
114 "aes-128-gcm" => Ok(Method::Aes128Gcm),
115 "aes-256-gcm" => Ok(Method::Aes256Gcm),
116 s => Err(Error::Method(s.to_owned())),
117 }
118 }
119}