1use num_bigint::BigUint;
14
15use crate::{aes, sha256};
16
17pub struct Key {
19 n: BigUint,
20 e: BigUint,
21}
22
23impl Key {
24 pub fn new(n: &str, e: &str) -> Option<Self> {
25 Some(Self {
26 n: BigUint::parse_bytes(n.as_bytes(), 10)?,
27 e: BigUint::parse_bytes(e.as_bytes(), 10)?,
28 })
29 }
30}
31
32fn increment(data: &mut [u8]) {
34 let mut i = data.len() - 1;
35 loop {
36 let (n, overflow) = data[i].overflowing_add(1);
37 data[i] = n;
38 if overflow {
39 if let Some(ni) = i.checked_sub(1) {
40 i = ni
41 } else {
42 i = data.len() - 1;
43 }
44 } else {
45 break;
46 }
47 }
48}
49
50pub fn encrypt_hashed(data: &[u8], key: &Key, random_bytes: &[u8; 224]) -> Vec<u8> {
52 assert!(data.len() <= 144);
56 let data_with_padding = {
57 let mut buffer = Vec::with_capacity(192);
58 buffer.extend(data);
59 buffer.extend(&random_bytes[..192 - data.len()]);
60 buffer
61 };
62
63 let data_pad_reversed = data_with_padding.iter().copied().rev().collect::<Vec<u8>>();
65
66 let mut temp_key: [u8; 32] = random_bytes[192..192 + 32].try_into().unwrap();
68
69 let key_aes_encrypted = loop {
70 let mut data_with_hash = {
72 let mut buffer = Vec::with_capacity(224);
73 buffer.extend(&data_pad_reversed);
74 buffer.extend(sha256!(&temp_key, &data_with_padding));
75 buffer
76 };
77
78 aes::ige_encrypt(data_with_hash.as_mut(), &temp_key, &[0u8; 32]);
80 let aes_encrypted = data_with_hash;
81
82 let temp_key_xor = {
84 let mut xored = temp_key;
85 xored
86 .iter_mut()
87 .zip(sha256!(&aes_encrypted))
88 .for_each(|(a, b)| *a ^= b);
89 xored
90 };
91
92 let key_aes_encrypted = {
94 let mut buffer = Vec::with_capacity(256);
95 buffer.extend(temp_key_xor);
96 buffer.extend(aes_encrypted);
97 buffer
98 };
99
100 if BigUint::from_bytes_be(&key_aes_encrypted) >= key.n {
102 increment(&mut temp_key);
104 continue;
105 }
106
107 break key_aes_encrypted;
109 };
110
111 let payload = BigUint::from_bytes_be(&key_aes_encrypted);
113 let encrypted = payload.modpow(&key.e, &key.n);
114 let mut block = encrypted.to_bytes_be();
115 while block.len() < 256 {
116 block.insert(0, 0);
117 }
118
119 block
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use crate::hex;
126
127 #[test]
128 fn test_rsa_encryption() {
129 let key = Key::new("25342889448840415564971689590713473206898847759084779052582026594546022463853940585885215951168491965708222649399180603818074200620463776135424884632162512403163793083921641631564740959529419359595852941166848940585952337613333022396096584117954892216031229237302943701877588456738335398602461675225081791820393153757504952636234951323237820036543581047826906120927972487366805292115792231423684261262330394324750785450942589751755390156647751460719351439969059949569615302809050721500330239005077889855323917509948255722081644689442127297605422579707142646660768825302832201908302295573257427896031830742328565032949", "65537").unwrap();
130 let result = encrypt_hashed(
131 &hex::from_hex("955ff5a9081a8e635f5743de9b00000004453dc27100000004622f1fcb000000f7a81627bbf511fa4afef71e94a0937474586c1add9198dda81a5df8393871c8293623c5fb968894af1be7dfe9c7be813f9307789242fd0cb0c16a5cb39a8d3e"),
132 &key,
133 hex::from_hex("12270000635593b03fee033d0672f9afddf9124de9e77df6251806cba93482e4c9e6e06e7d44e4c4baae821aff91af44789689faaee9bdfc7b2df8c08709afe57396c4638ceaa0dc30114f82447e81d3b53edc423b32660c43a5b8ad057b64500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007dada0920c4973913229e0f881aec7b9db0c392d34f52fb0995ea493ecb4c09d").as_slice().try_into().unwrap(),
134 );
135 assert_eq!(
136 result,
137 hex::from_hex(
138 "b610642a828b4a61fe32931815cae318d311660580f1e0df768f3140f4d37dfcfcac0c2870318de4ff2d2e0e9669bcfdc0bad06cadb1b59d9726b427368a9c7b4fc0d5e7b2e99fc571968705c03acf5341fd7021bef653fa77b3776ae430e366fc46d232459ebe128b08d80e049ae579a48b56ca93b520709468587c81af96666046e9ea85091d729e921e8d8a36f57b27644052dae7387c7f4131701d59cda75251dac66c94276280ef950d3c44c21e5a2454f7da7a6818cf23ae9c490b72b2170d7cbc24f8a93db739d76f2d241c78b80123faaff3e664f074d6375d794dbf2800a0b5bb48d54eceafedfb355bfbebd287d9023264e3b53627888250787a9e"
139 )
140 );
141 }
142}