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