simple_encdec/
lib.rs

1use std::collections::VecDeque;
2
3/// Decrypt a given encrypted string
4///
5/// ## Example
6/// ```rust
7/// use simple_encdec::decrypt;
8///
9/// let x = decrypt("a=GQVGsbbyG982gd");
10/// assert!(x.is_some());
11/// assert_eq!(x.unwrap(), "hello world")l
12/// ```
13pub fn decrypt(s: &str) -> Option<String> {
14    let mut data = VecDeque::<char>::new();
15
16    for c in s.chars().collect::<Vec<_>>().chunks(2) {
17        if c.len() < 2 {
18            return None;
19        }
20        data.push_back(c[0]);
21        data.push_front(c[1]);
22    }
23
24    data.rotate_left(data.len() / 2);
25
26    data.iter()
27        .enumerate()
28        .filter_map(|(j, val)| {
29            val.to_string()
30                .trim()
31                .parse::<i32>()
32                .map(|val_parsed| (j, val_parsed))
33                .ok()
34        })
35        .collect::<Vec<_>>()
36        .chunks_exact(2)
37        .for_each(|items| {
38            if let [x, y] = items {
39                let xor = x.1 ^ y.1;
40                if xor < 10 {
41                    data[x.0] = xor.to_string().parse().unwrap();
42                }
43            }
44        });
45
46    let base64_enc = data.drain(..).collect::<String>();
47
48    match base64::decode(base64_enc) {
49        Ok(s) => String::from_utf8(s).ok(),
50        _ => None,
51    }
52}
53/// Encrypt a given plain text string
54///
55/// ## Example
56/// ```rust
57/// use simple_encdec::encrypt;
58///
59/// let x = encrypt("hello world");
60/// assert!(x.is_some());
61/// assert_eq!(x.unwrap(), "a=GQVGsbbyG982gd");
62/// ```
63pub fn encrypt(s: &str) -> Option<String> {
64    let base64_enc = base64::encode(s.as_bytes());
65    let mut data = base64_enc.as_bytes().to_vec();
66    let mut first: Option<(usize, u8)> = None;
67    for (i, c) in base64_enc.as_bytes().iter().enumerate() {
68        if (0x30..0x3a).any(|x| x == *c) {
69            if let Some(s) = first {
70                let f = s.1 ^ (c - 0x30);
71                if f < 10 {
72                    data[s.0] = f + 0x30;
73                }
74                first = None;
75            } else {
76                first = Some((i, c - 0x30));
77            }
78        }
79    }
80
81    let mut ss = vec![];
82    for i in 0..data.len() / 2 {
83        ss.push(data[i]);
84        ss.push(data[data.len() - 1 - i]);
85    }
86    if data.len() % 2 > 0 {
87        ss.push(data[data.len() / 2 + 1]);
88    }
89    String::from_utf8(ss).ok()
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn test_encrypt_decrypt() {
98        let original = "hello world";
99        let encoded = encrypt(original);
100        assert!(encoded.is_some());
101        let decoded = decrypt(&encoded.unwrap());
102        assert!(decoded.is_some());
103        assert_eq!(decoded.unwrap(), original);
104    }
105}