paseto_core/paserk/
pie_wrap.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt;
4use core::marker::PhantomData;
5
6use crate::key::{HasKey, Key, KeyInner, SealingKey};
7use crate::version::{Local, Version};
8use crate::{LocalKey, PasetoError};
9
10/// This PASETO implementation allows encrypting keys using a [`LocalKey`](crate::LocalKey)
11pub trait PieWrapVersion: Version + HasKey<Local> {
12    /// Wrap the key
13    fn pie_wrap_key(
14        header: &'static str,
15        wrapping_key: &KeyInner<Self, Local>,
16        key_data: Vec<u8>,
17    ) -> Result<Vec<u8>, PasetoError>;
18
19    /// Unwrap the key
20    fn pie_unwrap_key<'key>(
21        header: &'static str,
22        wrapping_key: &KeyInner<Self, Local>,
23        key_data: &'key mut [u8],
24    ) -> Result<&'key [u8], PasetoError>;
25}
26
27/// An symmetrically encrypted [`Key`].
28///
29/// * Encrypted using [`Key::wrap_pie`]
30/// * Decrypted using [`PieWrappedKey::unwrap`]
31pub struct PieWrappedKey<V: PieWrapVersion, K: SealingKey> {
32    key_data: Box<[u8]>,
33    _version: PhantomData<(V, K)>,
34}
35
36impl<V: PieWrapVersion + HasKey<K>, K: SealingKey> Key<V, K> {
37    pub fn wrap_pie(self, with: &LocalKey<V>) -> Result<PieWrappedKey<V, K>, PasetoError> {
38        V::pie_wrap_key(
39            K::PIE_WRAP_HEADER,
40            &with.0,
41            <V as HasKey<K>>::encode(&self.0).into_vec(),
42        )
43        .map(|key_data| PieWrappedKey {
44            key_data: key_data.into_boxed_slice(),
45            _version: PhantomData,
46        })
47    }
48}
49
50impl<V: PieWrapVersion + HasKey<K>, K: SealingKey> PieWrappedKey<V, K> {
51    pub fn unwrap(mut self, with: &LocalKey<V>) -> Result<Key<V, K>, PasetoError> {
52        V::pie_unwrap_key(K::PIE_WRAP_HEADER, &with.0, &mut self.key_data)
53            .and_then(<V as HasKey<K>>::decode)
54            .map(Key)
55    }
56}
57
58impl<V: PieWrapVersion, K: SealingKey> fmt::Display for PieWrappedKey<V, K> {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        f.write_str(V::PASERK_HEADER)?;
61        f.write_str(K::PIE_WRAP_HEADER)?;
62        crate::base64::write_to_fmt(&self.key_data, f)
63    }
64}
65
66impl<V: PieWrapVersion, K: SealingKey> core::str::FromStr for PieWrappedKey<V, K> {
67    type Err = PasetoError;
68
69    fn from_str(s: &str) -> Result<Self, Self::Err> {
70        let s = s
71            .strip_prefix(V::PASERK_HEADER)
72            .ok_or(PasetoError::InvalidKey)?;
73        let s = s
74            .strip_prefix(K::PIE_WRAP_HEADER)
75            .ok_or(PasetoError::InvalidKey)?;
76
77        Ok(PieWrappedKey {
78            key_data: crate::base64::decode_vec(s)?.into_boxed_slice(),
79            _version: PhantomData,
80        })
81    }
82}
83
84serde_str!(
85    impl<V, K> PieWrappedKey<V, K>
86    where
87        V: PieWrapVersion,
88        K: SealingKey,
89    {
90        fn expecting() {
91            format_args!(
92                "a {}{} PASERK wrapped key",
93                V::PASERK_HEADER,
94                K::PIE_WRAP_HEADER
95            )
96        }
97    }
98);