1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use rand::Rng;
use std::io::Cursor;
use crate::traits::{HashAlgorithm, PublicKeyAlgorithm, SignatureAlgorithm, SymmetricAlgorithm};
pub fn encrypt<
P: PublicKeyAlgorithm,
S: SymmetricAlgorithm,
H: HashAlgorithm,
I: SignatureAlgorithm,
>(
mut plaintext: Vec<u8>,
receiver_pk: &P::PublicKey,
self_sk: &I::SignKey,
) -> Result<Vec<u8>, ()> {
let mut tmp_data = vec![];
let mut hash_data = H::hash(&plaintext[..]);
let mut signature = I::sign(&hash_data, self_sk);
tmp_data.append(&mut hash_data);
tmp_data.append(&mut signature);
tmp_data.append(&mut plaintext);
let session_bytes: Vec<u8> = (0..S::KEY_LENGTH)
.map(|_| rand::thread_rng().gen::<u8>())
.collect();
let session_key = S::from_bytes(&session_bytes[..]).unwrap_or(Default::default());
let mut ciphertext = S::encrypt(&tmp_data[..], &session_key);
let mut cek = P::encrypt(&session_bytes[..], receiver_pk);
let mut wtr = vec![];
wtr.write_u32::<BigEndian>(cek.len() as u32).unwrap_or(());
let mut last_data = vec![];
last_data.append(&mut wtr);
last_data.append(&mut cek);
last_data.append(&mut ciphertext);
Ok(last_data)
}
pub fn decrypt<
P: PublicKeyAlgorithm,
S: SymmetricAlgorithm,
H: HashAlgorithm,
I: SignatureAlgorithm,
>(
mut data: Vec<u8>,
sender_vk: &I::VerifyKey,
self_sk: &P::SecretKey,
) -> Result<Vec<u8>, ()> {
let (length, cipher) = data.split_at_mut(4);
let mut rdr = Cursor::new(length);
let length = rdr.read_u32::<BigEndian>().unwrap_or(0);
let (cek, ciphertext) = cipher.split_at_mut(length as usize);
let session_bytes = P::decrypt(cek, self_sk);
let session_key = S::from_bytes(&session_bytes[..]).unwrap_or(Default::default());
let mut plaintext = S::decrypt(ciphertext, &session_key);
let (hash, signature_plaintext) = plaintext.split_at_mut(H::HASH_LENGTH);
let (signature, plaintext) = signature_plaintext.split_at_mut(I::SIGNATURE_LENGTH);
if !I::verify(&hash, &signature, sender_vk) || hash != &H::hash(plaintext)[..] {
return Err(());
}
Ok(plaintext.to_vec())
}