1use std::marker::PhantomData;
4
5use serde::{Deserialize, Serialize};
6
7use crate::api;
8use crate::misc::crypto;
9use crate::misc::error::Opaque;
10use crate::misc::serde_ext::bytes_wrapper::B64UU;
11
12pub use crypto::SealingKey;
13
14#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
16#[serde(transparent)]
17pub struct Sealed<T>
18where
19 T: api::Signable,
20{
21 pub(crate) inner: B64UU,
22
23 phantom_data: PhantomData<T>,
24}
25
26impl<T> Sealed<T>
27where
28 T: api::Signable,
29{
30 pub fn new(message: &T, key: &SealingKey) -> api::Result<Self> {
32 Ok(Self {
33 phantom_data: PhantomData,
34 inner: serde_bytes::ByteBuf::from(
35 crypto::seal(message, key, T::CODE.to_bytes()).map_err(|err| {
36 log::error!(
37 "failed to seal message of type {tp}: {err:#}",
38 tp = std::any::type_name::<T>()
39 );
40
41 api::ErrorCode::InternalError
42 })?,
43 )
44 .into(),
45 })
46 }
47
48 pub fn open(self, key: &SealingKey) -> Result<T, Opaque> {
50 crypto::unseal(&*self.inner, key, T::CODE.to_bytes())
51 }
52}
53
54impl<T> From<B64UU> for Sealed<T>
55where
56 T: api::Signable,
57{
58 fn from(inner: B64UU) -> Self {
59 Self {
60 inner,
61 phantom_data: PhantomData,
62 }
63 }
64}