Skip to main content

pubhubs/api/
sealed.rs

1//! Sealing data using symmetric crypto
2
3use 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/// A symmetrically encrypted encoding of `T`.
15#[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    /// Seals a `message` using the given [`SealingKey`].
31    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    /// Opens this sealed message
49    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}