summaryrefslogtreecommitdiff
path: root/sem2/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'sem2/src/main.rs')
-rw-r--r--sem2/src/main.rs243
1 files changed, 205 insertions, 38 deletions
diff --git a/sem2/src/main.rs b/sem2/src/main.rs
index adf47b8..7c458f6 100644
--- a/sem2/src/main.rs
+++ b/sem2/src/main.rs
@@ -1,54 +1,221 @@
-use fastrand;
-use inquire::Text;
-use std::time::Instant;
+use inquire::{Select, Text};
+use std::fs::{self, File};
+use std::io::{self, Write};
+use std::path::{Path, PathBuf};
+
+use crate::elgamal::{decrypt_text, encrypt_text, OpenKey, SecretKey};
+use crate::mpn::Number;
mod algo;
+mod elgamal;
mod mpn;
mod program;
-fn main() {
- let radix = 10;
-
- let q_text = match Text::new("Введите число q:").prompt() {
- Ok(text) => text,
- Err(_) => return,
- };
- let q = match mpn::Number::parse(&q_text, radix as u8) {
- Ok(number) => number,
- Err(what) => {
- println!("{what}");
- return;
+fn files_recursive(dir: &Path) -> io::Result<Vec<PathBuf>> {
+ let mut dir_front = Vec::new();
+ let mut files = Vec::new();
+ dir_front.push(dir.to_owned());
+ while dir_front.len() != 0 {
+ let dir = dir_front.pop().unwrap();
+ for entry in fs::read_dir(dir)? {
+ let path = entry?.path();
+ if path.is_dir() {
+ dir_front.push(path.clone());
+ } else {
+ files.push(path.clone());
+ }
}
- };
-
- if !algo::rabin_miller_test(&q, 10) {
- println!("Число q должно быть простым");
- return;
}
+ return Ok(files);
+}
- let mut p;
- loop {
- let s = mpn::Number::random_num(fastrand::usize(1..=30), radix);
- println!("s = {s}");
- p = q.clone() * s + 1.into();
- if algo::rabin_miller_test(&p, 10) {
- break;
+fn dirs_recursive(dir: &Path) -> io::Result<Vec<PathBuf>> {
+ let mut dir_front = Vec::new();
+ let mut dirs = Vec::new();
+ dir_front.push(dir.to_owned());
+ dirs.push(dir.to_owned());
+ while dir_front.len() != 0 {
+ let dir = dir_front.pop().unwrap();
+ for entry in fs::read_dir(dir)? {
+ let path = entry?.path();
+ if path.is_dir() {
+ dir_front.push(path.clone());
+ dirs.push(path.clone());
+ }
}
}
- println!("Сгенерированное простое p: {p}");
+ return Ok(dirs);
+}
- let t_start = Instant::now();
- let g = program::find_of_order(&p, &q);
- let t_elapsed = t_start.elapsed();
+fn write_keys(
+ open: OpenKey,
+ open_path: String,
+ secret: SecretKey,
+ secret_path: String,
+) {
+ let mut open_file = File::create(open_path).unwrap();
+ let key = format!("{} {} {}", open.y, open.g, open.p);
+ open_file.write_all(key.as_bytes()).unwrap();
- match g {
- Ok(res) => {
- println!("Найденный элемент g: {res}");
- }
- Err(msg) => {
- println!("{msg}");
+ let mut secret_file = File::create(secret_path).unwrap();
+ let key = format!("{}", secret.x);
+ secret_file.write_all(key.as_bytes()).unwrap();
+}
+
+fn read_open_key(path: String) -> OpenKey {
+ let open_text = fs::read_to_string(path).unwrap();
+ let numbers = open_text.split(" ").collect::<Vec<&str>>();
+ let y = Number::parse(numbers[0], 10).unwrap();
+ let g = Number::parse(numbers[1], 10).unwrap();
+ let p = Number::parse(numbers[2], 10).unwrap();
+ return OpenKey { y, g, p };
+}
+
+fn read_secret_key(path: String) -> SecretKey {
+ let secret_text = fs::read_to_string(path).unwrap();
+ let x = Number::parse(&secret_text, 10).unwrap();
+ return SecretKey { x };
+}
+
+fn main() {
+ let operation = Select::new(
+ "Выберите тип операции:",
+ vec!["Генерация ключей", "Зашифрование", "Расшифрование"],
+ )
+ .prompt()
+ .unwrap();
+
+ if operation == "Генерация ключей" {
+ let dir_entries = dirs_recursive(Path::new("."))
+ .unwrap()
+ .into_iter()
+ .map(|e| e.to_str().unwrap().to_owned())
+ .collect::<Vec<String>>();
+ let result_path =
+ Select::new("Выберите куда сохранить результат:", dir_entries)
+ .prompt()
+ .unwrap();
+ let open_name = Text::new("Имя для файла с открытым ключом:")
+ .prompt()
+ .unwrap();
+ let secret_name = Text::new("Имя для файла с закрытым ключом:")
+ .prompt()
+ .unwrap();
+ let p_text = Text::new("Введите простое p:").prompt().unwrap();
+ let p = Number::parse(&p_text, 10).unwrap();
+ if !algo::rabin_miller_test(&p, 10) {
+ println!("Число p должно быть простым");
return;
}
+ let (op, cl) = elgamal::generate_keypair(&p);
+ let open_path = Path::new(&result_path)
+ .join(&open_name)
+ .to_string_lossy()
+ .to_string();
+ let secret_path = Path::new(&result_path)
+ .join(&secret_name)
+ .to_string_lossy()
+ .to_string();
+ write_keys(op, open_path, cl, secret_path);
}
- println!("Операция выполнена за {} наносекунд", t_elapsed.as_nanos());
+ if operation == "Зашифрование" {
+ let entries = files_recursive(Path::new("."))
+ .unwrap()
+ .into_iter()
+ .map(|e| e.to_str().unwrap().to_owned())
+ .collect::<Vec<String>>();
+ let open_name =
+ Select::new("Выберите файл с открытым ключом:", entries.clone())
+ .prompt()
+ .unwrap();
+ let plain_file =
+ Select::new("Выберите файл для зашифрования:", entries)
+ .prompt()
+ .unwrap();
+
+ let dir_entries = dirs_recursive(Path::new("."))
+ .unwrap()
+ .into_iter()
+ .map(|e| e.to_str().unwrap().to_owned())
+ .collect::<Vec<String>>();
+ let result_path =
+ Select::new("Выберите куда сохранить результат:", dir_entries)
+ .prompt()
+ .unwrap();
+
+ let cipher_name =
+ Text::new("Введите название для файла с шифротекстом:")
+ .prompt()
+ .unwrap();
+
+ let open_key = read_open_key(open_name);
+ let plaintext = fs::read_to_string(plain_file).unwrap();
+ println!("{plaintext}");
+ println!("Отфильтрованный текст:");
+ let plaintext = elgamal::filter_text(&plaintext);
+ println!("{plaintext}");
+ let cipher = encrypt_text(&plaintext, open_key);
+
+ let mut elements = Vec::new();
+ for (a, b) in &cipher {
+ let elem = format!("{},{}", a, b);
+ elements.push(elem);
+ }
+ let ciphertext = elements.join(":");
+ println!("Полученный шифротекст: {ciphertext}");
+ let cipher_path = Path::new(&result_path)
+ .join(&cipher_name)
+ .to_string_lossy()
+ .to_string();
+ fs::write(cipher_path, ciphertext.as_bytes())
+ .expect("Не получилось записать шифротекст");
+ }
+
+ if operation == "Расшифрование" {
+ let entries = files_recursive(Path::new("."))
+ .unwrap()
+ .into_iter()
+ .map(|e| e.to_str().unwrap().to_owned())
+ .collect::<Vec<String>>();
+ let secret_name =
+ Select::new("Выберите файл с закрытым ключом:", entries.clone())
+ .prompt()
+ .unwrap();
+ let open_name =
+ Select::new("Выберите файл с открытым ключом:", entries.clone())
+ .prompt()
+ .unwrap();
+ let cipher_file =
+ Select::new("Выберите файл для расшифрования:", entries)
+ .prompt()
+ .unwrap();
+
+ let dir_entries = dirs_recursive(Path::new("."))
+ .unwrap()
+ .into_iter()
+ .map(|e| e.to_str().unwrap().to_owned())
+ .collect::<Vec<String>>();
+ let result_path =
+ Select::new("Выберите куда сохранить результат:", dir_entries)
+ .prompt()
+ .unwrap();
+ let plain_name =
+ Text::new("Введите название для файла с расшифровкой:")
+ .prompt()
+ .unwrap();
+
+ let open = read_open_key(open_name);
+ let secret = read_secret_key(secret_name);
+ let ciphertext = fs::read_to_string(cipher_file).unwrap();
+ let plaintext = decrypt_text(&ciphertext, secret, open);
+ println!("Расшифрованный текст:");
+ println!("{plaintext}");
+
+ let plain_path = Path::new(&result_path)
+ .join(&plain_name)
+ .to_string_lossy()
+ .to_string();
+ fs::write(plain_path, plaintext.as_bytes())
+ .expect("Не получилось записать расшифровку");
+ }
}