cryptography_breaker/cli.rs
1//! Cli
2//!
3//! This module is used to provide cli supports, don't use it library
4
5use std::{path::PathBuf, str::FromStr};
6
7use clap::{Parser, Subcommand, ValueEnum};
8
9use crate::normalizer::CaseStrategy;
10
11/// Decrypt text file with three algorithms
12#[derive(Parser, Debug)]
13#[command(version, about)]
14pub struct Args {
15 /// Which algorithm to use
16 #[command(subcommand)]
17 pub algorithm: Algorithms,
18
19 /// Which alphabet to use
20 #[arg(default_value = "classic-en", short, long)]
21 pub alphabet: Alphabet,
22
23 /// What strategy you want to use for text
24 #[arg(default_value_t, short = 's', long)]
25 pub case_strategy: CaseStrategy,
26
27 #[arg(default_value = "false", short = 'w', long)]
28 /// Preserve whitespaces, but the alphabet cannot have any
29 pub preserve_whitespaces: bool,
30
31 #[arg(default_value = "false", short = 'c', long)]
32 /// Preserver characters not present in alphabet (including whitespaces if alphabet have none)
33 pub preserve_other_characters: bool,
34}
35
36#[derive(Clone, Debug, Subcommand)]
37pub enum Algorithms {
38 Vigenere {
39 /// What do you want to do
40 #[command(subcommand)]
41 command: VigenereCommands,
42 },
43 //DoubleVigenere,
44 //OneTimePad,
45}
46
47#[derive(Clone, Subcommand, Debug)]
48pub enum VigenereCommands {
49 /// Encrypt plain text.
50 Encrypt {
51 /// Your key to encrypt data
52 #[arg(short, long)]
53 key: String,
54
55 /// Path to file to encrypt
56 //#[arg(short, long, value_hint = ValueHint::FilePath)]
57 //file_path: PathBuf,
58
59 /// Text to encrypt
60 #[arg(short, long)] // , conflicts_with = "file_path"
61 plain_text: String,
62 },
63
64 /// Decrypt cipher text
65 Decrypt {
66 /// Key to decrypt data
67 #[arg(short, long)]
68 key: String,
69
70 /// Path to file to decrypt
71 //#[arg(short, long, value_hint = ValueHint::FilePath)]
72 //file_path: PathBuf,
73
74 /// Text to decrypt
75 #[arg(short, long)] // , conflicts_with = "file_path"
76 cipher_text: String,
77 },
78
79 /// Crack cipher text
80 Break {
81 /// Which method to use to crack cipher text
82 #[command(subcommand)]
83 method: VigenereBreakMethods,
84
85 // Path to file to crack
86 //#[arg(short, long, value_hint = ValueHint::FilePath)]
87 //file_path: PathBuf,
88 /// Text to crack
89 #[arg(short, long)] //, conflicts_with = "file_path"
90 cipher_text: String,
91 },
92
93 FindKeyLen {
94 /// Which method to use to find key length used to encrypt cipher text
95 #[command(subcommand)]
96 method: VigenereFindKeyMethods,
97
98 // Path to file to crack
99 //#[arg(short, long, value_hint = ValueHint::FilePath)]
100 //file_path: PathBuf,
101 /// Encrypted text
102 #[arg(short, long)] //, conflicts_with = "file_path"
103 cipher_text: String,
104 },
105}
106
107#[derive(Clone, Debug, Subcommand)]
108pub enum VigenereBreakMethods {
109 Bruteforce {
110 #[arg(short, long)]
111 key_len: usize,
112 //known_letters: Option<&'a [Option<char>]>,
113 #[arg(short, long)]
114 penalty_score: Option<f64>,
115 #[arg(short, long)]
116 reference_data_path: PathBuf,
117 #[arg(short = 't', long)]
118 reference_data_type: RefernceDataType,
119 #[arg(short, long)]
120 max_results: Option<usize>,
121 },
122 Dictionary {
123 #[arg(short, long)]
124 keys: Vec<String>,
125 #[arg(short, long)]
126 reference_data_path: PathBuf,
127 #[arg(short = 't', long)]
128 reference_data_type: RefernceDataType,
129 #[arg(short, long)]
130 penalty_score: Option<f64>,
131 #[arg(short, long)]
132 max_results: Option<usize>,
133 },
134 //Crib,
135 /* it doesn't work and to be honest i don't think it could. But mostly I don't care xD
136 breaking algorithms are less priority for me as I won't ever need this and I'm just want to learn how to create good code
137 Variational {
138 #[arg(short, long)]
139 penalty_score: Option<f64>,
140 #[arg(short, long)]
141 reference_data_path: PathBuf,
142 #[arg(short, long)]
143 key_len: usize,
144 },
145 */
146 //Statistical,
147}
148
149#[derive(Clone, Debug, Subcommand)]
150pub enum VigenereFindKeyMethods {
151 /// Uses Friedman test to calculate possible length
152 Approx {
153 #[arg(short, long)]
154 expected_ioc: f64,
155 },
156 /// Slices text and calculate IoC. The IoC closest to expected is probably the key length
157 TextSlices {
158 #[arg(short, long)]
159 expected_ioc: f64,
160 #[arg(short, long)]
161 max_results: Option<usize>,
162 },
163}
164
165#[derive(Clone, Debug, ValueEnum)]
166pub enum RefernceDataType {
167 Monograms,
168 Bigrams,
169 Trigrams,
170 Quadgrams,
171 //NGrams(usize),
172 Letters,
173 Words,
174}
175/*
176impl FromStr for RefernceDataType {
177 type Err = String;
178
179 fn from_str(s: &str) -> Result<Self, Self::Err> {
180 match s {
181 "monograms" => Ok(Self::Monograms),
182 "digrams" => Ok(Self::Digrams),
183 "trigrams" => Ok(Self::Trigrams),
184 "quadgrams" => Ok(Self::Monograms),
185 "ngram<usize>" => Ok(Self::NGrams(usize)),
186 "letters" => Ok(Self::Letters),
187 "words" => Ok(Self::Words),
188
189 _ => Err("Incorrect reference data type".to_string()),
190 }
191 }
192}
193*/
194#[derive(Clone, Debug)]
195pub enum Alphabet {
196 ClassicEn,
197 ClassicPl,
198 Borowcowy,
199 Custom(Vec<char>),
200}
201
202impl FromStr for Alphabet {
203 type Err = String;
204
205 fn from_str(s: &str) -> Result<Self, Self::Err> {
206 match s {
207 "classic-en" => Ok(Self::ClassicEn),
208 "classic-pl" => Ok(Self::ClassicPl),
209 "borowcowy" => Ok(Self::Borowcowy),
210
211 // The rest
212 custom => {
213 let alphabet_chars: Vec<char> = custom.chars().collect();
214 // We check for errors later as we can't handle everything here, so it will always return Ok()
215 Ok(Self::Custom(alphabet_chars))
216 }
217 }
218 }
219}