paseto_core/paserk/
pke.rs

1use alloc::boxed::Box;
2use core::fmt;
3use core::marker::PhantomData;
4
5use crate::key::{HasKey, Key, KeyInner};
6use crate::version::{Local, PkePublic, PkeSecret, Version};
7use crate::{LocalKey, PasetoError};
8
9/// This PASETO implementation allows encrypting keys using a [`PublicKey`](crate::PublicKey)
10pub trait PkeSealingVersion: Version + HasKey<Local> + HasKey<PkePublic> {
11    /// Seal the key using the public key
12    fn seal_key(
13        sealing_key: &KeyInner<Self, PkePublic>,
14        key: KeyInner<Self, Local>,
15    ) -> Result<Box<[u8]>, PasetoError>;
16}
17
18/// This PASETO implementation allows decrypting keys using a [`SecretKey`](crate::SecretKey)
19pub trait PkeUnsealingVersion: Version + HasKey<Local> + HasKey<PkeSecret> {
20    /// Unseal the key using the secret key
21    fn unseal_key(
22        sealing_key: &KeyInner<Self, PkeSecret>,
23        key_data: Box<[u8]>,
24    ) -> Result<KeyInner<Self, Local>, PasetoError>;
25}
26
27/// An asymmetrically encrypted [`LocalKey`].
28///
29/// * Encrypted using [`LocalKey::seal`]
30/// * Decrypted using [`SealedKey::unseal`]
31pub struct SealedKey<V: Version> {
32    key_data: Box<[u8]>,
33    _version: PhantomData<V>,
34}
35
36impl<V: Version> Clone for SealedKey<V> {
37    fn clone(&self) -> Self {
38        Self {
39            key_data: self.key_data.clone(),
40            _version: self._version,
41        }
42    }
43}
44
45impl<V: Version> fmt::Display for SealedKey<V> {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        f.write_str(V::PASERK_HEADER)?;
48        f.write_str(".seal.")?;
49        crate::base64::write_to_fmt(&self.key_data, f)
50    }
51}
52
53impl<V: Version> core::str::FromStr for SealedKey<V> {
54    type Err = PasetoError;
55
56    fn from_str(s: &str) -> Result<Self, Self::Err> {
57        let s = s
58            .strip_prefix(V::PASERK_HEADER)
59            .ok_or(PasetoError::InvalidKey)?;
60        let s = s.strip_prefix(".seal.").ok_or(PasetoError::InvalidKey)?;
61
62        Ok(SealedKey {
63            key_data: crate::base64::decode_vec(s)?.into_boxed_slice(),
64            _version: PhantomData,
65        })
66    }
67}
68
69impl<V: PkeSealingVersion> LocalKey<V> {
70    /// Encrypt the key such that it can only be decrypted by the resspective secret key.
71    pub fn seal(self, with: &Key<V, PkePublic>) -> Result<SealedKey<V>, PasetoError> {
72        V::seal_key(&with.0, self.0).map(|key_data| SealedKey {
73            key_data,
74            _version: PhantomData,
75        })
76    }
77}
78
79impl<V: PkeUnsealingVersion> SealedKey<V> {
80    /// Decrypt the sealed key.
81    pub fn unseal(self, with: &Key<V, PkeSecret>) -> Result<LocalKey<V>, PasetoError> {
82        V::unseal_key(&with.0, self.key_data).map(Key)
83    }
84}
85
86serde_str!(
87    impl<V> SealedKey<V>
88    where
89        V: PkeSealingVersion,
90    {
91        fn expecting() {
92            format_args!("a {}.seal. PASERK sealed key", V::PASERK_HEADER)
93        }
94    }
95);