1use crate::auth::SystemAuths;
2use crate::sessions::EncryptionContexts;
3use crate::transcryptor_client::{TranscryptorClient, TranscryptorError};
4use libpep::client::{Client, Distributed};
5use libpep::data::traits::{
6 BatchEncryptable, Encryptable, Encrypted, HasStructure, Pseudonymizable, Rekeyable,
7 Transcryptable,
8};
9use libpep::factors::PseudonymizationDomain;
10use libpep::keys::distribution::SessionKeyShares;
11use libpep::keys::{KeyProvider, SessionKeys};
12use libpep::transcryptor::BatchError;
13use paas_api::config::PAASConfig;
14use paas_api::paths::ApiPath;
15use paas_api::status::SystemId;
16use rand_core::{CryptoRng, Rng};
17use serde::Serialize;
18use serde::de::DeserializeOwned;
19use std::collections::HashMap;
20
21#[derive(Debug, thiserror::Error)]
22pub enum PseudonymServiceError {
23 #[error(transparent)]
24 TranscryptorError(#[from] TranscryptorError),
25 #[error(transparent)]
26 BatchError(#[from] BatchError),
27 #[error("No auth found for system {0}")]
28 MissingAuth(SystemId),
29 #[error("No session found for system {0}")]
30 MissingSession(SystemId),
31 #[error("No session key share found for system {0}")]
32 MissingSessionKeyShares(SystemId),
33 #[error("PEP crypto client not initialized")]
34 UninitializedClient,
35 #[error("Transcryptor does not have session")]
36 UninitializedTranscryptor,
37 #[error("Inconsistent config received from {system}")]
38 InconsistentConfig { system: SystemId },
39}
40
41#[derive(Clone)]
42pub struct PseudonymService {
43 pub(crate) config: PAASConfig,
44 pub(crate) transcryptors: Vec<TranscryptorClient>,
45 pep_crypto_client: Option<Client>,
46}
47
48pub type SessionKeySharess = HashMap<SystemId, SessionKeyShares>;
49
50impl PseudonymService {
53 pub async fn new(
55 config: PAASConfig,
56 auths: SystemAuths,
57 ) -> Result<Self, PseudonymServiceError> {
58 let transcryptors =
59 futures::future::try_join_all(config.transcryptors.iter().map(|c| async {
60 let auth = auths
61 .get(&c.system_id)
62 .ok_or_else(|| PseudonymServiceError::MissingAuth(c.system_id.clone()))?;
63
64 let mut client = TranscryptorClient::new(c.clone(), auth)
65 .await
66 .map_err(PseudonymServiceError::TranscryptorError)?;
67
68 let reported_config = client
69 .check_config()
70 .await
71 .map_err(PseudonymServiceError::TranscryptorError)?;
72
73 if reported_config != config {
74 return Err(PseudonymServiceError::InconsistentConfig {
75 system: c.system_id.clone(),
76 });
77 }
78
79 Ok(client)
80 }))
81 .await?;
82
83 Ok(Self {
84 config,
85 transcryptors,
86 pep_crypto_client: None,
87 })
88 }
89
90 #[doc(hidden)]
93 pub async fn new_allow_http(
94 config: PAASConfig,
95 auths: SystemAuths,
96 ) -> Result<Self, PseudonymServiceError> {
97 let transcryptors =
98 futures::future::try_join_all(config.transcryptors.iter().map(|c| async {
99 let auth = auths
100 .get(&c.system_id)
101 .ok_or_else(|| PseudonymServiceError::MissingAuth(c.system_id.clone()))?;
102
103 let mut client = TranscryptorClient::new_allow_http(c.clone(), auth)
104 .await
105 .map_err(PseudonymServiceError::TranscryptorError)?;
106
107 let reported_config = client
108 .check_config()
109 .await
110 .map_err(PseudonymServiceError::TranscryptorError)?;
111
112 if reported_config != config {
113 return Err(PseudonymServiceError::InconsistentConfig {
114 system: c.system_id.clone(),
115 });
116 }
117
118 Ok(client)
119 }))
120 .await?;
121
122 Ok(Self {
123 config,
124 transcryptors,
125 pep_crypto_client: None,
126 })
127 }
128
129 pub async fn restore(
131 config: PAASConfig,
132 auths: SystemAuths,
133 session_ids: EncryptionContexts,
134 session_key_shares: SessionKeySharess,
135 session_keys: SessionKeys,
136 ) -> Result<Self, PseudonymServiceError> {
137 let transcryptors =
138 futures::future::try_join_all(config.transcryptors.iter().map(|c| async {
139 let auth = auths
140 .get(&c.system_id)
141 .ok_or_else(|| PseudonymServiceError::MissingAuth(c.system_id.clone()))?;
142
143 let session_id = session_ids
144 .get(&c.system_id)
145 .ok_or_else(|| PseudonymServiceError::MissingSession(c.system_id.clone()))?;
146
147 let sks = session_key_shares.get(&c.system_id).ok_or_else(|| {
148 PseudonymServiceError::MissingSessionKeyShares(c.system_id.clone())
149 })?;
150
151 let mut client =
152 TranscryptorClient::restore(c.clone(), auth, session_id.clone(), *sks)
153 .await
154 .map_err(PseudonymServiceError::TranscryptorError)?;
155
156 let reported_config = client
157 .check_config()
158 .await
159 .map_err(PseudonymServiceError::TranscryptorError)?;
160
161 if reported_config != config {
162 return Err(PseudonymServiceError::InconsistentConfig {
163 system: c.system_id.clone(),
164 });
165 }
166
167 Ok(client)
168 }))
169 .await?;
170
171 Ok(Self {
172 config,
173 transcryptors,
174 pep_crypto_client: Some(Client::restore(session_keys)),
175 })
176 }
177
178 pub fn dump(
180 &self,
181 ) -> Result<(EncryptionContexts, SessionKeys, SessionKeySharess), PseudonymServiceError> {
182 let session_ids = self.get_current_sessions();
183 let session_keys = *self
184 .pep_crypto_client
185 .as_ref()
186 .ok_or(PseudonymServiceError::UninitializedClient)?
187 .dump();
188
189 let mut session_key_shares = HashMap::new();
190 for transcryptor in &self.transcryptors {
191 if let Some(key_share) = transcryptor.sks.as_ref() {
192 session_key_shares.insert(transcryptor.config.system_id.clone(), *key_share);
193 }
194 }
195
196 Ok((session_ids?, session_keys, session_key_shares))
197 }
198
199 pub fn is_initialized(&self) -> bool {
201 self.pep_crypto_client.is_some()
202 }
203
204 pub async fn init(&mut self) -> Result<(), PseudonymServiceError> {
206 let mut sks = vec![];
207 for transcryptor in &mut self.transcryptors {
208 let (_session_id, key_share) = transcryptor
209 .start_session()
210 .await
211 .map_err(PseudonymServiceError::TranscryptorError)?;
212 sks.push(key_share);
213 }
214
215 self.pep_crypto_client = Some(Client::from_shares(self.config.blinded_global_keys, &sks));
216
217 Ok(())
218 }
219
220 pub async fn end(&mut self) -> Result<(), PseudonymServiceError> {
222 futures::future::try_join_all(self.transcryptors.iter_mut().map(|client| async {
223 client
224 .end_session()
225 .await
226 .map_err(PseudonymServiceError::TranscryptorError)
227 }))
228 .await?;
229
230 Ok(())
231 }
232
233 pub async fn refresh_session(
235 &mut self,
236 transcryptor_index: usize,
237 ) -> Result<(), PseudonymServiceError> {
238 let old_sks = self.transcryptors[transcryptor_index].sks;
239
240 let (_, new_sks) = {
241 let transcryptor = &mut self.transcryptors[transcryptor_index];
242 transcryptor
243 .start_session()
244 .await
245 .map_err(PseudonymServiceError::TranscryptorError)?
246 };
247
248 if let (Some(old_sks), Some(crypto_client)) = (old_sks, self.pep_crypto_client.as_mut()) {
249 crypto_client.update_session_secret_keys(old_sks, new_sks);
250 } else {
251 self.init().await?;
252 }
253
254 Ok(())
255 }
256
257 pub async fn pseudonymize<T>(
261 &mut self,
262 encrypted_pseudonym: &T,
263 sessions_from: &EncryptionContexts,
264 domain_from: &PseudonymizationDomain,
265 domain_to: &PseudonymizationDomain,
266 ) -> Result<T, PseudonymServiceError>
267 where
268 T: Pseudonymizable + DeserializeOwned + Serialize + Clone + ApiPath,
269 {
270 if self.pep_crypto_client.is_none() {
271 self.init().await?;
272 }
273
274 let mut transcrypted = encrypted_pseudonym.clone();
275
276 for i in 0..self.transcryptors.len() {
277 let system_id = &self.transcryptors[i].config.system_id;
278 let session_from = sessions_from
279 .get(system_id)
280 .ok_or_else(|| PseudonymServiceError::MissingSession(system_id.clone()))?;
281
282 let session_id = match &self.transcryptors[i].session_id {
283 Some(id) => id.clone(),
284 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
285 };
286
287 let result = self.transcryptors[i]
288 .pseudonymize(
289 &transcrypted,
290 domain_from,
291 domain_to,
292 session_from,
293 &session_id,
294 )
295 .await;
296
297 transcrypted = match result {
298 Err(TranscryptorError::InvalidSession(_)) => {
299 self.refresh_session(i).await?;
300
301 let new_session_id = match &self.transcryptors[i].session_id {
302 Some(id) => id.clone(),
303 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
304 };
305 self.transcryptors[i]
306 .pseudonymize(
307 &transcrypted,
308 domain_from,
309 domain_to,
310 session_from,
311 &new_session_id,
312 )
313 .await?
314 }
315 Err(err) => return Err(PseudonymServiceError::TranscryptorError(err)),
316 Ok(value) => value,
317 };
318 }
319
320 Ok(transcrypted)
321 }
322
323 pub async fn pseudonymize_batch<T>(
327 &mut self,
328 encrypted_pseudonyms: Vec<T>,
329 sessions_from: &EncryptionContexts,
330 domain_from: &PseudonymizationDomain,
331 domain_to: &PseudonymizationDomain,
332 ) -> Result<Vec<T>, PseudonymServiceError>
333 where
334 T: Pseudonymizable + DeserializeOwned + Serialize + Clone + ApiPath + HasStructure,
335 {
336 if self.pep_crypto_client.is_none() {
337 self.init().await?;
338 }
339
340 let mut transcrypted = encrypted_pseudonyms;
341
342 for i in 0..self.transcryptors.len() {
343 let system_id = &self.transcryptors[i].config.system_id;
344 let session_from = sessions_from
345 .get(system_id)
346 .ok_or_else(|| PseudonymServiceError::MissingSession(system_id.clone()))?;
347
348 let session_id = match &self.transcryptors[i].session_id {
349 Some(id) => id.clone(),
350 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
351 };
352
353 let result = self.transcryptors[i]
354 .pseudonymize_batch(
355 transcrypted.clone(),
356 domain_from,
357 domain_to,
358 session_from,
359 &session_id,
360 )
361 .await;
362
363 transcrypted = match result {
364 Err(TranscryptorError::InvalidSession(_)) => {
365 self.refresh_session(i).await?;
366
367 let new_session_id = match &self.transcryptors[i].session_id {
368 Some(id) => id.clone(),
369 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
370 };
371 self.transcryptors[i]
372 .pseudonymize_batch(
373 transcrypted,
374 domain_from,
375 domain_to,
376 session_from,
377 &new_session_id,
378 )
379 .await?
380 }
381 Err(err) => return Err(PseudonymServiceError::TranscryptorError(err)),
382 Ok(value) => value,
383 };
384 }
385
386 Ok(transcrypted)
387 }
388
389 pub async fn rekey<T>(
391 &mut self,
392 encrypted_data_point: &T,
393 sessions_from: &EncryptionContexts,
394 ) -> Result<T, PseudonymServiceError>
395 where
396 T: Rekeyable + DeserializeOwned + Serialize + Clone + ApiPath,
397 {
398 if self.pep_crypto_client.is_none() {
399 self.init().await?;
400 }
401
402 let mut transcrypted = encrypted_data_point.clone();
403
404 for i in 0..self.transcryptors.len() {
405 let system_id = &self.transcryptors[i].config.system_id;
406 let session_from = sessions_from
407 .get(system_id)
408 .ok_or_else(|| PseudonymServiceError::MissingSession(system_id.clone()))?;
409
410 let session_id = match &self.transcryptors[i].session_id {
411 Some(id) => id.clone(),
412 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
413 };
414
415 let result = self.transcryptors[i]
416 .rekey(&transcrypted, session_from, &session_id)
417 .await;
418
419 transcrypted = match result {
420 Err(TranscryptorError::InvalidSession(_)) => {
421 self.refresh_session(i).await?;
422
423 let new_session_id = match &self.transcryptors[i].session_id {
424 Some(id) => id.clone(),
425 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
426 };
427 self.transcryptors[i]
428 .rekey(&transcrypted, session_from, &new_session_id)
429 .await?
430 }
431 Err(err) => return Err(PseudonymServiceError::TranscryptorError(err)),
432 Ok(value) => value,
433 };
434 }
435
436 Ok(transcrypted)
437 }
438 pub async fn rekey_batch<T>(
442 &mut self,
443 encrypted_data_points: Vec<T>,
444 sessions_from: &EncryptionContexts,
445 ) -> Result<Vec<T>, PseudonymServiceError>
446 where
447 T: Rekeyable + DeserializeOwned + Serialize + Clone + ApiPath + HasStructure,
448 {
449 if self.pep_crypto_client.is_none() {
450 self.init().await?;
451 }
452
453 let mut transcrypted = encrypted_data_points;
454
455 for i in 0..self.transcryptors.len() {
456 let system_id = &self.transcryptors[i].config.system_id;
457 let session_from = sessions_from
458 .get(system_id)
459 .ok_or_else(|| PseudonymServiceError::MissingSession(system_id.clone()))?;
460
461 let session_id = match &self.transcryptors[i].session_id {
462 Some(id) => id.clone(),
463 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
464 };
465
466 let result = self.transcryptors[i]
467 .rekey_batch(transcrypted.clone(), session_from, &session_id)
468 .await;
469
470 transcrypted = match result {
471 Err(TranscryptorError::InvalidSession(_)) => {
472 self.refresh_session(i).await?;
473
474 let new_session_id = match &self.transcryptors[i].session_id {
475 Some(id) => id.clone(),
476 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
477 };
478 self.transcryptors[i]
479 .rekey_batch(transcrypted, session_from, &new_session_id)
480 .await?
481 }
482 Err(err) => return Err(PseudonymServiceError::TranscryptorError(err)),
483 Ok(value) => value,
484 };
485 }
486
487 Ok(transcrypted)
488 }
489 pub async fn transcrypt<T>(
491 &mut self,
492 encrypted: &T,
493 sessions_from: &EncryptionContexts,
494 domain_from: &PseudonymizationDomain,
495 domain_to: &PseudonymizationDomain,
496 ) -> Result<T, PseudonymServiceError>
497 where
498 T: Transcryptable + DeserializeOwned + Serialize + Clone + ApiPath,
499 {
500 if self.pep_crypto_client.is_none() {
501 self.init().await?;
502 }
503
504 let mut transcrypted = encrypted.clone();
505
506 for i in 0..self.transcryptors.len() {
507 let system_id = &self.transcryptors[i].config.system_id;
508 let session_from = sessions_from
509 .get(system_id)
510 .ok_or_else(|| PseudonymServiceError::MissingSession(system_id.clone()))?;
511
512 let session_id = match &self.transcryptors[i].session_id {
513 Some(id) => id.clone(),
514 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
515 };
516
517 let result = self.transcryptors[i]
518 .transcrypt(
519 &transcrypted,
520 domain_from,
521 domain_to,
522 session_from,
523 &session_id,
524 )
525 .await;
526
527 transcrypted = match result {
528 Err(TranscryptorError::InvalidSession(_)) => {
529 self.refresh_session(i).await?;
530
531 let new_session_id = match &self.transcryptors[i].session_id {
532 Some(id) => id.clone(),
533 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
534 };
535 self.transcryptors[i]
536 .transcrypt(
537 &transcrypted,
538 domain_from,
539 domain_to,
540 session_from,
541 &new_session_id,
542 )
543 .await?
544 }
545 Err(err) => return Err(PseudonymServiceError::TranscryptorError(err)),
546 Ok(value) => value,
547 };
548 }
549
550 Ok(transcrypted)
551 }
552
553 pub async fn transcrypt_batch<T>(
556 &mut self,
557 encrypted: Vec<T>,
558 sessions_from: &EncryptionContexts,
559 domain_from: &PseudonymizationDomain,
560 domain_to: &PseudonymizationDomain,
561 ) -> Result<Vec<T>, PseudonymServiceError>
562 where
563 T: Transcryptable + DeserializeOwned + Serialize + Clone + ApiPath + HasStructure,
564 {
565 if self.pep_crypto_client.is_none() {
566 self.init().await?;
567 }
568
569 let mut transcrypted = encrypted;
570
571 for i in 0..self.transcryptors.len() {
572 let system_id = &self.transcryptors[i].config.system_id;
573 let session_from = sessions_from
574 .get(system_id)
575 .ok_or_else(|| PseudonymServiceError::MissingSession(system_id.clone()))?;
576
577 let session_id = match &self.transcryptors[i].session_id {
578 Some(id) => id.clone(),
579 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
580 };
581
582 let result = self.transcryptors[i]
583 .transcrypt_batch(
584 transcrypted.clone(),
585 domain_from,
586 domain_to,
587 session_from,
588 &session_id,
589 )
590 .await;
591
592 transcrypted = match result {
593 Err(TranscryptorError::InvalidSession(_)) => {
594 self.refresh_session(i).await?;
595
596 let new_session_id = match &self.transcryptors[i].session_id {
597 Some(id) => id.clone(),
598 None => return Err(PseudonymServiceError::UninitializedTranscryptor),
599 };
600 self.transcryptors[i]
601 .transcrypt_batch(
602 transcrypted,
603 domain_from,
604 domain_to,
605 session_from,
606 &new_session_id,
607 )
608 .await?
609 }
610 Err(err) => return Err(PseudonymServiceError::TranscryptorError(err)),
611 Ok(value) => value,
612 };
613 }
614
615 Ok(transcrypted)
616 }
617 pub fn encrypt<R: Rng + CryptoRng, E: Encryptable + 'static>(
619 &mut self,
620 message: &E,
621 rng: &mut R,
622 ) -> Result<(E::EncryptedType, EncryptionContexts), PseudonymServiceError>
623 where
624 SessionKeys: KeyProvider<E::PublicKeyType>,
625 {
626 let pep_client = self
627 .pep_crypto_client
628 .as_ref()
629 .ok_or(PseudonymServiceError::UninitializedClient)?;
630
631 Ok((
632 pep_client.encrypt(message, rng),
633 self.get_current_sessions()?.clone(),
634 ))
635 }
636
637 pub fn encrypt_batch<R: Rng + CryptoRng, E: Encryptable + BatchEncryptable + 'static>(
639 &mut self,
640 message: &[E],
641 rng: &mut R,
642 ) -> Result<(Vec<E::EncryptedType>, EncryptionContexts), PseudonymServiceError>
643 where
644 SessionKeys: KeyProvider<E::PublicKeyType>,
645 {
646 let pep_client = self
647 .pep_crypto_client
648 .as_ref()
649 .ok_or(PseudonymServiceError::UninitializedClient)?;
650
651 Ok((
652 pep_client.encrypt_batch(message, rng)?,
653 self.get_current_sessions()?.clone(),
654 ))
655 }
656
657 pub fn get_current_sessions(&self) -> Result<EncryptionContexts, PseudonymServiceError> {
658 let sessions = self
659 .transcryptors
660 .iter()
661 .map(|t| {
662 let session_id = t
663 .session_id
664 .clone()
665 .ok_or(PseudonymServiceError::UninitializedTranscryptor)?;
666
667 Ok((t.config.system_id.clone(), session_id))
668 })
669 .collect::<Result<_, PseudonymServiceError>>()?;
670
671 Ok(EncryptionContexts(sessions))
672 }
673
674 pub fn decrypt<E: Encrypted>(
676 &mut self,
677 encrypted: &E,
678 ) -> Result<E::UnencryptedType, PseudonymServiceError>
679 where
680 SessionKeys: KeyProvider<E::SecretKeyType>,
681 {
682 let pep_client = self
683 .pep_crypto_client
684 .as_ref()
685 .ok_or(PseudonymServiceError::UninitializedClient)?;
686
687 Ok(pep_client.decrypt(encrypted))
688 }
689
690 pub fn decrypt_batch<E: Encrypted>(
692 &mut self,
693 encrypted: &[E],
694 ) -> Result<Vec<E::UnencryptedType>, PseudonymServiceError>
695 where
696 SessionKeys: KeyProvider<E::SecretKeyType>,
697 {
698 let pep_client = self
699 .pep_crypto_client
700 .as_ref()
701 .ok_or(PseudonymServiceError::UninitializedClient)?;
702
703 Ok(pep_client.decrypt_batch(encrypted)?)
704 }
705}