1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
extern crate rand;
use rand::Rng;
use std::str;
use std::i64;
use std::iter::Iterator;
pub fn xlat_prime() -> [u8; 53] {
return [
0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f,
0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72,
0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44, 0x48, 0x53,
0x55, 0x42, 0x73, 0x67, 0x76, 0x63, 0x61, 0x36,
0x39, 0x38, 0x33, 0x34, 0x6e, 0x63, 0x78, 0x76,
0x39, 0x38, 0x37, 0x33, 0x32, 0x35, 0x34, 0x6b,
0x3b, 0x66, 0x67, 0x38, 0x37
];
}
pub fn xlat(i : usize, len : usize) -> Vec<u8> {
let xs : [u8; 53] = xlat_prime();
let xs_len : usize = xs.len();
if len < 1 {
return Vec::new();
}
else {
let mut head : Vec<u8> = Vec::new();
head.push(xs[i % xs_len]);
let mut tail : Vec<u8> = xlat(i + 1, len - 1);
head.append(&mut tail);
return head;
}
}
pub fn xor(tp : (&u8, &u8)) -> u8 {
let (a, b) : (&u8, &u8) = tp;
return (*a) ^ (*b);
}
pub fn encrypt(password : &str) -> String {
let mut rng = rand::thread_rng();
let seed : usize = rng.gen_range(0, 16);
let plaintext : &[u8] = password.as_bytes();
let keys : Vec<u8> = xlat(seed, password.len());
assert_eq!(plaintext.len(), keys.len());
let zipped : Vec<(&u8, &u8)> = plaintext.iter().zip(keys.iter()).collect();
let ciphertext : Vec<u8> = zipped.iter().map(|pair| xor(*pair)).collect();
let hexpairs : Vec<String> = ciphertext.iter().map(|cipherbyte| format!("{:02x}", cipherbyte)).collect();
let hexdata : String = hexpairs.concat();
return format!("{:02}{}", seed, hexdata);
}
pub fn decrypt(hash : &str) -> String {
if hash.len() < 2 {
return "".to_string();
}
else {
let (seed_str, hash_str) : (&str, &str) = hash.split_at(2);
let seed : usize = seed_str.parse().expect("Invalid seed");
let codepoints : Vec<u8> = String::from(hash_str).bytes().collect();
let hexpairs : Vec<&[u8]> = codepoints.chunks(2).collect();
let ciphertext : Vec<u8> = hexpairs.iter().map(|hexpair| match str::from_utf8(*hexpair) {
Ok(v) => match i64::from_str_radix(v, 16) {
Ok(w) => w as u8,
Err(err) => panic!(err)
},
Err(err) => panic!(err)
}).collect();
let keys : Vec<u8> = xlat(seed, ciphertext.len());
assert_eq!(ciphertext.len(), keys.len());
let zipped : Vec<(&u8, &u8)> = ciphertext.iter().zip(keys.iter()).collect();
let plainbytes : Vec<u8> = zipped.iter().map(|pair| xor(*pair)).collect();
match String::from_utf8(plainbytes) {
Ok(password) => return password,
Err(err) => panic!(err)
};
}
}
#[test]
fn smoketest() {
assert_eq!(decrypt("1308181c00091d"), "monkey");
}