mysql_common/crypto/
rsa.rs

1// Copyright (c) 2021 Anatoly Ikorsky
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use super::der;
10use byteorder::{BigEndian, ByteOrder};
11use num_bigint::BigUint;
12use sha1::{Digest, Sha1};
13
14/// Padding operation trait.
15pub trait Padding {
16    /// Padding operation for `input` bytes, where `k` is the length of modulus in octets.
17    fn pub_pad(&mut self, input: impl AsRef<[u8]>, k: usize) -> Vec<u8>;
18}
19
20/// Represents a source of random bytes.
21pub trait Rng {
22    type Error: std::error::Error;
23
24    /// Implementor must fill all the bytes in the `dest`.
25    fn fill(&mut self, dest: &mut [u8]) -> Result<(), Self::Error>;
26}
27
28/// Randomness source based on the [`getrandom::fill`].
29pub 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/// Padding, as described in PKCS #1: RSA Encryption Version 1.5 (rfc2313).
40#[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/// Padding, as described in PKCS #1: RSA Cryptography Specifications Version 2.0 (rfc2437).
81#[derive(Debug)]
82pub struct Pkcs1OaepPadding<T> {
83    rng: T,
84}
85
86impl<T> Pkcs1OaepPadding<T> {
87    /// Length of a SHA-1 hash digest.
88    const HASH_LEN: usize = 20;
89
90    pub fn new(rng: T) -> Self {
91        Self { rng }
92    }
93
94    /// Mask Generation Function as defined in rfc2437.
95    ///
96    /// It will use SHA-1 as a hash function.
97    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    /// Will pad input according to PKCS #1 v2 with encoding parameters equal to `[]`.
125    fn pub_pad(&mut self, input: impl AsRef<[u8]>, k: usize) -> Vec<u8> {
126        let input = input.as_ref();
127        // 1. Skip because encoding parameters == []
128        // 2. If ||M|| > emLen-2hLen-1 then output "message too long" and stop.
129        if input.len() > k - 2 * Self::HASH_LEN - 1 {
130            panic!("message too long");
131        }
132        // 3. Generate an octet string PS consisting of emLen-||M||-2hLen-1 zero
133        //    octets. The length of PS may be 0.
134        let mut ps = vec![0; k - input.len() - 2 * Self::HASH_LEN - 2];
135        ps.push(0x01);
136        // 4. Let pHash = Hash(P), an octet string of length hLen.
137        let p_hash = Sha1::digest([]).to_vec();
138        // 5. Concatenate pHash, PS, the message M, and other padding to form a
139        //    data block DB as: DB = pHash || PS || 01 || M
140        let db = [&*p_hash, &*ps, input].concat();
141        // 6. Generate a random octet string seed of length hLen.
142        let mut seed = vec![0; Self::HASH_LEN];
143        self.rng.fill(&mut seed[..]).expect("rng out of entropy");
144        // 7. Let dbMask = MGF(seed, emLen-hLen).
145        let db_mask = Self::mgf1(&seed, k - Self::HASH_LEN);
146        // 8. Let maskedDB = DB \xor dbMask.
147        let masked_db: Vec<_> = db.into_iter().zip(db_mask).map(|(a, b)| a ^ b).collect();
148        // 9. Let seedMask = MGF(maskedDB, hLen).
149        let seed_mask = Self::mgf1(&masked_db, Self::HASH_LEN);
150        // 10. Let maskedSeed = seed \xor seedMask.
151        let masked_seed: Vec<_> = seed
152            .into_iter()
153            .zip(seed_mask)
154            .map(|(a, b)| a ^ b)
155            .collect();
156        // 11. Let EM = maskedSeed || maskedDB.
157        [&*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    /// Basic constructor.
169    pub fn new(modulus: BigUint, exponent: BigUint) -> PublicKey {
170        PublicKey { modulus, exponent }
171    }
172
173    /// Will parse public key from pem representation.
174    ///
175    /// # Panic
176    ///
177    /// Will panic in case of bad pem data.
178    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    /// Returns number of octets in the modulus.
185    pub fn num_octets(&self) -> usize {
186        (self.modulus.bits() as usize + 6) >> 3
187    }
188
189    /// Returns modulus of the public key.
190    pub fn modulus(&self) -> &BigUint {
191        &self.modulus
192    }
193
194    /// Returns exponent of the public key.
195    pub fn exponent(&self) -> &BigUint {
196        &self.exponent
197    }
198
199    /// Will encrypt block with public key.
200    ///
201    /// # Panic
202    ///
203    /// Will panic if block is too long for key or padding.
204    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        // is this needed?
210        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}