use crate::utils::powmod; use crate::window_state::WindowState; use eframe::egui; #[derive(PartialEq, Eq)] enum State { Idle, Requested, Generated, } pub struct Window { state: State, p: u64, g: u64, a: u64, y: u64, } impl Default for Window { fn default() -> Self { Self { state: State::Idle, p: 0, g: 0, a: 0, y: 0, } } } fn min_order(x: u64, order: u64) -> u64 { let mut min = 0; let mut pow = x; for power in 1..order { if pow == 1 { min = power; break; } pow = (pow * x) % order; } return min; } impl Window { fn generate(&mut self) { let primes = erathosphene(10000); let i = fastrand::usize(4..primes.len()); self.p = primes[i as usize]; for i in 1..self.p { if min_order(i, self.p) == self.p - 1 { self.g = i; break; } } self.a = fastrand::u64(1..=self.p - 1); self.y = powmod(self.g, self.a, self.p); } } fn erathosphene(n: u64) -> Vec { let mut is_prime = vec![true; n as usize]; let mut p = 2; while p * p < n { let mut cur = p * p; while cur < n { is_prime[cur as usize] = false; cur += p; } while !is_prime[(p + 1) as usize] { p += 1; } p += 1 } let mut primes = Vec::new(); is_prime.iter().enumerate().for_each(|(i, p)| { if *p { primes.push(i as u64); } }); return primes; } impl WindowState for Window { fn get_name(&self) -> &str { "Генерация ключей" } fn update(&mut self, ui: &mut egui::Ui) { if ui.button("Сгенерировать").clicked() { self.state = State::Requested; } if self.state == State::Requested { self.generate(); self.state = State::Generated; } if self.state == State::Generated { ui.horizontal(|ui| { ui.label("Модуль p:"); let mut tmp = self.p.to_string(); ui.add_enabled(false, egui::TextEdit::singleline(&mut tmp)); }); ui.horizontal(|ui| { ui.label("Порождающий элемент g группы Z_p:"); let mut tmp = self.g.to_string(); ui.add_enabled(false, egui::TextEdit::singleline(&mut tmp)); }); ui.horizontal(|ui| { ui.label("Секретный ключ a:"); let mut tmp = self.a.to_string(); ui.add_enabled(false, egui::TextEdit::singleline(&mut tmp)); }); ui.horizontal(|ui| { ui.label("Публичный ключ y:"); let mut tmp = self.y.to_string(); ui.add_enabled(false, egui::TextEdit::singleline(&mut tmp)); }); if ui.button("Скопировать публичный ключ").clicked() { ui.output().copied_text = format!("{},{}", self.y, self.p); } if ui.button("Скопировать секретный ключ").clicked() { ui.output().copied_text = format!("{},{},{}", self.g, self.a, self.p); } } } }