1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::vec::Vec;
4
5use serde::{Deserialize, Serialize};
6use umbral_pre::{Capsule, CapsuleFrag, PublicKey, Signature, Signer, VerifiedCapsuleFrag};
7
8use crate::conditions::{Conditions, Context};
9use crate::hrac::HRAC;
10use crate::key_frag::EncryptedKeyFrag;
11use crate::versioning::{
12 messagepack_deserialize, messagepack_serialize, ProtocolObject, ProtocolObjectInner,
13};
14use crate::VerificationError;
15
16#[derive(PartialEq, Debug, Serialize, Deserialize)]
18pub struct ReencryptionRequest {
19 pub capsules: Box<[Capsule]>,
21 pub hrac: HRAC,
23 pub encrypted_kfrag: EncryptedKeyFrag,
25 pub publisher_verifying_key: PublicKey,
27 pub bob_verifying_key: PublicKey,
29 pub conditions: Option<Conditions>,
31 pub context: Option<Context>,
33}
34
35impl ReencryptionRequest {
36 pub fn new(
38 capsules: &[Capsule],
39 hrac: &HRAC,
40 encrypted_kfrag: &EncryptedKeyFrag,
41 publisher_verifying_key: &PublicKey,
42 bob_verifying_key: &PublicKey,
43 conditions: Option<&Conditions>,
44 context: Option<&Context>,
45 ) -> Self {
46 Self {
47 capsules: capsules.to_vec().into(),
48 hrac: *hrac,
49 encrypted_kfrag: encrypted_kfrag.clone(),
50 publisher_verifying_key: *publisher_verifying_key,
51 bob_verifying_key: *bob_verifying_key,
52 conditions: conditions.cloned(),
53 context: context.cloned(),
54 }
55 }
56}
57
58impl<'a> ProtocolObjectInner<'a> for ReencryptionRequest {
59 fn brand() -> [u8; 4] {
60 *b"ReRq"
61 }
62
63 fn version() -> (u16, u16) {
64 (3, 0)
65 }
66
67 fn unversioned_to_bytes(&self) -> Box<[u8]> {
68 messagepack_serialize(&self)
69 }
70
71 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
72 if minor_version == 0 {
73 Some(messagepack_deserialize(bytes))
74 } else {
75 None
76 }
77 }
78}
79
80impl<'a> ProtocolObject<'a> for ReencryptionRequest {}
81
82#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
84pub struct ReencryptionResponse {
85 cfrags: Box<[CapsuleFrag]>,
86 signature: Signature,
87}
88
89fn message_to_sign(capsules: &[Capsule], cfrags: &[CapsuleFrag]) -> Vec<u8> {
90 let capsule_bytes = capsules.iter().fold(Vec::<u8>::new(), |mut acc, capsule| {
91 acc.extend(messagepack_serialize(capsule).as_ref());
92 acc
93 });
94
95 let cfrag_bytes = cfrags.iter().fold(Vec::<u8>::new(), |mut acc, cfrag| {
96 acc.extend(messagepack_serialize(cfrag).as_ref());
97 acc
98 });
99
100 [capsule_bytes, cfrag_bytes].concat()
101}
102
103impl ReencryptionResponse {
104 pub fn new<'a>(
106 signer: &Signer,
107 capsules_and_vcfrags: impl IntoIterator<Item = (&'a Capsule, VerifiedCapsuleFrag)>,
108 ) -> Self {
109 let (capsules, vcfrags): (Vec<_>, Vec<_>) = capsules_and_vcfrags.into_iter().unzip();
110
111 let cfrags: Vec<_> = vcfrags
113 .into_iter()
114 .map(|vcfrag| vcfrag.unverify())
115 .collect();
116
117 let capsules: Vec<_> = capsules.into_iter().cloned().collect();
118
119 let signature = signer.sign(&message_to_sign(&capsules, &cfrags));
120
121 ReencryptionResponse {
122 cfrags: cfrags.into_boxed_slice(),
123 signature,
124 }
125 }
126
127 pub fn verify(
129 self,
130 capsules: &[Capsule],
131 alice_verifying_key: &PublicKey,
132 ursula_verifying_key: &PublicKey,
133 policy_encrypting_key: &PublicKey,
134 bob_encrypting_key: &PublicKey,
135 ) -> Result<Box<[VerifiedCapsuleFrag]>, VerificationError> {
136 if capsules.len() != self.cfrags.len() {
137 return Err(VerificationError);
139 }
140
141 if !self.signature.verify(
143 ursula_verifying_key,
144 &message_to_sign(capsules, &self.cfrags),
145 ) {
146 return Err(VerificationError);
147 }
148
149 let vcfrags = self
150 .cfrags
151 .into_vec()
152 .into_iter()
153 .zip(capsules.iter())
154 .map(|(cfrag, capsule)| {
155 cfrag.verify(
156 capsule,
157 alice_verifying_key,
158 policy_encrypting_key,
159 bob_encrypting_key,
160 )
161 })
162 .collect::<Result<Vec<_>, _>>();
163
164 vcfrags
167 .map(|vcfrags| vcfrags.into_boxed_slice())
168 .map_err(|_err| VerificationError)
169 }
170}
171
172impl<'a> ProtocolObjectInner<'a> for ReencryptionResponse {
173 fn brand() -> [u8; 4] {
174 *b"ReRs"
175 }
176
177 fn version() -> (u16, u16) {
178 (3, 0)
179 }
180
181 fn unversioned_to_bytes(&self) -> Box<[u8]> {
182 messagepack_serialize(&self)
183 }
184
185 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
186 if minor_version == 0 {
187 Some(messagepack_deserialize(bytes))
188 } else {
189 None
190 }
191 }
192}
193
194impl<'a> ProtocolObject<'a> for ReencryptionResponse {}
195
196#[cfg(test)]
197mod tests {
198 use umbral_pre::SecretKey;
199 use umbral_pre::{encrypt, generate_kfrags, Signer};
200
201 use crate::{Conditions, Context, EncryptedKeyFrag, HRAC};
202
203 use super::ReencryptionRequest;
204
205 #[test]
206 fn conditions_and_context_are_different() {
207 let some_secret = SecretKey::random();
208 let some_trinket = some_secret.public_key();
209
210 let _another_secret = SecretKey::random();
211 let another_trinket = some_secret.public_key();
212
213 let encryption_result = encrypt(&some_trinket, b"peace at dawn");
214
215 let (capsule, _ciphertext) = encryption_result.unwrap();
216
217 let hrac = HRAC::new(&some_trinket, &another_trinket, &[42]);
218
219 let signer = Signer::new(SecretKey::random());
220
221 let verified_kfrags =
222 generate_kfrags(&some_secret, &another_trinket, &signer, 5, 8, true, true);
223 let verified_kfrags_vector = verified_kfrags.into_vec();
224 let one_verified_krag_in_particular = verified_kfrags_vector[0].clone();
225 let encrypted_kfrag = EncryptedKeyFrag::new(
226 &signer,
227 &another_trinket,
228 &hrac,
229 one_verified_krag_in_particular,
230 );
231
232 let request = ReencryptionRequest::new(
233 &[capsule],
234 &hrac,
235 &encrypted_kfrag,
236 &some_trinket,
237 &another_trinket,
238 Some(&Conditions::new("abcd")),
239 Some(&Context::new("efgh")),
240 );
241 let conditions = request.conditions.unwrap();
242 assert_eq!(conditions.as_ref(), "abcd");
243
244 let context = request.context.unwrap();
245 assert_eq!(context.as_ref(), "efgh");
246 }
247}