1use std::convert::TryInto;
3use std::fmt::{Display, Formatter};
5
6use rand;
7
8use crate::{Result, ErrorKind, ResultExt};
9use crate::attack::simple_attacks::Parameters;
10use crate::cipher::common::{offset_text, Ciphers, DEFAULT_CHARSET, get_key_parts};
11use crate::cipher::cryptomath::gcd;
12use rand::Rng;
13
14
15#[derive(Debug, Copy, Clone)]
16enum WrongAffineKeyCauses {
17 MultiplyingKeyBelowZero,
18 MultiplyingKeyZero,
19 AddingKeyBelowZero,
20 AddingKeyTooLong,
21 KeysNotRelativelyPrime
22}
23
24impl Display for WrongAffineKeyCauses {
25 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
26 let message = match self {
27 WrongAffineKeyCauses::MultiplyingKeyBelowZero=> "Multiplying key must be greater than 0.",
28 WrongAffineKeyCauses::MultiplyingKeyZero=> "Multiplying key must not be 0.",
29 WrongAffineKeyCauses::AddingKeyBelowZero=> "Adding key must be greater than 0.",
30 WrongAffineKeyCauses::AddingKeyTooLong=> "Adding key must be smaller than charset length.",
31 WrongAffineKeyCauses::KeysNotRelativelyPrime=> "Keys are not relatively prime."
32 };
33 write!(f, "{}", message)
34 }
35}
36
37#[derive(Debug)]
38pub struct WrongAffineKey {
39 key: usize,
40 multiplying_key: usize,
41 adding_key: usize,
42 cause: WrongAffineKeyCauses
43}
44
45impl WrongAffineKey {
46
47 fn new(key: usize, cause: WrongAffineKeyCauses, charset_length: usize) -> Self {
48 let (multiplying_key, adding_key) = get_key_parts(key, charset_length);
49 WrongAffineKey {
50 key,
51 multiplying_key,
52 adding_key,
53 cause
54 }
55 }
56}
57
58impl Display for WrongAffineKey {
59 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
60 write!(f, "Wrong key: {} key decomposes to {} as multiplicative key and {} as adding key, \
61 but problem is {}", self.key, self.multiplying_key, self.adding_key, self.cause)
62 }
63}
64
65pub fn cipher(text: &str, key: usize, charset: &str)-> Result<String> {
90 validate_key(key, charset.len())?;
91 let ciphered_text = offset_text(text, key, true, &Ciphers::AFFINE, DEFAULT_CHARSET);
92 ciphered_text
93}
94
95pub fn decipher(ciphered_text: &str, key: usize, charset: &str)-> Result<String> {
111 validate_key(key, charset.len())?;
112 let deciphered_text = offset_text(ciphered_text, key, false, &Ciphers::AFFINE, charset);
113 deciphered_text
114}
115
116
117pub fn decipher_par(parameters: &Parameters)-> Result<String> {
133 let ciphered_text = parameters.get_str("ciphered_text")?;
134 let charset = parameters.get_str("charset")?;
135 let key = parameters.get_int("key")?;
136 decipher(ciphered_text.as_str(), key, charset.as_str())
137}
138
139pub fn get_random_key<T>(charset: T)-> Result<usize>
150 where T: AsRef<str>{
151 let charset_length = charset.as_ref().len();
152 let charset_length_isize: isize = charset_length.try_into()
153 .chain_err(|| ErrorKind::ConversionError("charset_length", "usize", "isize"))?;
154 let mut rng = rand::thread_rng();
155 loop {
156 let key_a = rng.gen_range(2, charset_length_isize);
157 let key_b = rng.gen_range(2, charset_length_isize);
158 if gcd(key_a, charset_length_isize) == 1 {
159 return Ok((key_a as usize) * charset_length + (key_b as usize))
160 }
161 }
162}
163
164pub fn validate_key(key: usize, charset_length: usize)-> Result<bool> {
179 let multiplying_key = key / charset_length;
180 let adding_key = key % charset_length;
181 if multiplying_key == 0 {
182 bail!(ErrorKind::WrongAffineKeyError(
183 WrongAffineKey::new(key, WrongAffineKeyCauses::MultiplyingKeyZero, charset_length)
184 ));
185 } else if adding_key > charset_length -1 {
186 bail!(ErrorKind::WrongAffineKeyError(
187 WrongAffineKey::new(key, WrongAffineKeyCauses::AddingKeyTooLong, charset_length)
188 ));
189 } else if gcd(multiplying_key.try_into().chain_err(|| ErrorKind::ConversionError("multiplying_key", "usize", "isize"))?,
190 charset_length.try_into().chain_err(|| ErrorKind::ConversionError("charset_length", "usize", "isize"))?) != 1 {
191 bail!(ErrorKind::WrongAffineKeyError(
192 WrongAffineKey::new(key, WrongAffineKeyCauses::KeysNotRelativelyPrime, charset_length)
193 ));
194 }
195 Ok(true)
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 use test_common::random::strings::random_string;
203
204 use crate::cipher::common::DEFAULT_CHARSET;
205
206 const ORIGINAL_MESSAGE: &'static str = "A computer would deserve to be called intelligent if it could deceive a human into believing that it was human.\" Alan Turing";
207 const CIPHERED_MESSAGE_KEY_2894: &'static str = "5QG9ol3La6QI93!xQxaia6faQL9QdaQG1!!axQARLa!!AuaRLQADQALQG93!xQxaGaAfaQ1QX3o1RQARL9Qda!AafARuQLX1LQALQI1iQX3o1RN\"Q5!1RQP36ARu";
208 const TEST_KEY: usize = 2894;
209
210 #[test]
211 fn test_cipher() {
212 let ciphered_text = cipher(ORIGINAL_MESSAGE, TEST_KEY, DEFAULT_CHARSET).expect("Error getting ciphered text.");
213 assert_eq!(CIPHERED_MESSAGE_KEY_2894, ciphered_text);
214 }
215
216 #[test]
217 fn test_decipher() {
218 let deciphered_text = decipher(CIPHERED_MESSAGE_KEY_2894, TEST_KEY, DEFAULT_CHARSET).unwrap();
219 assert_eq!(ORIGINAL_MESSAGE, deciphered_text);
220 }
221
222 #[test]
223 fn test_get_random_key() {
224 let test_string = random_string(10);
225 let key = get_random_key(DEFAULT_CHARSET).unwrap();
226 assert!(validate_key(key, DEFAULT_CHARSET.len()).unwrap());
227 let ciphered_test_string = cipher(&test_string, key, DEFAULT_CHARSET).expect("Error getting ciphered text.");
228 let recovered_string = decipher(ciphered_test_string.as_str(), key, DEFAULT_CHARSET).unwrap();
229 assert_eq!(test_string, recovered_string);
230 }
231}