1use aes::cipher::generic_array::GenericArray;
2use aes::cipher::{BlockDecrypt, BlockEncrypt, KeyInit, KeyIvInit};
3use aes::Aes256;
4use bytes::BytesMut;
5use cbc::cipher::block_padding::Pkcs7;
6use cbc::cipher::{BlockDecryptMut, BlockEncryptMut};
7use hmac::{Hmac, Mac};
8use once_cell::sync::Lazy;
9use rand::{random, Rng};
10use rsa::{BigUint, Oaep, Pkcs1v15Encrypt, Pss, RsaPublicKey};
11use sha1::Sha1;
12use std::convert::TryInto;
13use thiserror::Error;
14
15#[derive(Debug, Error)]
16pub enum CryptError {
17 #[error("Malformed signature: {0}")]
18 MalformedSignature(#[from] RsaError),
19 #[error("Malformed message")]
20 MalformedMessage,
21 #[error("Invalid HMAC")]
22 InvalidHmac,
23}
24
25pub type Result<T> = std::result::Result<T, CryptError>;
26
27#[derive(Debug, Error)]
28#[error("{0}")]
29pub struct RsaError(rsa::errors::Error);
30
31mod system_key {
32 include!(concat!(env!("OUT_DIR"), "/system_key.rs"));
33}
34
35static SYSTEM_PUBLIC_KEY: Lazy<RsaPublicKey> = Lazy::new(|| {
36 RsaPublicKey::new(
37 BigUint::from_bytes_le(system_key::N),
38 BigUint::from_bytes_le(system_key::E),
39 )
40 .expect("Failed to parse public key")
41});
42
43pub fn verify_signature(data: &[u8], signature: &[u8]) -> Result<bool> {
45 match SYSTEM_PUBLIC_KEY.verify(Pss::new::<Sha1>(), data, signature) {
46 Ok(_) => Ok(true),
47 Err(rsa::errors::Error::Verification) => Ok(false),
48 Err(err) => Err(CryptError::MalformedSignature(RsaError(err))),
49 }
50}
51
52pub struct SessionKeys {
53 pub plain: [u8; 32],
54 pub encrypted: Vec<u8>,
55}
56
57pub fn generate_session_key(nonce: Option<&[u8; 16]>) -> SessionKeys {
58 let mut rng = rand::thread_rng();
59 let plain: [u8; 32] = rng.gen();
60
61 let encrypted = match nonce {
62 Some(nonce) => {
63 let mut data = [0; 48];
64 data[0..32].copy_from_slice(&plain);
65 data[32..48].copy_from_slice(nonce);
66 encrypt_with_key(&SYSTEM_PUBLIC_KEY, &data)
67 }
68 None => encrypt_with_key(&SYSTEM_PUBLIC_KEY, &plain),
69 }
70 .expect("Invalid crypt setup");
71
72 SessionKeys { plain, encrypted }
73}
74
75pub fn encrypt_with_key(key: &RsaPublicKey, data: &[u8]) -> Result<Vec<u8>> {
76 let mut rng = rand::thread_rng();
77 Ok(key
78 .encrypt(&mut rng, Oaep::new::<Sha1>(), data)
79 .map_err(RsaError)?)
80}
81
82pub fn encrypt_with_key_pkcs1(key: &RsaPublicKey, data: &[u8]) -> Result<Vec<u8>> {
83 let mut rng = rand::thread_rng();
84 Ok(key
85 .encrypt(&mut rng, Pkcs1v15Encrypt, data)
86 .map_err(RsaError)?)
87}
88
89#[test]
90fn test_gen_session_key() {
91 assert!(!generate_session_key(None).encrypted.is_empty());
92 assert!(!generate_session_key(Some(&[
93 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
94 ]))
95 .encrypted
96 .is_empty(),);
97}
98
99fn encrypt_iv(iv: [u8; 16], key: &[u8; 32]) -> [u8; 16] {
101 let iv_crypter = Aes256::new(GenericArray::from_slice(key));
102 let mut iv_block = GenericArray::from(iv);
103 iv_crypter.encrypt_block(&mut iv_block);
104 iv_block.into()
105}
106
107fn decrypt_iv(iv: [u8; 16], key: &[u8; 32]) -> [u8; 16] {
109 let iv_crypter = Aes256::new(GenericArray::from_slice(key));
110 let mut iv_block = GenericArray::from(iv);
111 iv_crypter.decrypt_block(&mut iv_block);
112 iv_block.into()
113}
114
115#[test]
116fn test_iv_encryption_round_trip() {
117 let iv = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
118 let key = [
119 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
120 12, 13, 14, 15, 16,
121 ];
122 let encrypted = encrypt_iv(iv, &key);
123 assert_eq!(iv, decrypt_iv(encrypted, &key));
124}
125
126type Aes256CbcEnc = cbc::Encryptor<Aes256>;
127type Aes256CbcDec = cbc::Decryptor<Aes256>;
128
129fn encrypt_message(mut message: BytesMut, key: &[u8; 32], plain_iv: &[u8; 16]) -> BytesMut {
130 let cipher = <Aes256CbcEnc as KeyIvInit>::new(
131 GenericArray::from_slice(key),
132 GenericArray::from_slice(plain_iv),
133 );
134 let length = message.len();
135 message.resize(length + 16, 0);
136 let len = cipher
137 .encrypt_padded_mut::<Pkcs7>(&mut message, length)
138 .expect("not enough padding")
139 .len();
140
141 message.truncate(len);
142 message
143}
144
145fn decrypt_message(mut message: BytesMut, key: &[u8; 32], plain_iv: &[u8; 16]) -> Result<BytesMut> {
146 let cipher = Aes256CbcDec::new(
147 GenericArray::from_slice(key),
148 GenericArray::from_slice(plain_iv),
149 );
150 let len = cipher
151 .decrypt_padded_mut::<Pkcs7>(message.as_mut())
152 .map_err(|_| CryptError::MalformedMessage)?
153 .len();
154 message.truncate(len);
155 Ok(message)
156}
157
158#[test]
159fn test_encryption_round_trip() {
160 let iv = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
161 let key = [
162 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
163 12, 13, 14, 15, 16,
164 ];
165 let msg = "some test message to encrypt";
166 let plain = BytesMut::from(msg);
167 let encrypted = encrypt_message(plain.clone(), &key, &iv);
168 assert_eq!(plain, decrypt_message(encrypted, &key, &iv).unwrap());
169}
170
171fn symmetric_encrypt_with_iv(
172 mut iv_buff: BytesMut,
173 message: BytesMut,
174 key: &[u8; 32],
175 plain_iv: [u8; 16],
176) -> BytesMut {
177 let encrypted_iv = encrypt_iv(plain_iv, key);
178 iv_buff[0..16].copy_from_slice(&encrypted_iv);
179 let encrypted_message = encrypt_message(message, key, &plain_iv);
180
181 iv_buff.unsplit(encrypted_message);
182 iv_buff
183}
184
185type HmacSha1 = Hmac<Sha1>;
186
187pub fn symmetric_encrypt_with_iv_buffer(
191 iv_buff: BytesMut,
192 input: BytesMut,
193 key: &[u8; 32],
194) -> BytesMut {
195 let hmac_random: [u8; 3] = random();
196
197 let mut hmac_key = [0; 64];
198 hmac_key[0..16].copy_from_slice(&key[0..16]);
199
200 let mut hmac = <HmacSha1 as Mac>::new(GenericArray::from_slice(&hmac_key));
201 hmac.update(&hmac_random);
202 hmac.update(&input);
203
204 let hmac: [u8; 20] = hmac.finalize().into_bytes().into();
205
206 let mut iv = [0; 16];
207 iv[0..13].copy_from_slice(&hmac[0..13]);
208 iv[13..].copy_from_slice(&hmac_random);
209
210 symmetric_encrypt_with_iv(iv_buff, input, key, iv)
211}
212
213pub fn symmetric_encrypt(input: BytesMut, key: &[u8; 32]) -> BytesMut {
215 symmetric_encrypt_with_iv_buffer(BytesMut::from(&[0; 16][..]), input, key)
216}
217
218fn symmetric_decrypt_impl(mut input: BytesMut, key: &[u8; 32]) -> Result<([u8; 16], BytesMut)> {
219 let message = input.split_off(16);
220 let encrypted_iv = input.as_ref().try_into().unwrap();
221 let plain_iv = decrypt_iv(encrypted_iv, key);
222
223 let message = decrypt_message(message, key, &plain_iv)?;
224
225 Ok((plain_iv, message))
226}
227
228pub fn symmetric_decrypt_without_hmac(input: BytesMut, key: &[u8; 32]) -> Result<BytesMut> {
231 let (_, message) = symmetric_decrypt_impl(input, key)?;
232 Ok(message)
233}
234
235pub fn symmetric_decrypt(input: BytesMut, key: &[u8; 32]) -> Result<BytesMut> {
238 let (plain_iv, message) = symmetric_decrypt_impl(input, key)?;
239 let hmac_random = &plain_iv[13..];
243
244 let mut hmac_key = [0; 64];
245 hmac_key[0..16].copy_from_slice(&key[0..16]);
246
247 let mut hmac = <HmacSha1 as Mac>::new(GenericArray::from_slice(&hmac_key));
248 hmac.update(hmac_random);
249 hmac.update(&message);
250
251 let hmac: [u8; 20] = hmac.finalize().into_bytes().into();
252
253 if hmac[0..13] != plain_iv[0..13] {
254 return Err(CryptError::InvalidHmac);
255 }
256 Ok(message)
257}
258
259#[test]
260fn roundtrip_test() {
261 let key = random();
262
263 let input = BytesMut::from(&[55; 16][..]);
264
265 let encrypted = symmetric_encrypt(input.clone(), &key);
266
267 let decrypted = symmetric_decrypt(encrypted, &key).unwrap();
268
269 assert_eq!(input, decrypted);
270}