1use super::Error;
16use super::{base64_decode, base64_encode};
17use aes_gcm_siv::{
18 aead::{Aead, KeyInit},
19 Aes256GcmSiv, Nonce,
20};
21use once_cell::sync::Lazy;
22
23type Result<T, E = Error> = std::result::Result<T, E>;
24
25static PINGAP_NONCE: Lazy<&Nonce> =
26 Lazy::new(|| Nonce::from_slice(b"pingap nonce"));
27
28fn generate_key(key: &str) -> Vec<u8> {
38 let key_size = 32;
39 let buf = key.as_bytes();
40 let pos = buf.len();
41 if pos > key_size {
42 return buf[0..key_size].to_vec();
43 }
44 if pos == key_size {
45 return buf.to_vec();
46 }
47 let mut block: Vec<u8> = vec![0; key_size];
48 block[..pos].copy_from_slice(buf);
49 block
50}
51
52pub fn aes_encrypt(key: &str, data: &str) -> Result<String> {
62 let cipher =
63 Aes256GcmSiv::new_from_slice(&generate_key(key)).map_err(|e| {
64 Error::Invalid {
65 message: e.to_string(),
66 }
67 })?;
68 let cipher_text =
69 cipher
70 .encrypt(&PINGAP_NONCE, data.as_bytes())
71 .map_err(|e| Error::Aes {
72 message: e.to_string(),
73 })?;
74 Ok(base64_encode(&cipher_text))
75}
76
77pub fn aes_decrypt(key: &str, data: &str) -> Result<String> {
87 let cipher =
88 Aes256GcmSiv::new_from_slice(&generate_key(key)).map_err(|e| {
89 Error::Invalid {
90 message: e.to_string(),
91 }
92 })?;
93 let cipher_text =
94 base64_decode(data).map_err(|e| Error::Base64Decode { source: e })?;
95 let plaintext = cipher
96 .decrypt(&PINGAP_NONCE, cipher_text.as_ref())
97 .map_err(|e| Error::Aes {
98 message: e.to_string(),
99 })?;
100
101 Ok(std::str::from_utf8(&plaintext)
102 .unwrap_or_default()
103 .to_string())
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use pretty_assertions::assert_eq;
110
111 #[test]
112 fn test_aes_encrypt() {
113 let key = "12345678901234567890123456789012";
114 let data = "hello";
115 let result = aes_encrypt(key, data);
116 assert_eq!(result.is_ok(), true);
117
118 let result = aes_decrypt(key, &result.unwrap());
119 assert_eq!(result.is_ok(), true);
120 assert_eq!(result.unwrap(), data);
121 }
122}