pg_core/client/rust/
mod.rs

1//! This module utilizes the symmetric primitives provided by [`Rust
2//! Crypto`](https://github.com/RustCrypto). The streaming interface, enabled using the feature
3//! `stream` is a small wrapper around [`aead::stream`]. This feature enables an interface
4//! to encrypt data using asynchronous byte streams, specifically from an
5//! [AsyncRead][`futures::io::AsyncRead`] into an [AsyncWrite][`futures::io::AsyncWrite`].
6
7use alloc::string::ToString;
8use alloc::vec::Vec;
9
10use crate::artifacts::{PublicKey, UserSecretKey, VerifyingKey};
11use crate::client::*;
12use crate::error::Error;
13use crate::identity::EncryptionPolicy;
14
15use aead::{Aead, KeyInit};
16use aes_gcm::{Aes128Gcm, Nonce};
17use ibe::kem::cgw_kv::CGWKV;
18use ibs::gg::Signer;
19use rand::{CryptoRng, RngCore};
20
21#[cfg(feature = "stream")]
22pub mod stream;
23
24/// In-memory configuration for a [`Sealer`].
25#[derive(Debug)]
26pub struct SealerMemoryConfig {
27    key: [u8; KEY_SIZE],
28    nonce: [u8; IV_SIZE],
29}
30
31/// In-memory configuration for an [`Unsealer`].
32#[derive(Debug)]
33pub struct UnsealerMemoryConfig {
34    message_len: usize,
35}
36
37impl SealerConfig for SealerMemoryConfig {}
38impl super::sealed::SealerConfig for SealerMemoryConfig {}
39
40impl UnsealerConfig for UnsealerMemoryConfig {}
41impl super::sealed::UnsealerConfig for UnsealerMemoryConfig {}
42
43impl From<aead::Error> for Error {
44    fn from(_: aead::Error) -> Self {
45        Self::Symmetric
46    }
47}
48
49impl From<aes_gcm::aes::cipher::InvalidLength> for Error {
50    fn from(_: aes_gcm::aes::cipher::InvalidLength) -> Self {
51        Self::Symmetric
52    }
53}
54
55#[derive(Debug, Serialize, Deserialize)]
56struct MessageAndSignature {
57    message: Vec<u8>,
58    sig: SignatureExt,
59}
60
61impl<'r, R: RngCore + CryptoRng> Sealer<'r, R, SealerMemoryConfig> {
62    /// Create a new [`Sealer`].
63    pub fn new(
64        mpk: &PublicKey<CGWKV>,
65        policies: &EncryptionPolicy,
66        pub_sign_key: &SigningKeyExt,
67        rng: &'r mut R,
68    ) -> Result<Self, Error> {
69        let (header, ss) = Header::new(mpk, policies, rng)?;
70        let Algorithm::Aes128Gcm(iv) = header.algo;
71
72        let mut key = [0u8; KEY_SIZE];
73        let mut nonce = [0u8; IV_SIZE];
74        key.copy_from_slice(&ss.0[..KEY_SIZE]);
75        nonce.copy_from_slice(&iv.0[..IV_SIZE]);
76
77        Ok(Self {
78            rng,
79            header,
80            pub_sign_key: pub_sign_key.clone(),
81            priv_sign_key: None,
82            config: SealerMemoryConfig { key, nonce },
83        })
84    }
85
86    /// Seals the entire payload.
87    pub fn seal(mut self, message: impl AsRef<[u8]>) -> Result<Vec<u8>, Error> {
88        let mut out = Vec::with_capacity(message.as_ref().len() + 1024);
89
90        out.extend_from_slice(&PRELUDE);
91        out.extend_from_slice(&VERSION_V3.to_be_bytes());
92
93        self.header = self.header.with_mode(Mode::InMemory {
94            size: message.as_ref().len().try_into()?,
95        });
96
97        let header_buf = bincode::serialize(&self.header)?;
98        out.extend_from_slice(&u32::try_from(header_buf.len())?.to_be_bytes());
99        out.extend_from_slice(&header_buf);
100
101        let signer = Signer::new().chain(header_buf);
102        let h_sig = signer.clone().sign(&self.pub_sign_key.key.0, self.rng);
103
104        let h_sig_ext = SignatureExt {
105            sig: h_sig,
106            pol: self.pub_sign_key.policy.clone(),
107        };
108
109        let h_sig_ext_bytes = bincode::serialize(&h_sig_ext)?;
110        out.extend_from_slice(&u32::try_from(h_sig_ext_bytes.len())?.to_be_bytes());
111        out.extend_from_slice(&h_sig_ext_bytes);
112
113        let m_sig_key = self.priv_sign_key.unwrap_or(self.pub_sign_key);
114        let m_sig = signer.chain(&message).sign(&m_sig_key.key.0, self.rng);
115
116        let aead = Aes128Gcm::new_from_slice(&self.config.key)?;
117        let nonce = Nonce::from_slice(&self.config.nonce);
118
119        let enc_input = bincode::serialize(&MessageAndSignature {
120            message: message.as_ref().to_vec(),
121            sig: SignatureExt {
122                sig: m_sig,
123                pol: m_sig_key.policy,
124            },
125        })?;
126
127        let ciphertext = aead.encrypt(nonce, enc_input.as_ref())?;
128
129        out.extend_from_slice(&ciphertext);
130
131        Ok(out)
132    }
133}
134
135impl Unsealer<Vec<u8>, UnsealerMemoryConfig> {
136    /// Create a new [`Unsealer`].
137    pub fn new(input: impl AsRef<[u8]>, vk: &VerifyingKey) -> Result<Self, Error> {
138        let b = input.as_ref();
139        let (preamble_bytes, b) = b.split_at(PREAMBLE_SIZE);
140        let (version, header_len) = preamble_checked(preamble_bytes)?;
141
142        let (header_bytes, b) = b.split_at(header_len);
143        let (h_sig_len_bytes, b) = b.split_at(SIG_SIZE_SIZE);
144        let h_sig_len = u32::from_be_bytes(h_sig_len_bytes.try_into()?);
145        let (h_sig_bytes, ct) = b.split_at(h_sig_len as usize);
146
147        let h_sig_ext: SignatureExt = bincode::deserialize(h_sig_bytes)?;
148        let id = h_sig_ext.pol.derive_ibs()?;
149
150        let verifier = Verifier::default().chain(header_bytes);
151
152        if !verifier.clone().verify(&vk.0, &h_sig_ext.sig, &id) {
153            return Err(Error::IncorrectSignature);
154        }
155
156        let header: Header = bincode::deserialize(header_bytes)?;
157        let message_len = match header.mode {
158            Mode::InMemory { size } => size as usize,
159            _ => return Err(Error::ModeNotSupported(header.mode)),
160        };
161
162        Ok(Self {
163            version,
164            header,
165            pub_id: h_sig_ext.pol,
166            r: ct.to_vec(),
167            verifier,
168            vk: vk.clone(),
169            config: UnsealerMemoryConfig { message_len },
170        })
171    }
172
173    /// Unseals the payload.
174    pub fn unseal(
175        self,
176        ident: &str,
177        usk: &UserSecretKey<CGWKV>,
178    ) -> Result<(Vec<u8>, VerificationResult), Error> {
179        let rec_info = self
180            .header
181            .recipients
182            .get(ident)
183            .ok_or_else(|| Error::UnknownIdentifier(ident.to_string()))?;
184
185        let ss = rec_info.decaps(usk)?;
186        let key = &ss.0[..KEY_SIZE];
187
188        let Algorithm::Aes128Gcm(iv) = self.header.algo;
189
190        let aead = Aes128Gcm::new_from_slice(key)?;
191        let nonce = Nonce::from_slice(&iv.0);
192
193        let plain = aead.decrypt(nonce, &*self.r)?;
194
195        let msg: MessageAndSignature = bincode::deserialize(&plain)?;
196        let id = msg.sig.pol.derive_ibs()?;
197
198        if !self
199            .verifier
200            .chain(&msg.message)
201            .verify(&self.vk.0, &msg.sig.sig, &id)
202        {
203            return Err(Error::IncorrectSignature);
204        }
205
206        debug_assert_eq!(self.config.message_len, msg.message.len());
207
208        let private = if self.pub_id == msg.sig.pol {
209            None
210        } else {
211            Some(msg.sig.pol)
212        };
213
214        Ok((
215            msg.message,
216            VerificationResult {
217                public: self.pub_id,
218                private,
219            },
220        ))
221    }
222}
223
224#[cfg(test)]
225mod tests {
226    use super::*;
227    use crate::test::TestSetup;
228
229    #[test]
230    fn test_seal_memory() {
231        let mut rng = rand::thread_rng();
232        let setup = TestSetup::new(&mut rng);
233
234        // Alice email
235        let pub_sign_key = &setup.signing_keys[0];
236        // Alice bsn
237        let priv_sign_key = &setup.signing_keys[1];
238
239        let input = b"SECRET DATA";
240        let sealed = Sealer::<_, SealerMemoryConfig>::new(
241            &setup.ibe_pk,
242            &setup.policy,
243            &pub_sign_key,
244            &mut rng,
245        )
246        .unwrap()
247        .with_priv_signing_key(priv_sign_key.clone())
248        .seal(input)
249        .unwrap();
250
251        // Take Bob's USK for email + name
252        let usk = &setup.usks[2];
253        let (original, verified_policy) =
254            Unsealer::<_, UnsealerMemoryConfig>::new(sealed, &setup.ibs_pk)
255                .unwrap()
256                .unseal("Bob", &usk)
257                .unwrap();
258
259        assert_eq!(&input.to_vec(), &original);
260
261        let expected = VerificationResult {
262            public: setup.policies[0].clone(),
263            private: Some(setup.policies[1].clone()),
264        };
265
266        assert_eq!(&verified_policy, &expected);
267    }
268
269    #[test]
270    fn test_seal_unseal_wrong_usk() {
271        let mut rng = rand::thread_rng();
272        let setup = TestSetup::new(&mut rng);
273
274        let pub_sign_key = &setup.signing_keys[0];
275        let priv_sign_key = &setup.signing_keys[1];
276
277        let input = b"SECRET DATA";
278        let sealed = Sealer::<_, SealerMemoryConfig>::new(
279            &setup.ibe_pk,
280            &setup.policy,
281            &pub_sign_key,
282            &mut rng,
283        )
284        .unwrap()
285        .with_priv_signing_key(priv_sign_key.clone())
286        .seal(input)
287        .unwrap();
288
289        // Take Charlie's USK for only name.
290        let usk = &setup.usks[4];
291        let res = Unsealer::<_, UnsealerMemoryConfig>::new(sealed, &setup.ibs_pk)
292            .unwrap()
293            .unseal("Charlie", &usk);
294
295        assert!(matches!(res, Err(Error::KEM)));
296    }
297
298    #[test]
299    fn test_seal_unseal_wrong_id() {
300        let mut rng = rand::thread_rng();
301        let setup = TestSetup::new(&mut rng);
302
303        let pub_sign_key = &setup.signing_keys[0];
304        let priv_sign_key = &setup.signing_keys[1];
305
306        let input = b"SECRET DATA";
307        let sealed = Sealer::<_, SealerMemoryConfig>::new(
308            &setup.ibe_pk,
309            &setup.policy,
310            &pub_sign_key,
311            &mut rng,
312        )
313        .unwrap()
314        .with_priv_signing_key(priv_sign_key.clone())
315        .seal(input)
316        .unwrap();
317
318        let usk = &setup.usks[4];
319        let res = Unsealer::<_, UnsealerMemoryConfig>::new(sealed, &setup.ibs_pk)
320            .unwrap()
321            .unseal("Daniel", &usk);
322
323        assert!(matches!(res, Err(Error::UnknownIdentifier(_))));
324    }
325}