1use core::fmt;
4
5use rand_core::{CryptoRng, RngCore};
6
7#[cfg(feature = "default-rng")]
8use rand_core::OsRng;
9
10use crate::capsule::{Capsule, OpenReencryptedError};
11use crate::capsule_frag::VerifiedCapsuleFrag;
12use crate::dem::{DecryptionError, EncryptionError, DEM};
13use crate::key_frag::{KeyFragBase, VerifiedKeyFrag};
14use crate::keys::{PublicKey, SecretKey, Signer};
15
16use alloc::boxed::Box;
17use alloc::vec::Vec;
18
19#[derive(Debug, PartialEq, Eq)]
21pub enum ReencryptionError {
22 OnOpen(OpenReencryptedError),
24 OnDecryption(DecryptionError),
26}
27
28impl fmt::Display for ReencryptionError {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 Self::OnOpen(err) => write!(f, "Re-encryption error on open: {err}"),
32 Self::OnDecryption(err) => write!(f, "Re-encryption error on decryption: {err}"),
33 }
34 }
35}
36
37pub fn encrypt_with_rng(
41 rng: &mut (impl CryptoRng + RngCore),
42 delegating_pk: &PublicKey,
43 plaintext: &[u8],
44) -> Result<(Capsule, Box<[u8]>), EncryptionError> {
45 let (capsule, key_seed) = Capsule::from_public_key(rng, delegating_pk);
46 let dem = DEM::new(key_seed.as_secret());
47 dem.encrypt(rng, plaintext, &capsule.to_bytes_simple())
48 .map(|ciphertext| (capsule, ciphertext))
49}
50
51#[cfg(feature = "default-rng")]
53pub fn encrypt(
54 delegating_pk: &PublicKey,
55 plaintext: &[u8],
56) -> Result<(Capsule, Box<[u8]>), EncryptionError> {
57 encrypt_with_rng(&mut OsRng, delegating_pk, plaintext)
58}
59
60pub fn decrypt_original(
62 delegating_sk: &SecretKey,
63 capsule: &Capsule,
64 ciphertext: impl AsRef<[u8]>,
65) -> Result<Box<[u8]>, DecryptionError> {
66 let key_seed = capsule.open_original(delegating_sk);
67 let dem = DEM::new(key_seed.as_secret());
68 dem.decrypt(ciphertext, &capsule.to_bytes_simple())
69}
70
71#[allow(clippy::too_many_arguments)]
88pub fn generate_kfrags_with_rng(
89 rng: &mut (impl CryptoRng + RngCore),
90 delegating_sk: &SecretKey,
91 receiving_pk: &PublicKey,
92 signer: &Signer,
93 threshold: usize,
94 shares: usize,
95 sign_delegating_key: bool,
96 sign_receiving_key: bool,
97) -> Box<[VerifiedKeyFrag]> {
98 let base = KeyFragBase::new(rng, delegating_sk, receiving_pk, signer, threshold);
99
100 let mut result = Vec::<VerifiedKeyFrag>::new();
101 for _ in 0..shares {
102 result.push(VerifiedKeyFrag::from_base(
103 rng,
104 &base,
105 sign_delegating_key,
106 sign_receiving_key,
107 ));
108 }
109
110 result.into_boxed_slice()
111}
112
113#[cfg(feature = "default-rng")]
115#[allow(clippy::too_many_arguments)]
116pub fn generate_kfrags(
117 delegating_sk: &SecretKey,
118 receiving_pk: &PublicKey,
119 signer: &Signer,
120 threshold: usize,
121 shares: usize,
122 sign_delegating_key: bool,
123 sign_receiving_key: bool,
124) -> Box<[VerifiedKeyFrag]> {
125 generate_kfrags_with_rng(
126 &mut OsRng,
127 delegating_sk,
128 receiving_pk,
129 signer,
130 threshold,
131 shares,
132 sign_delegating_key,
133 sign_receiving_key,
134 )
135}
136
137pub fn reencrypt_with_rng(
146 rng: &mut (impl CryptoRng + RngCore),
147 capsule: &Capsule,
148 verified_kfrag: VerifiedKeyFrag,
149) -> VerifiedCapsuleFrag {
150 VerifiedCapsuleFrag::reencrypted(rng, capsule, verified_kfrag.unverify())
151}
152
153#[cfg(feature = "default-rng")]
155pub fn reencrypt(capsule: &Capsule, verified_kfrag: VerifiedKeyFrag) -> VerifiedCapsuleFrag {
156 reencrypt_with_rng(&mut OsRng, capsule, verified_kfrag)
157}
158
159pub fn decrypt_reencrypted(
170 receiving_sk: &SecretKey,
171 delegating_pk: &PublicKey,
172 capsule: &Capsule,
173 verified_cfrags: impl IntoIterator<Item = VerifiedCapsuleFrag>,
174 ciphertext: impl AsRef<[u8]>,
175) -> Result<Box<[u8]>, ReencryptionError> {
176 let cfrags: Vec<_> = verified_cfrags
177 .into_iter()
178 .map(|vcfrag| vcfrag.unverify())
179 .collect();
180 let key_seed = capsule
181 .open_reencrypted(receiving_sk, delegating_pk, &cfrags)
182 .map_err(ReencryptionError::OnOpen)?;
183 let dem = DEM::new(key_seed.as_secret());
184 dem.decrypt(&ciphertext, &capsule.to_bytes_simple())
185 .map_err(ReencryptionError::OnDecryption)
186}
187
188#[cfg(test)]
189mod tests {
190
191 use alloc::vec::Vec;
192
193 use crate::{SecretKey, Signer, VerifiedCapsuleFrag};
194
195 use super::{decrypt_original, decrypt_reencrypted, encrypt, generate_kfrags, reencrypt};
196
197 #[test]
198 fn test_simple_api() {
199 let threshold: usize = 2;
210 let num_frags: usize = threshold + 1;
211
212 let delegating_sk = SecretKey::random();
214 let delegating_pk = delegating_sk.public_key();
215
216 let signer = Signer::new(SecretKey::random());
217 let verifying_pk = signer.verifying_key();
218
219 let receiving_sk = SecretKey::random();
221 let receiving_pk = receiving_sk.public_key();
222
223 let plaintext = b"peace at dawn";
225 let (capsule, ciphertext) = encrypt(&delegating_pk, plaintext).unwrap();
226
227 let plaintext_alice = decrypt_original(&delegating_sk, &capsule, &ciphertext).unwrap();
229 assert_eq!(&plaintext_alice as &[u8], plaintext);
230
231 let verified_kfrags = generate_kfrags(
233 &delegating_sk,
234 &receiving_pk,
235 &signer,
236 threshold,
237 num_frags,
238 true,
239 true,
240 );
241
242 let kfrags = verified_kfrags
246 .iter()
247 .cloned()
248 .map(|vkfrag| vkfrag.unverify());
249
250 let verified_kfrags: Vec<_> = kfrags
252 .into_iter()
253 .map(|kfrag| {
254 kfrag
255 .verify(&verifying_pk, Some(&delegating_pk), Some(&receiving_pk))
256 .unwrap()
257 })
258 .collect();
259
260 let verified_cfrags: Vec<VerifiedCapsuleFrag> = verified_kfrags[0..threshold]
261 .iter()
262 .map(|vkfrag| reencrypt(&capsule, vkfrag.clone()))
263 .collect();
264
265 let cfrags = verified_cfrags
267 .iter()
268 .cloned()
269 .map(|vcfrag| vcfrag.unverify());
270
271 let verified_cfrags: Vec<_> = cfrags
273 .into_iter()
274 .map(|cfrag| {
275 cfrag
276 .verify(&capsule, &verifying_pk, &delegating_pk, &receiving_pk)
277 .unwrap()
278 })
279 .collect();
280
281 let plaintext_bob = decrypt_reencrypted(
283 &receiving_sk,
284 &delegating_pk,
285 &capsule,
286 verified_cfrags,
287 &ciphertext,
288 )
289 .unwrap();
290 assert_eq!(&plaintext_bob as &[u8], plaintext);
291 }
292}