diff options
Diffstat (limited to 'lab2/src/generate_window.rs')
| -rw-r--r-- | lab2/src/generate_window.rs | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/lab2/src/generate_window.rs b/lab2/src/generate_window.rs new file mode 100644 index 0000000..56a572a --- /dev/null +++ b/lab2/src/generate_window.rs @@ -0,0 +1,156 @@ +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<u64> { + 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); + } + } + } +} |