summaryrefslogtreecommitdiff
path: root/labs/src
diff options
context:
space:
mode:
Diffstat (limited to 'labs/src')
-rw-r--r--labs/src/lab1.rs134
-rw-r--r--labs/src/lab3.rs128
-rw-r--r--labs/src/lab6.rs114
-rw-r--r--labs/src/lab7.rs305
-rw-r--r--labs/src/lab_trait.rs6
-rw-r--r--labs/src/main.rs42
6 files changed, 729 insertions, 0 deletions
diff --git a/labs/src/lab1.rs b/labs/src/lab1.rs
new file mode 100644
index 0000000..b442199
--- /dev/null
+++ b/labs/src/lab1.rs
@@ -0,0 +1,134 @@
+use crate::lab_trait::Lab;
+use eframe::egui;
+
+pub struct Window {
+ order: u32,
+ element: u32,
+ element_check: Option<bool>,
+ primitive_roots: Vec<u32>,
+ state: State,
+}
+
+impl Window {
+ fn clear_state(&mut self) {
+ self.element_check = None;
+ self.state = State::Idle;
+ }
+}
+
+impl Default for Window {
+ fn default() -> Self {
+ Self {
+ order: 29,
+ element: 2,
+ element_check: None,
+ primitive_roots: Vec::new(),
+ state: State::Idle,
+ }
+ }
+}
+
+impl Lab for Window {
+ fn get_name(&self) -> &str { "Задача №1" }
+
+ fn update(&mut self, ui: &mut egui::Ui) {
+ ui.horizontal(|ui| {
+ ui.label("Порядок поля: ");
+ if ui
+ .add(egui::DragValue::new(&mut self.order).clamp_range(2..=u32::MAX))
+ .changed()
+ {
+ self.clear_state();
+ }
+ });
+ ui.horizontal(|ui| {
+ ui.label("Проверяемый элемент: ");
+ if ui
+ .add(egui::DragValue::new(&mut self.element).clamp_range(1..=self.order - 1))
+ .changed()
+ {
+ self.clear_state();
+ }
+ });
+
+ if ui.button("Проверить элемент").clicked() {
+ let min = min_order(self.element, self.order);
+ self.element_check = Some(min == self.order - 1);
+ }
+ match self.element_check {
+ Some(true) => {
+ ui.label("Элемент является порождающим элементом");
+ }
+ Some(false) => {
+ ui.label("Элемент не является порождающим элементом");
+ }
+ None => {}
+ }
+
+ if ui.button("Рассчитать порождающие элементы").clicked() {
+ self.primitive_roots.clear();
+ self.state = if is_prime(self.order) {
+ State::Running(1)
+ } else {
+ State::Error
+ }
+ }
+ match self.state {
+ State::Running(current) => {
+ ui.label("Вычисление...");
+ let min = min_order(current, self.order);
+ if min == self.order - 1 {
+ self.primitive_roots.push(current);
+ }
+ self.state = if current == self.order - 1 {
+ State::Done
+ } else {
+ State::Running(current + 1)
+ }
+ }
+ State::Done => {
+ ui.label(format!(
+ "Порождающие элементы поля F_{}: {:?}",
+ self.order, self.primitive_roots
+ ));
+ }
+ State::Idle => {}
+ State::Error => {
+ ui.label("Можно указать только простое число!");
+ }
+ }
+ }
+}
+
+enum State {
+ Idle,
+ Running(u32),
+ Done,
+ Error,
+}
+
+fn min_order(x: u32, order: u32) -> u32 {
+ 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;
+}
+
+fn is_prime(x: u32) -> bool {
+ if x <= 1 {
+ return false;
+ }
+ for i in 2..x / 2 + 1 {
+ if x % i == 0 {
+ return false;
+ }
+ }
+ return true;
+}
+
diff --git a/labs/src/lab3.rs b/labs/src/lab3.rs
new file mode 100644
index 0000000..7f8edf5
--- /dev/null
+++ b/labs/src/lab3.rs
@@ -0,0 +1,128 @@
+use crate::lab_trait::Lab;
+use eframe::egui;
+use rug::{Complete, Integer};
+
+enum State {
+ Clean,
+ Done,
+ Error,
+}
+
+pub struct Window {
+ str_num: String,
+ factors: Vec<Integer>,
+ state: State,
+}
+
+impl Default for Window {
+ fn default() -> Self {
+ Self {
+ str_num: String::from("21894583143407671"),
+ factors: Vec::new(),
+ state: State::Clean,
+ }
+ }
+}
+
+impl Lab for Window {
+ fn get_name(&self) -> &str { "Задача №3" }
+
+ fn update(&mut self, ui: &mut egui::Ui) {
+ ui.horizontal(|ui| {
+ ui.label("Число: ");
+ let field = ui.add(egui::TextEdit::singleline(&mut self.str_num));
+ if field.changed() {
+ self.state = State::Clean;
+ self.factors.clear();
+ }
+ });
+ if ui.button("Разложить на множители").clicked() {
+ self.factors.clear();
+ match Integer::parse(&self.str_num) {
+ Ok(number) => {
+ self.factors.append(&mut factorize(&number.complete()));
+ self.state = State::Done;
+ },
+ Err(_) => self.state = State::Error,
+ };
+ }
+ if let State::Done = self.state {
+ if self.factors.len() == 1 {
+ ui.label(format!("Число является простым"));
+ }
+ else {
+ ui.label(format!("Множители: {:?}", self.factors));
+ }
+ }
+ if let State::Error = self.state {
+ ui.label("В числе имеются недопустимые символы");
+ }
+ }
+}
+
+fn factorize(n: &Integer) -> Vec<Integer> {
+ let mut factors = Vec::new();
+ let mut front = vec![n.clone()];
+
+ while !front.is_empty() {
+ let num = front.pop().unwrap();
+ match lehman(&num) {
+ Some(factor) => {
+ let other = num.div_exact_ref(&factor).complete();
+ front.push(factor);
+ front.push(other);
+ },
+ None => factors.push(num)
+ };
+ }
+
+ return factors;
+}
+
+fn lehman(n: &Integer) -> Option<Integer> {
+ let one = &Integer::from(1u32);
+ let mut a = Integer::from(2u32);
+ let root3 = n.root_ref(3).complete();
+
+ while a <= root3 {
+ let (_, r) = n.div_rem_ref(&a).complete();
+ if r == 0 {
+ return Some(a);
+ }
+ a += one;
+ }
+
+ let root6 = n.root_ref(6).complete();
+ let mut k = Integer::from(1u32);
+ while k <= root3 {
+ let mut d = Integer::ZERO;
+ let sqrtk4 = k.sqrt_ref().complete() * 4;
+ let (r6sk4, _) = root6.div_rem_ref(&sqrtk4).complete();
+ while d <= (&r6sk4 + one).complete() {
+ let kn4: Integer = k.clone() * n.clone() * 4;
+ let sqrt_kn4 = kn4.sqrt_ref().complete();
+
+ let number = (sqrt_kn4.clone() + d.clone()).square() - kn4.clone();
+ if number.is_perfect_square() {
+ let big_a = sqrt_kn4 + d.clone();
+ let big_b = (big_a.square_ref() - kn4).sqrt();
+
+ let gcd1 = (big_a.clone() + big_b.clone()).gcd_ref(n).complete();
+ let gcd2 = (big_a.clone() - big_b.clone()).gcd_ref(n).complete();
+
+ if &gcd1 > one && &gcd1 < n {
+ return Some(gcd1);
+ }
+ else if &gcd2 > one && &gcd2 < n {
+ return Some(gcd2);
+ }
+ }
+
+ d += one;
+ }
+ k += one;
+ }
+
+ return None;
+}
+
diff --git a/labs/src/lab6.rs b/labs/src/lab6.rs
new file mode 100644
index 0000000..9061da7
--- /dev/null
+++ b/labs/src/lab6.rs
@@ -0,0 +1,114 @@
+use crate::lab_trait::Lab;
+use eframe::egui;
+use std::collections::HashSet;
+use std::collections::HashMap;
+
+enum State<'a> {
+ Clean,
+ Done1,
+ Done2,
+ Error(&'a str),
+}
+
+pub struct Window<'a> {
+ n: u32,
+ q: u32,
+ subgroup: Vec<u32>,
+ subgroups: HashMap<u32, Vec<u32>>,
+ state: State<'a>,
+}
+
+impl<'a> Default for Window<'a> {
+ fn default() -> Self {
+ Self {
+ n: 6,
+ q: 3,
+ subgroup: Vec::new(),
+ subgroups: HashMap::new(),
+ state: State::Clean,
+ }
+ }
+}
+
+impl<'a> Lab for Window<'a> {
+ fn get_name(&self) -> &str { "Задача №6" }
+
+ fn update(&mut self, ui: &mut egui::Ui) {
+ ui.horizontal(|ui| {
+ ui.label("Порядок группы Z_n: ");
+ if ui.add(egui::DragValue::new(&mut self.n).clamp_range(2..=u32::MAX)).changed() {
+ self.state = State::Clean;
+ self.subgroup.clear();
+ }
+ });
+ ui.horizontal(|ui| {
+ ui.label("Порядок q подгруппы: ");
+ if ui.add(egui::DragValue::new(&mut self.q).clamp_range(1..=self.n)).changed() {
+ self.state = State::Clean;
+ self.subgroup.clear();
+ }
+ });
+ if ui.button("Вычислить подгруппу").clicked() {
+ self.subgroups.clear();
+ if self.n % self.q != 0 {
+ self.state = State::Error("q не является делителем n");
+ }
+ else {
+ self.subgroups = calculate_subgroups(self.n);
+ for (_, sg) in &self.subgroups {
+ if sg.len() == self.q as usize {
+ self.subgroup = sg.clone();
+ break;
+ }
+ }
+ self.state = State::Done1;
+ }
+ }
+ if ui.button("Вычислить все подгруппы").clicked() {
+ self.subgroups.clear();
+ if self.n % self.q != 0 {
+ self.state = State::Error("q не является делителем n");
+ }
+ else {
+ self.subgroups = calculate_subgroups(self.n);
+ self.state = State::Done2;
+ }
+ }
+ match self.state {
+ State::Clean => {},
+ State::Done1 => {
+ ui.label(format!("Вычисленная подгруппа: {:?}", self.subgroup));
+ },
+ State::Done2 => {
+ for (gen, set) in self.subgroups.iter() {
+ ui.label(format!("Подгруппа {:?} с генератором {}", set, gen));
+ }
+ },
+ State::Error(msg) => { ui.label(msg); },
+ }
+ }
+}
+
+fn powmod(x: u32, n: u32, m: u32) -> u32 {
+ let mut res = 0;
+ for _ in 0..n {
+ res = (res + x) % m;
+ }
+ return res;
+}
+
+fn calculate_subgroups(n: u32) -> HashMap<u32, Vec<u32>> {
+ let mut subgroups = HashMap::new();
+ for i in 0..n {
+ let mut group = HashSet::new();
+ group.insert(i);
+ for p in 2..=n {
+ let power = powmod(i, p, n);
+ group.insert(power);
+ }
+ let mut vec = group.drain().collect::<Vec<u32>>();
+ vec.sort();
+ subgroups.insert(i as u32, vec);
+ }
+ return subgroups;
+}
diff --git a/labs/src/lab7.rs b/labs/src/lab7.rs
new file mode 100644
index 0000000..030c0d4
--- /dev/null
+++ b/labs/src/lab7.rs
@@ -0,0 +1,305 @@
+use crate::lab_trait::Lab;
+use eframe::egui;
+use std::collections::HashSet;
+
+enum State {
+ Nothing,
+ Cipher,
+ Decipher,
+ Line(u32),
+
+ RDecipher,
+ RLine(u32),
+}
+
+pub struct Window {
+ state: State,
+ line: u32,
+ q1: Vec<String>,
+ q2: Vec<String>,
+ q3: Vec<String>,
+ q4: Vec<String>,
+
+ rq1: String,
+ rq2: String,
+ rq3: String,
+ rq4: String,
+ rline: u32,
+}
+
+impl Default for Window {
+ fn default() -> Self {
+ Self {
+ state: State::Nothing,
+ line: 1,
+ q1: vec![
+ "Нечаянно пригрѣтый славой".to_string(),
+ "Орла двуглаваго щипали".to_string(),
+ "Остервененіе народа".to_string(),
+ "Мы очутилися въ П".to_string(),
+ "Скажи за чѣмъ ты въ сам дѣлѣ".to_string(),
+ "Но стихоплетъ Великородный".to_string(),
+ "Авось по манью — --".to_string(),
+ "Сей всадникъ Папою вѣнчанный".to_string(),
+ "Безрукій К. друзьямъ Мореи".to_string(),
+ "А про тебя и въ усъ не дуетъ".to_string(),
+ "Предавшихъ нѣкогда — --".to_string(),
+ "Но искры пламени инова".to_string(),
+ "Они за рюмкой руской водки".to_string(),
+ "У безпокойнаго Никиты".to_string(),
+ "Свои рѣшительныя мѣры".to_string(),
+ "Блеститъ надъ К. тѣнистой".to_string(),
+ "Надъ нами З — валъ тогда".to_string(),
+ "У Б — шатра".to_string(),
+ "Б., зима иль Р. Б.".to_string(),
+ "А Р. З. главой З.".to_string(),
+ "Меня уже предупредилъ".to_string(),
+ "Семействамъ возвратитъ с".to_string(),
+ "Изчезнувшій какъ тѣнь зари".to_string(),
+ "Изъ К. ужъ мигалъ".to_string(),
+ "Ты А. холопъ".to_string(),
+ "Свирѣпой шайкѣ палачей".to_string(),
+ "Уже издавно можетъ быть ".to_string(),
+ ],
+ q2: vec![
+ "Моря достались Албіону".to_string(),
+ "Авось дороги намъ испр.".to_string(),
+ "Измученъ казнію покоя".to_string(),
+ "Кинжалъ… тѣмъ… ".to_string(),
+ ],
+ q3: vec![
+ "Вл. слабый и лукавый".to_string(),
+ "Его мы очень смирн знали".to_string(),
+ "Гроза 12 года".to_string(),
+ "Но Богъ помогъ — сталъ ропотъ ниже".to_string(),
+ "И чѣмъ жирнѣе тѣмъ тяжелѣ".to_string(),
+ "Авось, о Шиболетъ народный".to_string(),
+ "Авось аренды забывая".to_string(),
+ "Сей мужъ судьбы, сей странникъ бранный".to_string(),
+ "Тряслися грозно Пиринеи —".to_string(),
+ "Я всѣхъ уйму съ моимъ народомъ".to_string(),
+ "Потѣшный полкъ Петра титана ".to_string(),
+ "Р. Р. снова присм…".to_string(),
+ "У нихъ [свои бывали] сходки".to_string(),
+ "Витійствомъ рѣзкимъ знамениты".to_string(),
+ "Другъ Марса, Вакха и Венеры".to_string(),
+ "[Но т] Такъ было надъ Невою льдистой".to_string(),
+ "Плѣшивый щеголь врагъ труда".to_string(),
+ "Когда ненаши повара".to_string(),
+ "Насти… — кто тутъ намъ помогъ?".to_string(),
+ "И скоро сило вещей".to_string(),
+ "ОР… нашъ н".to_string(),
+ "Тебѣ бъ я оду посвятилъ".to_string(),
+ "Ханжа запрется въ монастырь".to_string(),
+ "Предъ кѣмъ унизились З".to_string(),
+ "Волканъ Неаполя пылалъ".to_string(),
+ ],
+ q4: vec![
+ "Нашъ З. въ покоѣ говорилъ".to_string(),
+ "Дружина старыхъ усачей".to_string(),
+ "И пуще З. пошелъ кутить".to_string(),
+ "Они за чашею вина".to_string(),
+ "Сбирались члены сей семьи".to_string(),
+ "Тутъ [бы] Л. дерзко предлагалъ".to_string(),
+ "Но тамъ гдѣ ранѣе весна ".to_string(),
+ ],
+
+ rq1: String::new(),
+ rq2: String::new(),
+ rq3: String::new(),
+ rq4: String::new(),
+ rline: 1,
+ }
+ }
+}
+
+impl Lab for Window {
+ fn get_name(&self) -> &str {
+ "Задача №7"
+ }
+
+ fn update(&mut self, ui: &mut egui::Ui) {
+ if ui.button("Вывести оригинал").clicked() {
+ self.state = State::Cipher;
+ }
+ if ui.button("Вывести дешифровку").clicked() {
+ self.state = State::Decipher;
+ }
+ ui.horizontal(|ui| {
+ if ui
+ .add(egui::DragValue::new(&mut self.line).clamp_range(1..=56))
+ .changed()
+ {
+ self.state = State::Nothing;
+ }
+ if ui.button("Вывести строку").clicked() {
+ self.state = State::Line(self.line);
+ }
+ });
+ let response = ui.add(egui::TextEdit::multiline(&mut self.rq1));
+ if response.changed() {
+ self.state = State::Nothing;
+ }
+ let response = ui.add(egui::TextEdit::multiline(&mut self.rq2));
+ if response.changed() {
+ self.state = State::Nothing;
+ }
+ let response = ui.add(egui::TextEdit::multiline(&mut self.rq3));
+ if response.changed() {
+ self.state = State::Nothing;
+ }
+ let response = ui.add(egui::TextEdit::multiline(&mut self.rq4));
+ if response.changed() {
+ self.state = State::Nothing;
+ }
+ if ui.button("Вывести дешифровку введённого текста").clicked()
+ {
+ self.state = State::RDecipher;
+ }
+ ui.horizontal(|ui| {
+ let q1 = self.rq1.lines().collect::<Vec<_>>().len();
+ let q2 = self.rq2.lines().collect::<Vec<_>>().len();
+ let q3 = self.rq3.lines().collect::<Vec<_>>().len();
+ let q4 = self.rq4.lines().collect::<Vec<_>>().len();
+ if ui
+ .add(egui::DragValue::new(&mut self.rline).clamp_range(1..=q1 + q2 + q3 + q4))
+ .changed()
+ {
+ self.state = State::Nothing;
+ }
+ if ui.button("Вывести строку введённого текста").clicked()
+ {
+ self.state = State::RLine(self.rline);
+ }
+ });
+
+ match self.state {
+ State::Nothing => {}
+ State::Cipher => {
+ let mut cipher = Vec::new();
+ cipher.extend(&self.q1);
+ cipher.extend(&self.q2);
+ cipher.extend(&self.q3);
+ cipher.extend(&self.q4);
+ egui::ScrollArea::vertical().show(ui, |ui| {
+ for line in cipher {
+ ui.label(line);
+ }
+ });
+ }
+ State::Decipher => {
+ egui::ScrollArea::vertical().show(ui, |ui| {
+ get_poem(&self.q1, &self.q2, &self.q3, &self.q4)
+ .into_iter()
+ .for_each(|x| {
+ ui.label(x);
+ });
+ });
+ }
+ State::Line(n) => {
+ let poem = get_poem(&self.q1, &self.q2, &self.q3, &self.q4);
+ ui.label(format!("Строка {}: \"{}\"", n, poem[n as usize - 1]));
+ }
+ State::RDecipher => {
+ let q1 = splitlines(&self.rq1);
+ let q2 = splitlines(&self.rq2);
+ let q3 = splitlines(&self.rq3);
+ let q4 = splitlines(&self.rq4);
+ let mut lens = HashSet::new();
+ lens.insert(q1.len());
+ lens.insert(q2.len());
+ lens.insert(q3.len());
+ lens.insert(q4.len());
+ if lens.len() != 1 {
+ ui.label("Введённые тексты должны быть одинаковой длины");
+ } else {
+ get_random_poem(&q1, &q2, &q3, &q4)
+ .into_iter()
+ .for_each(|x| {
+ ui.label(x);
+ });
+ }
+ }
+ State::RLine(n) => {
+ let q1 = splitlines(&self.rq1);
+ let q2 = splitlines(&self.rq2);
+ let q3 = splitlines(&self.rq3);
+ let q4 = splitlines(&self.rq4);
+ let mut lens = HashSet::new();
+ lens.insert(q1.len());
+ lens.insert(q2.len());
+ lens.insert(q3.len());
+ lens.insert(q4.len());
+ if lens.len() != 1 {
+ ui.label("Введённые тексты должны быть одинаковой длины");
+ } else {
+ let poem = get_random_poem(&q1, &q2, &q3, &q4);
+ ui.label(format!("Строка {}: \"{}\"", n, poem[n as usize - 1]));
+ }
+ }
+ }
+ }
+}
+
+fn splitlines(text: &String) -> Vec<String> {
+ text.lines().map(|x| x.to_string()).collect::<Vec<String>>()
+}
+
+fn get_poem(
+ q1: &Vec<String>,
+ _q2: &Vec<String>,
+ q3: &Vec<String>,
+ q4: &Vec<String>,
+) -> Vec<String> {
+ let mut cipher = Vec::new();
+ cipher.extend(q1);
+ cipher.extend(q3);
+ cipher.extend(q4);
+ let mut key = vec![27, 43, 0, 16];
+ let mut poem = Vec::new();
+ let mut count = 1;
+ while key[1] < cipher.len() {
+ if count == 5 {
+ for i in 0..=2 {
+ poem.push(cipher[key[i]].clone());
+ key[i] += 1;
+ }
+ } else if count == 10 {
+ for i in 0..=1 {
+ poem.push(cipher[key[i]].clone());
+ key[i] += 1;
+ }
+ key[2] += 1;
+ key[3] += 1;
+ } else if count == 11 || count >= 13 && count <= 16 {
+ for i in 0..=2 {
+ poem.push(cipher[key[i]].clone());
+ key[i] += 1;
+ }
+ key[3] += 1;
+ } else {
+ for i in 0..=3 {
+ poem.push(cipher[key[i]].clone());
+ key[i] += 1;
+ }
+ }
+ count += 1;
+ }
+ return poem;
+}
+
+fn get_random_poem(
+ q1: &Vec<String>,
+ q2: &Vec<String>,
+ q3: &Vec<String>,
+ q4: &Vec<String>,
+) -> Vec<String> {
+ let mut poem = Vec::new();
+ for i in 0..q1.len() {
+ poem.push(q3[i].clone());
+ poem.push(q4[i].clone());
+ poem.push(q1[i].clone());
+ poem.push(q2[i].clone());
+ }
+ return poem;
+}
diff --git a/labs/src/lab_trait.rs b/labs/src/lab_trait.rs
new file mode 100644
index 0000000..23f110b
--- /dev/null
+++ b/labs/src/lab_trait.rs
@@ -0,0 +1,6 @@
+use eframe::egui;
+
+pub trait Lab {
+ fn get_name(&self) -> &str;
+ fn update(&mut self, ui: &mut egui::Ui);
+}
diff --git a/labs/src/main.rs b/labs/src/main.rs
new file mode 100644
index 0000000..f672971
--- /dev/null
+++ b/labs/src/main.rs
@@ -0,0 +1,42 @@
+mod lab1;
+mod lab3;
+mod lab6;
+mod lab7;
+mod lab_trait;
+
+use eframe::egui;
+use lab_trait::Lab;
+
+fn main() {
+ let options = eframe::NativeOptions::default();
+ eframe::run_native(
+ "Криптографические методы защиты информации",
+ options,
+ Box::new(|_cc| Box::new(Application::default())),
+ );
+}
+
+struct Application {
+ labs: Vec<Box<dyn Lab>>,
+}
+
+impl Default for Application {
+ fn default() -> Self {
+ Self {
+ labs: vec![
+ Box::new(lab1::Window::default()),
+ Box::new(lab3::Window::default()),
+ Box::new(lab6::Window::default()),
+ Box::new(lab7::Window::default()),
+ ],
+ }
+ }
+}
+
+impl eframe::App for Application {
+ fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
+ for window in &mut self.labs {
+ egui::Window::new(window.get_name()).show(ctx, |ui| window.update(ui));
+ }
+ }
+}