1mod crypto;
2mod error;
3mod payload;
4mod sga;
5
6use crate::error::Result;
7
8pub fn encrypt(message: &str, password: &str) -> Result<String> {
26 if password.is_empty() {
27 return Err(error::ValidationErrors::EmptyPassword);
28 }
29 if message.is_empty() {
30 return Err(error::ValidationErrors::EmptyCharacters);
31 }
32
33 let sga_encoded = sga::encode(message);
34 let (ciphertext, salt, nonce) = crypto::encrypt(&sga_encoded, password)?;
35
36 Ok(payload::encode_payload(&ciphertext, &salt, &nonce))
37}
38
39pub fn decrypt(message: &str, password: &str) -> Result<String> {
59 let (ciphertext, salt, nonce) = payload::decode_payload(message)?;
60 let decrypted = crypto::decrypt(&ciphertext, password, &salt, &nonce)?;
61
62 let decoded = sga::decode(&decrypted)?;
63
64 Ok(decoded)
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 use base64::Engine;
71
72 #[test]
73 fn roundtrip_default() {
74 let encrypted = encrypt("hello world", "ultra_super_secret_password").unwrap();
75 let decrypted = decrypt(&encrypted, "ultra_super_secret_password").unwrap();
76 assert_eq!(decrypted, "hello world");
77 }
78
79 #[test]
80 fn roundtrip_special_characters() {
81 let message = "hello world 123";
82 let encrypted = encrypt(message, "password").unwrap();
83 let decrypted = decrypt(&encrypted, "password").unwrap();
84 assert_eq!(decrypted, message);
85 }
86
87 #[test]
88 fn roundtrip_long_message() {
89 let message = "a".repeat(500);
90 let encrypted = encrypt(&message, "password").unwrap();
91 let decrypted = decrypt(&encrypted, "password").unwrap();
92 assert_eq!(decrypted, message);
93 }
94
95 #[test]
96 fn encrypt_empty_password_returns_err() {
97 assert!(encrypt("hello world", "").is_err());
98 }
99
100 #[test]
101 fn encrypt_empty_message_returns_err() {
102 assert!(encrypt("", "password").is_err());
103 }
104
105 #[test]
106 fn decrypt_wrong_password_returns_err() {
107 let encrypted = encrypt("hello world", "correct-password").unwrap();
108 assert!(decrypt(&encrypted, "wrong-password").is_err());
109 }
110
111 #[test]
112 fn decrypt_corrupted_payload_returns_err() {
113 assert!(decrypt("this-is-not-a-valid-payload", "password").is_err());
114 }
115
116 #[test]
117 fn decrypt_payload_too_short_returns_err() {
118 let short = base64::engine::general_purpose::STANDARD.encode([0u8; 10]);
120 assert!(decrypt(&short, "password").is_err());
121 }
122}