Skip to main content

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}