1use super::der;
10use byteorder::{BigEndian, ByteOrder};
11use num_bigint::BigUint;
12use sha1::{Digest, Sha1};
13
14pub trait Padding {
16 fn pub_pad(&mut self, input: impl AsRef<[u8]>, k: usize) -> Vec<u8>;
18}
19
20pub trait Rng {
22 type Error: std::error::Error;
23
24 fn fill(&mut self, dest: &mut [u8]) -> Result<(), Self::Error>;
26}
27
28pub struct GetRandom;
30
31impl Rng for GetRandom {
32 type Error = getrandom::Error;
33
34 fn fill(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
35 getrandom::fill(dest)
36 }
37}
38
39#[derive(Debug)]
41pub struct Pkcs1Padding<T> {
42 rng: T,
43}
44
45impl<T> Pkcs1Padding<T> {
46 pub fn new(rng: T) -> Self {
47 Self { rng }
48 }
49}
50
51impl<T: Rng> Padding for Pkcs1Padding<T> {
52 fn pub_pad(&mut self, input: impl AsRef<[u8]>, k: usize) -> Vec<u8> {
53 let input = input.as_ref();
54 let input_len = input.len();
55 assert!(
56 input_len < k - 11,
57 "The length of the data D shall not be more than k-11 octets"
58 );
59
60 let mut output = vec![0u8; k];
61
62 output[0] = 0x00;
63 output[1] = 0x02;
64 let ps_len = k - 3 - input_len;
65
66 for i in 0..ps_len {
67 while output[i + 2] == 0 {
68 self.rng
69 .fill(&mut output[i + 2..=i + 2])
70 .expect("rng ran out of entropy while padding");
71 }
72 }
73
74 output[2 + ps_len] = 0x00;
75 output[2 + ps_len + 1..].copy_from_slice(input);
76 output
77 }
78}
79
80#[derive(Debug)]
82pub struct Pkcs1OaepPadding<T> {
83 rng: T,
84}
85
86impl<T> Pkcs1OaepPadding<T> {
87 const HASH_LEN: usize = 20;
89
90 pub fn new(rng: T) -> Self {
91 Self { rng }
92 }
93
94 fn mgf1(seed: &[u8], len: usize) -> Vec<u8> {
98 if len as u64 > 2u64.pow(32) * Self::HASH_LEN as u64 {
99 panic!("mask too long");
100 }
101
102 fn ceil_div(dividend: usize, divisor: usize) -> usize {
103 let mut quotient = dividend / divisor;
104 if dividend % divisor > 0 {
105 quotient += 1;
106 }
107 quotient
108 }
109
110 let output = (0..ceil_div(len, Self::HASH_LEN))
111 .map(|c| {
112 let cs = &mut [0u8; 4];
113 BigEndian::write_u32(cs, c as u32);
114 Sha1::digest([seed, cs].concat()).to_vec()
115 })
116 .collect::<Vec<Vec<u8>>>()
117 .concat();
118
119 output[..len].into()
120 }
121}
122
123impl<T: Rng> Padding for Pkcs1OaepPadding<T> {
124 fn pub_pad(&mut self, input: impl AsRef<[u8]>, k: usize) -> Vec<u8> {
126 let input = input.as_ref();
127 if input.len() > k - 2 * Self::HASH_LEN - 1 {
130 panic!("message too long");
131 }
132 let mut ps = vec![0; k - input.len() - 2 * Self::HASH_LEN - 2];
135 ps.push(0x01);
136 let p_hash = Sha1::digest([]).to_vec();
138 let db = [&*p_hash, &*ps, input].concat();
141 let mut seed = vec![0; Self::HASH_LEN];
143 self.rng.fill(&mut seed[..]).expect("rng out of entropy");
144 let db_mask = Self::mgf1(&seed, k - Self::HASH_LEN);
146 let masked_db: Vec<_> = db.into_iter().zip(db_mask).map(|(a, b)| a ^ b).collect();
148 let seed_mask = Self::mgf1(&masked_db, Self::HASH_LEN);
150 let masked_seed: Vec<_> = seed
152 .into_iter()
153 .zip(seed_mask)
154 .map(|(a, b)| a ^ b)
155 .collect();
156 [&*masked_seed, &*masked_db].concat()
158 }
159}
160
161#[derive(Debug)]
162pub struct PublicKey {
163 modulus: BigUint,
164 exponent: BigUint,
165}
166
167impl PublicKey {
168 pub fn new(modulus: BigUint, exponent: BigUint) -> PublicKey {
170 PublicKey { modulus, exponent }
171 }
172
173 pub fn from_pem(pem_data: impl AsRef<[u8]>) -> PublicKey {
179 let (der, file_type) = der::pem_to_der(pem_data);
180 let (modulus, exponent) = der::parse_pub_key(&der, file_type);
181 PublicKey::new(modulus, exponent)
182 }
183
184 pub fn num_octets(&self) -> usize {
186 (self.modulus.bits() as usize + 6) >> 3
187 }
188
189 pub fn modulus(&self) -> &BigUint {
191 &self.modulus
192 }
193
194 pub fn exponent(&self) -> &BigUint {
196 &self.exponent
197 }
198
199 pub fn encrypt_block(&self, block: impl AsRef<[u8]>, mut pad: impl Padding) -> Vec<u8> {
205 let enc_block = pad.pub_pad(block, self.num_octets());
206 let enc_int = BigUint::from_bytes_be(&enc_block);
207 let rsa = enc_int.modpow(self.exponent(), self.modulus());
208 let mut rsa_bytes = rsa.to_bytes_be();
209 while rsa_bytes.len() < self.num_octets() {
211 rsa_bytes.insert(0, 0);
212 }
213 rsa_bytes
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use std::io::Read;
220
221 use super::*;
222
223 const SEED: &[u8; 64] = b"\x03\x2e\x45\x32\x6f\xa8\x59\xa7\x2e\xc2\x35\xac\xff\x92\x9b\x15\xd1\
224 \x37\x2e\x30\xb2\x07\x25\x5f\x06\x11\xb8\xf7\x85\xd7\x64\x37\x41\x52\xe0\xac\x00\x9e\x50\x9e\
225 \x7b\xa3\x0c\xd2\xf1\x77\x8e\x11\x3b\x64\xe1\x35\xcf\x4e\x22\x92\xc7\x5e\xfe\x52\x88\xed\xfd\
226 \xa4";
227 const MASK: &[u8; 128] =
228 b"\x5f\x8d\xe1\x05\xb5\xe9\x6b\x2e\x49\x0d\xde\xcb\xd1\x47\xdd\x1d\xef\
229 \x7e\x3b\x8e\x0e\x6a\x26\xeb\x7b\x95\x6c\xcb\x8b\x3b\xdc\x1c\xa9\x75\xbc\x57\xc3\x98\x9e\x8f\
230 \xba\xd3\x1a\x22\x46\x55\xd8\x00\xc4\x69\x54\x84\x0f\xf3\x20\x52\xcd\xf0\xd6\x40\x56\x2b\xdf\
231 \xad\xfa\x26\x3c\xfc\xcf\x3c\x52\xb2\x9f\x2a\xf4\xa1\x86\x99\x59\xbc\x77\xf8\x54\xcf\x15\xbd\
232 \x7a\x25\x19\x29\x85\xa8\x42\xdb\xff\x8e\x13\xef\xee\x5b\x7e\x7e\x55\xbb\xe4\xd3\x89\x64\x7c\
233 \x68\x6a\x9a\x9a\xb3\xfb\x88\x9b\x2d\x77\x67\xd3\x83\x7e\xea\x4e\x0a\x2f\x04";
234
235 struct Seed<'a>(&'a [u8]);
236
237 impl<'a> Rng for Seed<'a> {
238 type Error = std::io::Error;
239
240 fn fill(&mut self, dest: &mut [u8]) -> Result<(), std::io::Error> {
241 self.0.read_exact(dest)
242 }
243 }
244
245 #[test]
246 fn mgf1() {
247 let mask = Pkcs1OaepPadding::<()>::mgf1(&SEED[..], 128);
248 assert_eq!(mask, &MASK[..]);
249 }
250
251 #[test]
252 fn rsa_pkcs() {
253 let modulus: &[u8] = &[
254 0xa8, 0xb3, 0xb2, 0x84, 0xaf, 0x8e, 0xb5, 0x0b, 0x38, 0x70, 0x34, 0xa8, 0x60, 0xf1,
255 0x46, 0xc4, 0x91, 0x9f, 0x31, 0x87, 0x63, 0xcd, 0x6c, 0x55, 0x98, 0xc8, 0xae, 0x48,
256 0x11, 0xa1, 0xe0, 0xab, 0xc4, 0xc7, 0xe0, 0xb0, 0x82, 0xd6, 0x93, 0xa5, 0xe7, 0xfc,
257 0xed, 0x67, 0x5c, 0xf4, 0x66, 0x85, 0x12, 0x77, 0x2c, 0x0c, 0xbc, 0x64, 0xa7, 0x42,
258 0xc6, 0xc6, 0x30, 0xf5, 0x33, 0xc8, 0xcc, 0x72, 0xf6, 0x2a, 0xe8, 0x33, 0xc4, 0x0b,
259 0xf2, 0x58, 0x42, 0xe9, 0x84, 0xbb, 0x78, 0xbd, 0xbf, 0x97, 0xc0, 0x10, 0x7d, 0x55,
260 0xbd, 0xb6, 0x62, 0xf5, 0xc4, 0xe0, 0xfa, 0xb9, 0x84, 0x5c, 0xb5, 0x14, 0x8e, 0xf7,
261 0x39, 0x2d, 0xd3, 0xaa, 0xff, 0x93, 0xae, 0x1e, 0x6b, 0x66, 0x7b, 0xb3, 0xd4, 0x24,
262 0x76, 0x16, 0xd4, 0xf5, 0xba, 0x10, 0xd4, 0xcf, 0xd2, 0x26, 0xde, 0x88, 0xd3, 0x9f,
263 0x16, 0xfb,
264 ];
265 let exponent: &[u8] = &[0x01, 0x00, 0x01];
266
267 let msg1: &[u8] = &[
268 0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, 0x3b, 0xa9, 0x4c, 0xda, 0x9e, 0xf9,
269 0x53, 0x23, 0x97, 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, 0x4a, 0xfe, 0xfe, 0x34,
270 ];
271 let seed1: &[u8] = &[
272 0x01, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xae, 0x00,
273 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00,
274 0xf8, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0x00,
275 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00,
276 0xb9, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6b, 0x00,
277 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
278 0xfc, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xf4, 0x00,
279 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
280 0x5b, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x55, 0x00,
281 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00,
282 0x93, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x04, 0x00,
283 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
284 0xeb, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x5e, 0x00,
285 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00,
286 0xb4, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x88, 0x00,
287 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
288 0x4d, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0xf5, 0x00,
289 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
290 0x38, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xce, 0x00,
291 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
292 0x4b, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x96, 0x00,
293 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
294 0xd6, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x97, 0x00,
295 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
296 0x9b, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x83, 0x00,
297 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
298 0x84, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xab, 0x00,
299 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
300 ];
301 let cipher_text1 = vec![
302 0x50, 0xb4, 0xc1, 0x41, 0x36, 0xbd, 0x19, 0x8c, 0x2f, 0x3c, 0x3e, 0xd2, 0x43, 0xfc,
303 0xe0, 0x36, 0xe1, 0x68, 0xd5, 0x65, 0x17, 0x98, 0x4a, 0x26, 0x3c, 0xd6, 0x64, 0x92,
304 0xb8, 0x08, 0x04, 0xf1, 0x69, 0xd2, 0x10, 0xf2, 0xb9, 0xbd, 0xfb, 0x48, 0xb1, 0x2f,
305 0x9e, 0xa0, 0x50, 0x09, 0xc7, 0x7d, 0xa2, 0x57, 0xcc, 0x60, 0x0c, 0xce, 0xfe, 0x3a,
306 0x62, 0x83, 0x78, 0x9d, 0x8e, 0xa0, 0xe6, 0x07, 0xac, 0x58, 0xe2, 0x69, 0x0e, 0xc4,
307 0xeb, 0xc1, 0x01, 0x46, 0xe8, 0xcb, 0xaa, 0x5e, 0xd4, 0xd5, 0xcc, 0xe6, 0xfe, 0x7b,
308 0x0f, 0xf9, 0xef, 0xc1, 0xea, 0xbb, 0x56, 0x4d, 0xbf, 0x49, 0x82, 0x85, 0xf4, 0x49,
309 0xee, 0x61, 0xdd, 0x7b, 0x42, 0xee, 0x5b, 0x58, 0x92, 0xcb, 0x90, 0x60, 0x1f, 0x30,
310 0xcd, 0xa0, 0x7b, 0xf2, 0x64, 0x89, 0x31, 0x0b, 0xcd, 0x23, 0xb5, 0x28, 0xce, 0xab,
311 0x3c, 0x31,
312 ];
313
314 let public_key = PublicKey::new(
315 BigUint::from_bytes_be(modulus),
316 BigUint::from_bytes_be(exponent),
317 );
318
319 let rng = Seed(seed1);
320 let pad = Pkcs1Padding::new(rng);
321
322 let cipher_text = public_key.encrypt_block(msg1, pad);
323 assert_eq!(cipher_text, cipher_text1);
324 }
325
326 #[test]
327 fn rsa_oaep() {
328 let modulus: &[u8] = &[
329 0xbb, 0xf8, 0x2f, 0x09, 0x06, 0x82, 0xce, 0x9c, 0x23, 0x38, 0xac, 0x2b, 0x9d, 0xa8,
330 0x71, 0xf7, 0x36, 0x8d, 0x07, 0xee, 0xd4, 0x10, 0x43, 0xa4, 0x40, 0xd6, 0xb6, 0xf0,
331 0x74, 0x54, 0xf5, 0x1f, 0xb8, 0xdf, 0xba, 0xaf, 0x03, 0x5c, 0x02, 0xab, 0x61, 0xea,
332 0x48, 0xce, 0xeb, 0x6f, 0xcd, 0x48, 0x76, 0xed, 0x52, 0x0d, 0x60, 0xe1, 0xec, 0x46,
333 0x19, 0x71, 0x9d, 0x8a, 0x5b, 0x8b, 0x80, 0x7f, 0xaf, 0xb8, 0xe0, 0xa3, 0xdf, 0xc7,
334 0x37, 0x72, 0x3e, 0xe6, 0xb4, 0xb7, 0xd9, 0x3a, 0x25, 0x84, 0xee, 0x6a, 0x64, 0x9d,
335 0x06, 0x09, 0x53, 0x74, 0x88, 0x34, 0xb2, 0x45, 0x45, 0x98, 0x39, 0x4e, 0xe0, 0xaa,
336 0xb1, 0x2d, 0x7b, 0x61, 0xa5, 0x1f, 0x52, 0x7a, 0x9a, 0x41, 0xf6, 0xc1, 0x68, 0x7f,
337 0xe2, 0x53, 0x72, 0x98, 0xca, 0x2a, 0x8f, 0x59, 0x46, 0xf8, 0xe5, 0xfd, 0x09, 0x1d,
338 0xbd, 0xcb,
339 ];
340 let exponent: &[u8] = &[0x11];
341 let msg: &[u8] = &[
342 0xd4, 0x36, 0xe9, 0x95, 0x69, 0xfd, 0x32, 0xa7, 0xc8, 0xa0, 0x5b, 0xbc, 0x90, 0xd3,
343 0x2c, 0x49,
344 ];
345 let seed: &[u8] = &[
346 0xaa, 0xfd, 0x12, 0xf6, 0x59, 0xca, 0xe6, 0x34, 0x89, 0xb4, 0x79, 0xe5, 0x07, 0x6d,
347 0xde, 0xc2, 0xf0, 0x6c, 0xb5, 0x8f,
348 ];
349 let correct_cipher_text = vec![
350 0x12, 0x53, 0xe0, 0x4d, 0xc0, 0xa5, 0x39, 0x7b, 0xb4, 0x4a, 0x7a, 0xb8, 0x7e, 0x9b,
351 0xf2, 0xa0, 0x39, 0xa3, 0x3d, 0x1e, 0x99, 0x6f, 0xc8, 0x2a, 0x94, 0xcc, 0xd3, 0x00,
352 0x74, 0xc9, 0x5d, 0xf7, 0x63, 0x72, 0x20, 0x17, 0x06, 0x9e, 0x52, 0x68, 0xda, 0x5d,
353 0x1c, 0x0b, 0x4f, 0x87, 0x2c, 0xf6, 0x53, 0xc1, 0x1d, 0xf8, 0x23, 0x14, 0xa6, 0x79,
354 0x68, 0xdf, 0xea, 0xe2, 0x8d, 0xef, 0x04, 0xbb, 0x6d, 0x84, 0xb1, 0xc3, 0x1d, 0x65,
355 0x4a, 0x19, 0x70, 0xe5, 0x78, 0x3b, 0xd6, 0xeb, 0x96, 0xa0, 0x24, 0xc2, 0xca, 0x2f,
356 0x4a, 0x90, 0xfe, 0x9f, 0x2e, 0xf5, 0xc9, 0xc1, 0x40, 0xe5, 0xbb, 0x48, 0xda, 0x95,
357 0x36, 0xad, 0x87, 0x00, 0xc8, 0x4f, 0xc9, 0x13, 0x0a, 0xde, 0xa7, 0x4e, 0x55, 0x8d,
358 0x51, 0xa7, 0x4d, 0xdf, 0x85, 0xd8, 0xb5, 0x0d, 0xe9, 0x68, 0x38, 0xd6, 0x06, 0x3e,
359 0x09, 0x55,
360 ];
361
362 let public_key = PublicKey::new(
363 BigUint::from_bytes_be(modulus),
364 BigUint::from_bytes_be(exponent),
365 );
366
367 let rng = Seed(seed);
368 let pad = Pkcs1OaepPadding::new(rng);
369
370 let cipher_text = public_key.encrypt_block(msg, pad);
371 assert_eq!(cipher_text, correct_cipher_text);
372 }
373}