nucypher_core/
threshold_message_kit.rs1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::vec::Vec;
4
5use ferveo::api::{Ciphertext, CiphertextHeader, SharedSecret};
6use ferveo::Error;
7use serde::{Deserialize, Serialize};
8
9use crate::access_control::AccessControlPolicy;
10use crate::versioning::{
11 messagepack_deserialize, messagepack_serialize, ProtocolObject, ProtocolObjectInner,
12};
13
14#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
16pub struct ThresholdMessageKit {
17 pub ciphertext: Ciphertext,
19
20 pub acp: AccessControlPolicy,
22}
23
24impl ThresholdMessageKit {
25 pub fn new(ciphertext: &Ciphertext, acp: &AccessControlPolicy) -> Self {
27 ThresholdMessageKit {
28 ciphertext: ciphertext.clone(),
29 acp: acp.clone(),
30 }
31 }
32
33 pub fn ciphertext_header(&self) -> Result<CiphertextHeader, Error> {
35 self.ciphertext.header()
36 }
37
38 pub fn decrypt_with_shared_secret(
40 &self,
41 shared_secret: &SharedSecret,
42 ) -> Result<Vec<u8>, Error> {
43 ferveo::api::decrypt_with_shared_secret(
44 &self.ciphertext,
45 self.acp.aad()?.as_ref(),
46 shared_secret,
47 )
48 }
49}
50
51impl<'a> ProtocolObjectInner<'a> for ThresholdMessageKit {
52 fn version() -> (u16, u16) {
53 (1, 0)
54 }
55
56 fn brand() -> [u8; 4] {
57 *b"TMKi"
58 }
59
60 fn unversioned_to_bytes(&self) -> Box<[u8]> {
61 messagepack_serialize(&self)
62 }
63
64 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
65 if minor_version == 0 {
66 Some(messagepack_deserialize(bytes))
67 } else {
68 None
69 }
70 }
71}
72
73impl<'a> ProtocolObject<'a> for ThresholdMessageKit {}
74
75#[cfg(test)]
76mod tests {
77 use ferveo::api::{encrypt as ferveo_encrypt, SecretBox};
78
79 use crate::access_control::{AccessControlPolicy, AuthenticatedData};
80 use crate::conditions::Conditions;
81 use crate::test_utils::util::random_dkg_pubkey;
82 use crate::threshold_message_kit::ThresholdMessageKit;
83 use crate::versioning::ProtocolObject;
84 #[test]
85 fn threshold_message_kit() {
86 let dkg_pk = random_dkg_pubkey();
87 let data = "The Tyranny of Merit".as_bytes().to_vec();
88
89 let authorization = b"we_dont_need_no_stinking_badges";
90 let acp = AccessControlPolicy::new(
91 &AuthenticatedData::new(&dkg_pk, &Conditions::new("abcd")),
92 authorization,
93 );
94
95 let ciphertext =
96 ferveo_encrypt(SecretBox::new(data), &acp.aad().unwrap(), &dkg_pk).unwrap();
97 let tmk = ThresholdMessageKit::new(&ciphertext, &acp);
98
99 let serialized_tmk = tmk.to_bytes();
101 let deserialized_tmk = ThresholdMessageKit::from_bytes(&serialized_tmk).unwrap();
102 assert_eq!(
103 ciphertext.header().unwrap(),
104 deserialized_tmk.ciphertext_header().unwrap()
105 );
106 assert_eq!(acp, deserialized_tmk.acp);
107 }
108}