paseto_core/paserk/
pw_wrap.rs1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt;
4use core::marker::PhantomData;
5
6use crate::PasetoError;
7use crate::key::{HasKey, Key, SealingKey};
8use crate::version::Version;
9
10pub trait PwWrapVersion: Version {
12 type Params: Default;
13
14 fn pw_wrap_key(
16 header: &'static str,
17 pass: &[u8],
18 params: &Self::Params,
19 key_data: Vec<u8>,
20 ) -> Result<Vec<u8>, PasetoError>;
21
22 fn get_params(key_data: &[u8]) -> Result<Self::Params, PasetoError>;
24
25 fn pw_unwrap_key<'key>(
27 header: &'static str,
28 pass: &[u8],
29 key_data: &'key mut [u8],
30 ) -> Result<&'key [u8], PasetoError>;
31}
32
33pub struct PasswordWrappedKey<V: PwWrapVersion, K: SealingKey> {
38 key_data: Box<[u8]>,
39 _version: PhantomData<(V, K)>,
40}
41
42impl<V: PwWrapVersion + HasKey<K>, K: SealingKey> Key<V, K> {
43 pub fn password_wrap(self, pass: &[u8]) -> Result<PasswordWrappedKey<V, K>, PasetoError> {
45 self.password_wrap_with_params(pass, &V::Params::default())
46 }
47
48 pub fn password_wrap_with_params(
50 self,
51 pass: &[u8],
52 params: &V::Params,
53 ) -> Result<PasswordWrappedKey<V, K>, PasetoError> {
54 V::pw_wrap_key(
55 K::PW_WRAP_HEADER,
56 pass,
57 params,
58 V::encode(&self.0).into_vec(),
59 )
60 .map(|key_data| PasswordWrappedKey {
61 key_data: key_data.into_boxed_slice(),
62 _version: PhantomData,
63 })
64 }
65}
66
67impl<V: PwWrapVersion, K: SealingKey> PasswordWrappedKey<V, K> {
68 pub fn params(&self) -> Result<V::Params, PasetoError> {
70 V::get_params(&self.key_data)
71 }
72}
73
74impl<V: PwWrapVersion + HasKey<K>, K: SealingKey> PasswordWrappedKey<V, K> {
75 pub fn unwrap(mut self, pass: &[u8]) -> Result<Key<V, K>, PasetoError> {
77 V::pw_unwrap_key(K::PW_WRAP_HEADER, pass, &mut self.key_data)
78 .and_then(V::decode)
79 .map(Key)
80 }
81}
82
83impl<V: PwWrapVersion, K: SealingKey> fmt::Display for PasswordWrappedKey<V, K> {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 f.write_str(V::PASERK_HEADER)?;
86 f.write_str(K::PW_WRAP_HEADER)?;
87 crate::base64::write_to_fmt(&self.key_data, f)
88 }
89}
90
91impl<V: PwWrapVersion, K: SealingKey> core::str::FromStr for PasswordWrappedKey<V, K> {
92 type Err = PasetoError;
93
94 fn from_str(s: &str) -> Result<Self, Self::Err> {
95 let s = s
96 .strip_prefix(V::PASERK_HEADER)
97 .ok_or(PasetoError::InvalidKey)?;
98 let s = s
99 .strip_prefix(K::PW_WRAP_HEADER)
100 .ok_or(PasetoError::InvalidKey)?;
101
102 Ok(PasswordWrappedKey {
103 key_data: crate::base64::decode_vec(s)?.into_boxed_slice(),
104 _version: PhantomData,
105 })
106 }
107}
108
109serde_str!(
110 impl<V, K> PasswordWrappedKey<V, K>
111 where
112 V: PwWrapVersion,
113 K: SealingKey,
114 {
115 fn expecting() {
116 format_args!(
117 "a {}{} PASERK password wrapped key",
118 V::PASERK_HEADER,
119 K::PW_WRAP_HEADER
120 )
121 }
122 }
123);