1use crate::utils::constants::URL;
2use crate::Error;
3use crate::Error::ServerSide;
4use aes::cipher::block_padding::{NoPadding, Pkcs7};
5use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
6use md5::Md5;
7use rand::random;
8use regex::Regex;
9use reqwest::header::HeaderMap;
10use reqwest::Client;
11use rsa::pkcs8::{DecodePublicKey, EncodePrivateKey, EncodePublicKey};
12use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
13use serde::de::DeserializeOwned;
14use serde::{Deserialize, Serialize};
15
16type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
17type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
18
19#[derive(Clone, Eq, PartialEq, Hash, Debug)]
20pub struct LanisKeyPair {
21 pub private_key: RsaPrivateKey,
22 pub public_key: RsaPublicKey,
23 pub private_key_string: String,
25 pub public_key_string: String,
27 pub public_key_lanis: String,
29}
30
31pub async fn generate_lanis_key_pair(
33 key_size: usize,
34 client: &Client,
35) -> Result<LanisKeyPair, Error> {
36 let mut rng = rand::thread_rng();
37 match RsaPrivateKey::new(&mut rng, key_size) {
38 Ok(private_key) => {
39 let public_key = RsaPublicKey::from(&private_key);
40
41 let private_key_string = private_key.to_pkcs8_pem(Default::default());
42 let public_key_string = public_key.to_public_key_pem(Default::default());
43
44 if private_key_string.is_ok() && public_key_string.is_ok() {
45 let private_key_string = private_key_string.unwrap().to_string();
46 let public_key_string = public_key_string.unwrap();
47
48 match handshake(client, &public_key_string).await {
49 Ok(public_key_lanis) => Ok(LanisKeyPair {
50 private_key,
51 public_key,
52 private_key_string,
53 public_key_string,
54 public_key_lanis,
55 }),
56 Err(e) => Err(ServerSide(format!(
57 "Handshake with lanis failed with error: '{}'",
58 e
59 ))),
60 }
61 } else {
62 Err(Error::Parsing(
63 "Failed to convert private key and/or public key to pkcs8 pem!".to_string(),
64 ))
65 }
66 }
67 Err(e) => Err(Error::Crypto(format!(
68 "Failed to generate Private key!: {}",
69 e
70 ))),
71 }
72}
73
74async fn handshake(client: &Client, public_own_key: &String) -> Result<String, String> {
75 let mut rng = rand::thread_rng();
76 let public_key = get_public_key(&client).await?;
77
78 match public_key.encrypt(&mut rng, Pkcs1v15Encrypt, public_own_key.as_bytes()) {
79 Ok(encrypted_key) => {
80
81 let encrypted_key = base64::Engine::encode(&base64::engine::general_purpose::STANDARD, encrypted_key);
82
83 let mut headers = HeaderMap::new();
84 headers.insert("Accept", "*/*".parse().unwrap());
85 headers.insert("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8".parse().unwrap());
86 headers.insert("Sec-Fetch-Dest", "empty".parse().unwrap());
87 headers.insert("Sec-Fetch-Mode", "cors".parse().unwrap());
88 headers.insert("Sec-Fetch-Site", "same-origin".parse().unwrap());
89
90 match client.post(URL::AJAX).headers(headers).query(&[("f", "rsaHandshake"), ("s", "1111")]).form(&[("key", &encrypted_key)]).send().await {
91 Ok(response) => {
92 #[derive(Debug, Deserialize)]
93 struct ResponseData {
94 challenge: String,
95 }
96
97 match serde_json::from_str::<ResponseData>(response.text().await.unwrap().as_str()) {
98 Ok(data) => {
99 match base64::Engine::decode(&base64::engine::general_purpose::STANDARD, &data.challenge) {
100 Ok(challenge) => {
101 let result = decrypt_lanis_with_key(&challenge, public_own_key).await?;
102 let result_string = String::from_utf8_lossy(&result);
103 let result_string = result_string.trim();
104 if result_string == public_own_key.trim() {
105 Ok(encrypted_key)
106 } else {
107 Err(format!("Failed to perform challenge! Public Keys don't match!:\nOwn Public Key:\n{}\n\nResponse Public Key:\n{}", public_own_key, result_string))
108 }
109 }
110 Err(e) => {
111 Err(format!("Failed to decode challenge with error: '{}'", e))
112 }
113 }
114 }
115 Err(e) => {
116 Err(format!("Failed to decode json with error: '{}'", e))
117 }
118 }
119 }
120 Err(e) => Err(format!("Failed to perform handshake with error: '{}'", e)),
121 }
122 }
123 Err(e) => {
124 Err(format!("Failed to encrypt with error: '{}'\nIs your public key to long? Maybe take a look at the documentation of the key 'key_pair' in struct 'Account'", e))
125 }
126 }
127}
128
129async fn get_public_key(client: &Client) -> Result<RsaPublicKey, String> {
130 let mut headers = HeaderMap::new();
131 headers.insert("Accept", "*/*".parse().unwrap());
132 headers.insert(
133 "Content-Type",
134 "application/x-www-form-urlencoded; charset=UTF-8"
135 .parse()
136 .unwrap(),
137 );
138 headers.insert("Sec-Fetch-Dest", "empty".parse().unwrap());
139 headers.insert("Sec-Fetch-Mode", "cors".parse().unwrap());
140 headers.insert("Sec-Fetch-Site", "same-origin".parse().unwrap());
141
142 match client
143 .post(URL::AJAX)
144 .headers(headers)
145 .query(&[("f", "rsaPublicKey")])
146 .send()
147 .await
148 {
149 Ok(response) => {
150 #[derive(Debug, Deserialize)]
151 struct FuckYouLanis {
153 publickey: String,
154 }
155
156 let response_json = response.text().await.unwrap();
157 let json: FuckYouLanis = serde_json::from_str(&response_json).unwrap();
158 let public_key = json.publickey;
159 let public_key = RsaPublicKey::from_public_key_pem(&public_key).unwrap();
160
161 Ok(public_key)
162 }
163 Err(e) => Err(format!("Failed to get public key with error: {}", e)),
164 }
165}
166
167pub async fn encrypt_lanis_data(data: &[u8], public_key: &String) -> String {
169 let salt = random::<[u8; 8]>();
170
171 const KEY_SIZE: usize = 256;
172 const IV_SIZE: usize = 128;
173
174 let mut output = [0; (KEY_SIZE + IV_SIZE) / 8];
175 evpkdf::evpkdf::<Md5>(public_key.as_bytes(), &salt, 1, &mut output);
176
177 let (key, iv) = output.split_at(KEY_SIZE / 8);
178
179 let key: [u8; 32] = key.try_into().unwrap();
180 let iv: [u8; 16] = iv.try_into().unwrap();
181
182 let encryptor = Aes256CbcEnc::new(&key.into(), &iv.into());
183
184 let encrypted = {
185 let salted = "Salted__".to_string();
186 let salted = salted.as_bytes();
187
188 let encrypted = encryptor.encrypt_padded_vec_mut::<Pkcs7>(&data);
189
190 let mut result: Vec<u8> = Vec::new();
191 result.extend(salted);
192 result.extend(salt);
193 result.extend(encrypted);
194
195 result
196 };
197
198 let result = base64::Engine::encode(&base64::engine::general_purpose::STANDARD, encrypted);
199
200 result
201}
202
203pub async fn decrypt_lanis_encoded_tags(html_string: &str, key: &String) -> String {
205 let exp = Regex::new(r"<encoded>(.*?)</encoded>").unwrap();
206
207 let mut replaced_html = html_string.to_string();
208
209 for caps in exp.captures_iter(html_string) {
210 if let Some(encoded_content) = caps.get(1) {
211 let decrypted_content =
212 decrypt_lanis_string_with_key(encoded_content.as_str(), key).await;
213 let decrypted_string = decrypted_content.unwrap_or_default();
214 replaced_html = replaced_html.replacen(&caps[0], &decrypted_string, 1);
215 }
216 }
217
218 replaced_html.to_string()
219}
220
221pub async fn decrypt_lanis_string_with_key(
223 data: &str,
224 public_key: &String,
225) -> Result<String, String> {
226 match base64::Engine::decode(&base64::engine::general_purpose::STANDARD, &data) {
227 Ok(data) => {
228 let result = decrypt_lanis_with_key(&data, &public_key).await?;
229 let result_string = String::from_utf8_lossy(&result);
230 let result_string = result_string.trim();
231 Ok(result_string.to_string())
232 }
233 Err(e) => Err(format!(
234 "Failed to decode base64 string with error: '{}'",
235 e
236 )),
237 }
238}
239
240pub async fn decrypt_lanis_with_key(
242 data: &Vec<u8>,
243 public_key: &String,
244) -> Result<Vec<u8>, String> {
245 fn is_salted(encrypted_data: &Vec<u8>) -> bool {
246 match std::str::from_utf8(&encrypted_data[0..8]) {
247 Ok(s) => s == "Salted__",
248 Err(_) => false,
249 }
250 }
251
252 if !is_salted(&data) {
253 return Err("Data is not salted!".to_string());
254 }
255
256 let salt = &data[8..16];
257
258 const KEY_SIZE: usize = 256;
259 const IV_SIZE: usize = 128;
260
261 let mut output = [0; (KEY_SIZE + IV_SIZE) / 8];
262
263 evpkdf::evpkdf::<Md5>(public_key.as_bytes(), salt, 1, &mut output);
264
265 let (key, iv) = output.split_at(KEY_SIZE / 8);
266
267 let key: [u8; 32] = key.try_into().unwrap();
268 let iv: [u8; 16] = iv.try_into().unwrap();
269
270 let decryptor = Aes256CbcDec::new(&key.into(), &iv.into());
271
272 let result = decryptor
273 .decrypt_padded_vec_mut::<NoPadding>(&data[16..])
274 .unwrap();
275
276 Ok(result)
277}
278
279#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
280pub enum CryptorError {
281 Serialization(String),
283 Deserialization(String),
285 Decryption(String),
287}
288
289pub async fn encrypt_any<T: Clone + Serialize>(
291 data: &T,
292 key: &[u8; 32],
293) -> Result<Vec<u8>, CryptorError> {
294 let iv = [0; 16];
295
296 let serialized =
297 serde_json::to_vec(&data).map_err(|e| CryptorError::Serialization(e.to_string()))?;
298
299 let cipher = Aes256CbcEnc::new(&(*key).into(), &iv.into());
300 let result = cipher.encrypt_padded_vec_mut::<Pkcs7>(serialized.as_slice());
301
302 Ok(result)
303}
304
305pub async fn decrypt_any<T: Clone + DeserializeOwned>(
307 data: &[u8],
308 key: &[u8; 32],
309) -> Result<T, CryptorError> {
310 let iv = [0; 16];
311
312 let decryptor = Aes256CbcDec::new(&(*key).into(), &iv.into());
313 let decrypted = decryptor
314 .decrypt_padded_vec_mut::<Pkcs7>(data)
315 .map_err(|e| CryptorError::Decryption(e.to_string()))?;
316
317 let result: T = serde_json::from_slice(&decrypted)
318 .map_err(|e| CryptorError::Deserialization(e.to_string()))?;
319 Ok(result)
320}
321