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