oasis_core_runtime/common/crypto/mrae/
deoxysii.rs1use anyhow::Result;
3use hmac::{Hmac, Mac};
4use rand::rngs::OsRng;
5use sha2::Sha512_256;
6use x25519_dalek::{PublicKey, StaticSecret};
7
8pub use deoxysii::{DeoxysII, KEY_SIZE, NONCE_SIZE, TAG_SIZE};
9
10type Kdf = Hmac<Sha512_256>;
11
12pub trait Opener: Send + Sync {
14 fn box_open(
16 &self,
17 nonce: &[u8; NONCE_SIZE],
18 ciphertext: Vec<u8>,
19 additional_data: Vec<u8>,
20 peers_public_key: &PublicKey,
21 ) -> Result<Vec<u8>>;
22}
23
24fn derive_symmetric_key(public: &PublicKey, private: &StaticSecret) -> [u8; KEY_SIZE] {
27 let pmk = private.diffie_hellman(public);
28
29 let mut kdf = Kdf::new_from_slice(b"MRAE_Box_Deoxys-II-256-128").expect("Hmac::new_from_slice");
30 kdf.update(pmk.as_bytes());
31 drop(pmk);
32
33 let mut derived_key = [0u8; KEY_SIZE];
34 let digest = kdf.finalize();
35 derived_key.copy_from_slice(&digest.into_bytes()[..KEY_SIZE]);
36
37 derived_key
38}
39
40pub fn generate_key_pair() -> (PublicKey, StaticSecret) {
43 let sk = StaticSecret::random_from_rng(OsRng);
44 let pk = PublicKey::from(&sk);
45
46 (pk, sk)
47}
48
49pub fn box_seal(
55 nonce: &[u8; NONCE_SIZE],
56 plaintext: Vec<u8>,
57 additional_data: Vec<u8>,
58 peers_public_key: &PublicKey,
59 private_key: &StaticSecret,
60) -> Result<Vec<u8>> {
61 let key = derive_symmetric_key(peers_public_key, private_key);
62
63 let d2 = DeoxysII::new(&key);
64
65 Ok(d2.seal(nonce, plaintext, additional_data))
66}
67
68pub fn box_open(
74 nonce: &[u8; NONCE_SIZE],
75 ciphertext: Vec<u8>,
76 additional_data: Vec<u8>,
77 peers_public_key: &PublicKey,
78 private_key: &StaticSecret,
79) -> Result<Vec<u8>> {
80 let key = derive_symmetric_key(peers_public_key, private_key);
81
82 let d2 = DeoxysII::new(&key);
83
84 d2.open(nonce, ciphertext, additional_data)
85 .map_err(|err| err.into())
86}
87
88#[cfg(test)]
89mod tests {
90 extern crate test;
91
92 use self::test::{black_box, Bencher};
93 use super::*;
94 use rand::RngCore;
95
96 #[test]
97 fn test_mrae_asymmetric() {
98 let (a_pub, a_priv) = generate_key_pair(); let (b_pub, b_priv) = generate_key_pair(); assert_ne!(a_pub.to_bytes(), b_pub.to_bytes());
103 assert_ne!(a_priv.to_bytes(), b_priv.to_bytes());
104 assert_ne!(a_pub.to_bytes(), a_priv.to_bytes());
105 assert_ne!(b_pub.to_bytes(), b_priv.to_bytes());
106
107 let nonce = [1u8; NONCE_SIZE];
109 let text = String::from("This is a test!").as_bytes().to_vec();
110 let aad = vec![42u8; 10];
111
112 let sealed = box_seal(&nonce, text.clone(), aad.clone(), &b_pub, &a_priv);
113 assert!(sealed.is_ok());
114
115 let opened = box_open(&nonce, sealed.unwrap(), aad, &a_pub, &b_priv);
117 assert!(opened.is_ok());
118
119 let deciphered = opened.unwrap();
121 assert_eq!(deciphered, text);
122 }
123
124 #[bench]
125 fn bench_mrae_box_seal_4096(b: &mut Bencher) {
126 let mut rng = OsRng {};
127
128 let (_a_pub, a_priv) = generate_key_pair(); let (b_pub, _b_priv) = generate_key_pair(); let mut nonce = [0u8; NONCE_SIZE];
134 rng.fill_bytes(&mut nonce);
135 let mut text = [0u8; 4096];
136 rng.fill_bytes(&mut text);
137 let mut aad = [0u8; 64];
138 rng.fill_bytes(&mut aad);
139
140 b.iter(|| {
142 let _sealed = black_box(box_seal(
143 &nonce,
144 text.to_vec(),
145 aad.to_vec(),
146 &b_pub,
147 &a_priv,
148 ));
149 });
150 }
151
152 #[bench]
153 fn bench_mrae_box_open_4096(b: &mut Bencher) {
154 let mut rng = OsRng {};
155
156 let (a_pub, a_priv) = generate_key_pair(); let (b_pub, b_priv) = generate_key_pair(); let mut nonce = [0u8; NONCE_SIZE];
162 rng.fill_bytes(&mut nonce);
163 let mut text = [0u8; 4096];
164 rng.fill_bytes(&mut text);
165 let mut aad = [0u8; 64];
166 rng.fill_bytes(&mut aad);
167
168 let sealed = box_seal(&nonce, text.to_vec(), aad.to_vec(), &b_pub, &a_priv);
170 let ciphertext = sealed.unwrap();
171
172 b.iter(|| {
174 let _opened = black_box(box_open(
175 &nonce,
176 ciphertext.clone(),
177 aad.to_vec(),
178 &a_pub,
179 &b_priv,
180 ));
181 });
182 }
183}