nucypher_core/
message_kit.rs

1use alloc::boxed::Box;
2use alloc::string::String;
3
4use serde::{Deserialize, Serialize};
5use umbral_pre::{
6    decrypt_original, decrypt_reencrypted, encrypt, serde_bytes, Capsule, DecryptionError,
7    EncryptionError, PublicKey, ReencryptionError, SecretKey, VerifiedCapsuleFrag,
8};
9
10use crate::conditions::Conditions;
11use crate::versioning::{
12    messagepack_deserialize, messagepack_serialize, ProtocolObject, ProtocolObjectInner,
13};
14
15/// Encrypted message prepared for re-encryption.
16#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
17pub struct MessageKit {
18    /// Encapsulated symmetric key for this message.
19    pub capsule: Capsule,
20    #[serde(with = "serde_bytes::as_base64")]
21    ciphertext: Box<[u8]>,
22    /// Decryption conditions for this message.
23    pub conditions: Option<Conditions>,
24}
25
26impl MessageKit {
27    /// Creates a new encrypted message for the given policy key.
28    pub fn new(
29        policy_encrypting_key: &PublicKey,
30        plaintext: &[u8],
31        conditions: Option<&Conditions>,
32    ) -> Self {
33        let (capsule, ciphertext) = match encrypt(policy_encrypting_key, plaintext) {
34            Ok(result) => result,
35            Err(err) => match err {
36                // For now this is the only error that can happen during encryption,
37                // and there's really no point in propagating it.
38                EncryptionError::PlaintextTooLarge => panic!("encryption failed - out of memory?"),
39            },
40        };
41        Self {
42            capsule,
43            ciphertext,
44            conditions: conditions.cloned(),
45        }
46    }
47
48    /// Decrypts the message using the original (Alice's) key.
49    pub fn decrypt(&self, sk: &SecretKey) -> Result<Box<[u8]>, DecryptionError> {
50        decrypt_original(sk, &self.capsule, &self.ciphertext)
51    }
52
53    /// Decrypts the message using the Bob's key and re-encrypted capsule frags.
54    pub fn decrypt_reencrypted(
55        &self,
56        sk: &SecretKey,
57        policy_encrypting_key: &PublicKey,
58        vcfrags: impl IntoIterator<Item = VerifiedCapsuleFrag>,
59    ) -> Result<Box<[u8]>, ReencryptionError> {
60        decrypt_reencrypted(
61            sk,
62            policy_encrypting_key,
63            &self.capsule,
64            vcfrags,
65            self.ciphertext.clone(),
66        )
67    }
68}
69
70impl<'a> ProtocolObjectInner<'a> for MessageKit {
71    fn brand() -> [u8; 4] {
72        *b"MKit"
73    }
74
75    fn version() -> (u16, u16) {
76        (3, 0)
77    }
78
79    fn unversioned_to_bytes(&self) -> Box<[u8]> {
80        messagepack_serialize(&self)
81    }
82
83    fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
84        if minor_version == 0 {
85            Some(messagepack_deserialize(bytes))
86        } else {
87            None
88        }
89    }
90}
91
92impl<'a> ProtocolObject<'a> for MessageKit {}