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
#![warn(rust_2018_idioms)]
extern crate proc_macro;
use proc_macro2::Span;
use quote::quote;
use std::{
num::Wrapping,
time::{SystemTime, UNIX_EPOCH},
};
use syn::{parse_macro_input, Lit};
lazy_static::lazy_static! {
static ref XORKEY: Wrapping<u8> =
Wrapping(xorstr_random_number(Wrapping(0), Wrapping(<u8>::max_value().into())).0 as u8);
static ref TEMP_KEY: Wrapping<u32> =
Wrapping(SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as u32)
& Wrapping(0xFFFFFFF);
}
fn linear_congruent_generator(rounds: u32) -> Wrapping<u32> {
Wrapping(1013904223)
+ Wrapping(1664525)
* if rounds <= 0 {
*TEMP_KEY
} else {
linear_congruent_generator(rounds - 1)
}
}
fn xorstr_random() -> Wrapping<u32> {
linear_congruent_generator(10)
}
fn xorstr_random_number(min: Wrapping<u32>, max: Wrapping<u32>) -> Wrapping<u32> {
min + xorstr_random() % (max - min + Wrapping(1))
}
#[proc_macro]
pub fn xorstring(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
if input.is_empty() {
let key = XORKEY.0;
return quote! { (#key as u8) }.into();
}
let string: Lit = parse_macro_input!(input as Lit);
let string = match string {
Lit::ByteStr(lit) => lit,
_ => panic!("not byte string input"),
};
let mut encrypted = string.value();
for (i, c) in encrypted.iter_mut().enumerate() {
*c ^= (Wrapping(XORKEY.0 as usize) + Wrapping(i)).0 as u8;
}
let lit = syn::LitByteStr::new(encrypted.as_slice(), Span::call_site());
return quote! { (#lit as &[u8]) }.into();
}