1use crate::{aes, sha256};
22use num_bigint::BigUint;
23
24pub struct Key {
26 n: BigUint,
27 e: BigUint,
28}
29
30impl Key {
31 pub fn new(n: &str, e: &str) -> Option<Self> {
33 Some(Self {
34 n: BigUint::parse_bytes(n.as_bytes(), 10)?,
35 e: BigUint::parse_bytes(e.as_bytes(), 10)?,
36 })
37 }
38}
39
40fn increment(data: &mut [u8]) {
41 let mut i = data.len() - 1;
42 loop {
43 let (n, overflow) = data[i].overflowing_add(1);
44 data[i] = n;
45 if overflow {
46 i = i.checked_sub(1).unwrap_or(data.len() - 1);
47 } else {
48 break;
49 }
50 }
51}
52
53pub fn encrypt_hashed(data: &[u8], key: &Key, random_bytes: &[u8; 224]) -> Vec<u8> {
58 assert!(data.len() <= 144, "data too large for RSA-PAD");
59
60 let mut data_with_padding = Vec::with_capacity(192);
62 data_with_padding.extend_from_slice(data);
63 data_with_padding.extend_from_slice(&random_bytes[..192 - data.len()]);
64
65 let data_pad_reversed: Vec<u8> = data_with_padding.iter().copied().rev().collect();
67
68 let mut temp_key: [u8; 32] = random_bytes[192..].try_into().unwrap();
69
70 let key_aes_encrypted = loop {
71 let mut data_with_hash = Vec::with_capacity(224);
73 data_with_hash.extend_from_slice(&data_pad_reversed);
74 data_with_hash.extend_from_slice(&sha256!(&temp_key, &data_with_padding));
75
76 aes::ige_encrypt(&mut data_with_hash, &temp_key, &[0u8; 32]);
77
78 let hash = sha256!(&data_with_hash);
80 let mut xored = temp_key;
81 for (a, b) in xored.iter_mut().zip(hash.iter()) {
82 *a ^= b;
83 }
84
85 let mut candidate = Vec::with_capacity(256);
86 candidate.extend_from_slice(&xored);
87 candidate.extend_from_slice(&data_with_hash);
88
89 if BigUint::from_bytes_be(&candidate) < key.n {
90 break candidate;
91 }
92 increment(&mut temp_key);
93 };
94
95 let payload = BigUint::from_bytes_be(&key_aes_encrypted);
96 let encrypted = payload.modpow(&key.e, &key.n);
97 let mut block = encrypted.to_bytes_be();
98 while block.len() < 256 {
99 block.insert(0, 0);
100 }
101 block
102}