main.rs
1 use std::collections::HashMap; 2 use std::env; 3 use std::fs; 4 use std::path::Path; 5 use rand::{Rng, SeedableRng}; 6 use rand::rngs::StdRng; 7 use regex::Regex; 8 use hmac::{Hmac, Mac}; 9 use sha2::Sha256; 10 use base64::{engine::general_purpose, Engine as _}; 11 12 type HmacSha256 = Hmac<Sha256>; 13 14 struct WordDictionaries { 15 nouns: Vec<String>, 16 verbs: Vec<String>, 17 adjectives: Vec<String>, 18 adverbs: Vec<String>, 19 prepositions: Vec<String>, 20 articles: Vec<String>, 21 conjunctions: Vec<String>, 22 pronouns: Vec<String>, 23 proper_nouns: Vec<String>, 24 } 25 26 impl WordDictionaries { 27 fn new() -> Self { 28 WordDictionaries { 29 nouns: Self::load_words("dictionaries/nouns.txt"), 30 verbs: Self::load_words("dictionaries/verbs.txt"), 31 adjectives: Self::load_words("dictionaries/adjectives.txt"), 32 adverbs: Self::load_words("dictionaries/adverbs.txt"), 33 prepositions: Self::load_words("dictionaries/prepositions.txt"), 34 articles: Self::load_words("dictionaries/articles.txt"), 35 conjunctions: Self::load_words("dictionaries/conjunctions.txt"), 36 pronouns: Self::load_words("dictionaries/pronouns.txt"), 37 proper_nouns: Self::load_words("dictionaries/proper_nouns.txt"), 38 } 39 } 40 41 fn load_words(filename: &str) -> Vec<String> { 42 let path = Path::new(filename); 43 if !path.exists() { 44 eprintln!("Warning: Dictionary file '{}' not found.", filename); 45 return Vec::new(); 46 } 47 48 let content = match fs::read_to_string(path) { 49 Ok(c) => c, 50 Err(err) => { 51 eprintln!("Error reading '{}': {}", filename, err); 52 return Vec::new(); 53 } 54 }; 55 56 content 57 .lines() 58 .filter_map(|line| { 59 let word = line.trim(); 60 if word.is_empty() { 61 None 62 } else { 63 Some(word.to_lowercase()) 64 } 65 }) 66 .collect() 67 } 68 69 fn get_dictionary(&self, pos: &str) -> Option<&Vec<String>> { 70 match pos { 71 "noun" => Some(&self.nouns), 72 "verb" => Some(&self.verbs), 73 "adjective" => Some(&self.adjectives), 74 "adverb" => Some(&self.adverbs), 75 "preposition" => Some(&self.prepositions), 76 "article" => Some(&self.articles), 77 "conjunction" => Some(&self.conjunctions), 78 "pronoun" => Some(&self.pronouns), 79 "proper_noun" => Some(&self.proper_nouns), 80 _ => None, 81 } 82 } 83 84 fn get_pos(&self, word: &str) -> Option<String> { 85 let word = word.to_lowercase(); 86 if self.nouns.contains(&word) { 87 Some("noun".to_string()) 88 } else if self.verbs.contains(&word) { 89 Some("verb".to_string()) 90 } else if self.adjectives.contains(&word) { 91 Some("adjective".to_string()) 92 } else if self.adverbs.contains(&word) { 93 Some("adverb".to_string()) 94 } else if self.prepositions.contains(&word) { 95 Some("preposition".to_string()) 96 } else if self.articles.contains(&word) { 97 Some("article".to_string()) 98 } else if self.conjunctions.contains(&word) { 99 Some("conjunction".to_string()) 100 } else if self.pronouns.contains(&word) { 101 Some("pronoun".to_string()) 102 } else if self.proper_nouns.contains(&word) { 103 Some("proper_noun".to_string()) 104 } else { 105 None 106 } 107 } 108 } 109 110 struct GrammaticalCipher { 111 dictionaries: WordDictionaries, 112 encrypt_mappings: HashMap<(String, u64), HashMap<String, String>>, 113 decrypt_mappings: HashMap<(String, u64), HashMap<String, String>>, 114 } 115 116 impl GrammaticalCipher { 117 fn new() -> Self { 118 GrammaticalCipher { 119 dictionaries: WordDictionaries::new(), 120 encrypt_mappings: HashMap::new(), 121 decrypt_mappings: HashMap::new(), 122 } 123 } 124 125 fn encrypt(&mut self, sentence: &str, key: u64) -> String { 126 let encrypted = self.process(sentence, key, true); 127 let hmac = Self::generate_hmac(&encrypted, key); 128 format!("{} | {}", encrypted, hmac) 129 } 130 131 fn decrypt(&mut self, input: &str, key: u64) -> String { 132 let parts: Vec<&str> = input.rsplitn(2, " | ").collect(); 133 if parts.len() != 2 { 134 return "Error: Invalid encrypted format. Expected format: TEXT | HMAC".to_string(); 135 } 136 let provided_hmac = parts[0]; 137 let encrypted_text = parts[1]; 138 139 let calculated_hmac = Self::generate_hmac(encrypted_text, key); 140 if provided_hmac != calculated_hmac { 141 return "⚠️ Warning: Message has been tampered with or the key is incorrect.".to_string(); 142 } 143 144 self.process(encrypted_text, key, false) 145 } 146 147 fn generate_hmac(data: &str, key: u64) -> String { 148 let mut mac = HmacSha256::new_from_slice(&key.to_le_bytes()).expect("HMAC init failed"); 149 mac.update(data.as_bytes()); 150 let result = mac.finalize(); 151 let code_bytes = result.into_bytes(); 152 general_purpose::STANDARD.encode(code_bytes) 153 } 154 155 fn process(&mut self, sentence: &str, key: u64, encrypting: bool) -> String { 156 let re = Regex::new(r"[\w'-]+|[^\w\s]").unwrap(); 157 let tokens: Vec<&str> = re.find_iter(sentence).map(|m| m.as_str()).collect(); 158 let mut result = String::new(); 159 let mut prev_was_word = false; 160 161 for token in tokens { 162 let is_word = token.chars().all(|c| c.is_alphanumeric() || c == '\'' || c == '-'); 163 let lower = token.to_lowercase(); 164 165 if is_word { 166 if prev_was_word { 167 result.push(' '); 168 } 169 170 let mut stemmed = lower.clone(); 171 let mut matched_pos = self.dictionaries.get_pos(&stemmed); 172 173 if matched_pos.is_none() { 174 let guess_stem = self.stem_verb(&lower); 175 if guess_stem != lower { 176 stemmed = guess_stem; 177 matched_pos = self.dictionaries.get_pos(&stemmed); 178 } 179 } 180 181 if let Some(pos) = matched_pos { 182 self.ensure_mappings_exist(&pos, key); 183 let mapped = if encrypting { 184 self.encrypt_mappings.get(&(pos.clone(), key)) 185 .and_then(|m| m.get(&stemmed)) 186 .cloned() 187 } else { 188 self.decrypt_mappings.get(&(pos.clone(), key)) 189 .and_then(|m| m.get(&stemmed)) 190 .cloned() 191 }; 192 193 let final_word = if let Some(mapped_word) = mapped { 194 if token.chars().next().unwrap().is_uppercase() { 195 let mut chars = mapped_word.chars(); 196 match chars.next() { 197 None => String::new(), 198 Some(first_char) => first_char.to_uppercase().collect::<String>() + chars.as_str(), 199 } 200 } else { 201 mapped_word 202 } 203 } else { 204 token.to_string() 205 }; 206 207 result.push_str(&final_word); 208 } else { 209 result.push_str(token); 210 } 211 prev_was_word = true; 212 } else { 213 result.push_str(token); 214 prev_was_word = false; 215 } 216 } 217 218 result 219 } 220 221 fn ensure_mappings_exist(&mut self, pos: &str, key: u64) { 222 let key_pos = (pos.to_string(), key); 223 if self.encrypt_mappings.contains_key(&key_pos) && self.decrypt_mappings.contains_key(&key_pos) { 224 return; 225 } 226 self.create_mappings(&key_pos); 227 } 228 229 fn create_mappings(&mut self, key_pos: &(String, u64)) { 230 let (pos, key) = key_pos; 231 let mut rng = StdRng::seed_from_u64(*key); 232 233 if let Some(dict) = self.dictionaries.get_dictionary(pos) { 234 let mut encrypt_map = HashMap::new(); 235 let mut decrypt_map = HashMap::new(); 236 237 if dict.is_empty() { 238 return; 239 } 240 241 let mut shuffled = dict.clone(); 242 for i in (1..shuffled.len()).rev() { 243 let j = rng.gen_range(0..=i); 244 shuffled.swap(i, j); 245 } 246 247 for (i, word) in dict.iter().enumerate() { 248 let encrypted = &shuffled[i]; 249 encrypt_map.insert(word.clone(), encrypted.clone()); 250 decrypt_map.insert(encrypted.clone(), word.clone()); 251 } 252 253 self.encrypt_mappings.insert(key_pos.clone(), encrypt_map); 254 self.decrypt_mappings.insert(key_pos.clone(), decrypt_map); 255 } 256 } 257 258 fn stem_verb(&self, word: &str) -> String { 259 let lower = word.to_lowercase(); 260 if self.dictionaries.verbs.contains(&lower) { 261 return lower; 262 } 263 264 let mut w = lower.clone(); 265 266 if w.ends_with("ies") && w.len() > 4 { 267 w = format!("{}y", &w[..w.len() - 3]); 268 } else if w.ends_with("ied") && w.len() > 4 { 269 w = format!("{}y", &w[..w.len() - 3]); 270 } else if w.ends_with("ing") && w.len() > 5 { 271 w = w[..w.len() - 3].to_string(); 272 } else if w.ends_with("ed") && w.len() > 4 { 273 w = w[..w.len() - 2].to_string(); 274 } else if w.ends_with("en") && w.len() > 4 { 275 w = w[..w.len() - 2].to_string(); 276 } else if w.ends_with("es") && w.len() > 4 { 277 w = w[..w.len() - 2].to_string(); 278 } else if w.ends_with('s') && w.len() > 3 { 279 w = w[..w.len() - 1].to_string(); 280 } 281 282 if self.dictionaries.verbs.contains(&w) { 283 w 284 } else { 285 lower 286 } 287 } 288 } 289 290 fn main() { 291 let args: Vec<String> = env::args().collect(); 292 293 if args.len() < 4 { 294 eprintln!("Usage: {} [encrypt|decrypt] [key] [text...]", args[0]); 295 std::process::exit(1); 296 } 297 298 let operation = &args[1]; 299 let key_str = &args[2]; 300 let input_text = args[3..].join(" "); 301 302 let key = match key_str.parse::<u64>() { 303 Ok(k) => k, 304 Err(_) => { 305 eprintln!("Error: Key must be a positive integer"); 306 std::process::exit(1); 307 } 308 }; 309 310 let mut cipher = GrammaticalCipher::new(); 311 312 match operation.as_str() { 313 "encrypt" => { 314 let output = cipher.encrypt(&input_text, key); 315 println!("Original: {}", input_text); 316 println!("Encrypted: {}", output); 317 }, 318 "decrypt" => { 319 let output = cipher.decrypt(&input_text, key); 320 println!("Encrypted: {}", input_text); 321 println!("Decrypted: {}", output); 322 }, 323 _ => { 324 eprintln!("Error: Unknown operation. Use 'encrypt' or 'decrypt'"); 325 std::process::exit(1); 326 } 327 } 328 }