aether_core/
shield.rs

1use aes_gcm::{
2    aead::{Aead, KeyInit},
3    Aes256Gcm, Nonce,
4};
5use base64::{engine::general_purpose, Engine as _};
6use std::env;
7
8/// Security utility for Aether Shield.
9pub struct Shield;
10
11impl Shield {
12    /// Get the default key for the current machine.
13    pub fn default_key() -> String {
14        Self::get_machine_id()
15    }
16
17    /// Encrypt a prompt using a key derived from environment or provided key.
18    pub fn encrypt(prompt: &str, key_str: &str) -> String {
19        let key = Self::derive_key(key_str);
20        let cipher = Aes256Gcm::new(&key.into());
21        let nonce = Nonce::from_slice(b"aether_nonce"); // 12 bytes
22
23        let ciphertext = cipher
24            .encrypt(nonce, prompt.as_bytes())
25            .expect("Encryption failed");
26
27        general_purpose::STANDARD.encode(ciphertext)
28    }
29
30    /// Decrypt an encrypted prompt.
31    pub fn decrypt(encrypted_prompt: &str, key_str: &str) -> Result<String, String> {
32        let key = Self::derive_key(key_str);
33        let cipher = Aes256Gcm::new(&key.into());
34        let nonce = Nonce::from_slice(b"aether_nonce");
35
36        let ciphertext = general_purpose::STANDARD
37            .decode(encrypted_prompt)
38            .map_err(|e| e.to_string())?;
39
40        let plaintext = cipher
41            .decrypt(nonce, ciphertext.as_slice())
42            .map_err(|e| e.to_string())?;
43
44        String::from_utf8(plaintext).map_err(|e| e.to_string())
45    }
46
47    /// Helper to derive a 32-byte key from a string.
48    fn derive_key(key_str: &str) -> [u8; 32] {
49        let mut key = [0u8; 32];
50        let bytes = key_str.as_bytes();
51        for i in 0..32 {
52            if i < bytes.len() {
53                key[i] = bytes[i];
54            } else {
55                key[i] = (i as u8).wrapping_mul(0xAF); // Padding
56            }
57        }
58        key
59    }
60
61    /// Get current machine ID for dynamic key generation.
62    /// (Simplified implementation for portability)
63    pub fn get_machine_id() -> String {
64        // Envs that might identify the user/machine
65        let username = env::var("USERNAME").or_else(|_| env::var("USER")).unwrap_or_else(|_| "unknown".to_string());
66        let computername = env::var("COMPUTERNAME").unwrap_or_else(|_| "localhost".to_string());
67        format!("{}-{}", username, computername)
68    }
69}