use crate::window_state::WindowState; use eframe::egui; #[derive(PartialEq, Eq)] enum State { Idle, Requested, Generated, } pub struct Window { state: State, n: u64, e: u64, d: u64, k: u64, phi: u64, } impl Default for Window { fn default() -> Self { Self { state: State::Idle, n: 0, e: 0, d: 0, k: 0, phi: 0, } } } impl Window { fn generate(&mut self) { let primes = erathosphene(10000); let i = fastrand::usize(4..primes.len()); let mut j = fastrand::usize(4..primes.len()); while j == i { j = fastrand::usize(..primes.len()); } let p = primes[i as usize]; let q = primes[j as usize]; self.n = p * q; self.phi = (p - 1) * (q - 1); let mut e = self.phi; loop { let (d, x, _) = extended_gcd(e as i64, self.phi as i64); if d != 1 { e = fastrand::u64(2..self.phi); } else { self.e = e; self.d = if x < 0 { x + self.phi as i64 } else { x } as u64; break; } } let mut i = e; let mut order = 1; loop { if i == 1 { break; } else { order += 1; i = (i * e) % self.phi; } } self.k = order; } } fn extended_gcd(a: i64, b: i64) -> (i64, i64, i64) { if a == 0 { return (b, 0, 1); } let (d, x, y) = extended_gcd(b % a, a); return (d, y - (b / a) * x, x); } 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("Модуль n:"); let mut tmp = self.n.to_string(); ui.add_enabled(false, egui::TextEdit::singleline(&mut tmp)); }); ui.horizontal(|ui| { ui.label("Открытая экспонента e:"); let mut tmp = self.e.to_string(); ui.add_enabled(false, egui::TextEdit::singleline(&mut tmp)); }); ui.horizontal(|ui| { ui.label("Секретная экспонента d:"); let mut tmp = self.d.to_string(); ui.add_enabled(false, egui::TextEdit::singleline(&mut tmp)); }); if ui.button("Скопировать открытый ключ").clicked() { ui.output().copied_text = format!("{},{}", self.e, self.n); } if ui.button("Скопировать закрытый ключ").clicked() { ui.output().copied_text = format!("{},{}", self.d, self.n); } ui.label("Порядок элемента e по модулю phi(n):"); let mut tmp = self.k.to_string(); ui.add_enabled(false, egui::TextEdit::singleline(&mut tmp)); if ui.button("Скопировать открытую экспоненту e").clicked() { ui.output().copied_text = format!("{}", self.e); } if ui.button("Скопировать phi(n)").clicked() { ui.output().copied_text = format!("{}", self.phi); } if ui.button("Скопировать порядок").clicked() { ui.output().copied_text = format!("{}", self.k); } } } }