1use alloc::boxed::Box;
4use alloc::vec::Vec;
5use core::marker::PhantomData;
6
7use crate::encodings::{Footer, Payload};
8use crate::key::Key;
9use crate::validation::Validate;
10use crate::version::{Local, Public};
11use crate::{
12 EncryptedToken, LocalKey, PasetoError, PublicKey, SecretKey, SignedToken, UnencryptedToken,
13 UnsignedToken, version,
14};
15
16pub struct UnsealedToken<V, P, M, F = ()> {
25 pub claims: M,
27 pub footer: F,
29 pub(crate) _version: PhantomData<V>,
30 pub(crate) _purpose: PhantomData<P>,
31}
32
33impl<V: crate::version::Version, T: crate::version::Purpose, M> UnsealedToken<V, T, M> {
34 pub fn new(claims: M) -> Self {
36 UnsealedToken {
37 claims,
38 footer: (),
39 _version: PhantomData,
40 _purpose: PhantomData,
41 }
42 }
43}
44
45impl<V, T, M> UnsealedToken<V, T, M, ()> {
46 pub fn with_footer<F>(self, footer: F) -> UnsealedToken<V, T, M, F> {
50 UnsealedToken {
51 claims: self.claims,
52 footer,
53 _version: self._version,
54 _purpose: self._purpose,
55 }
56 }
57}
58
59pub struct SealedToken<V, P, M, F = ()> {
73 pub(crate) payload: Box<[u8]>,
74 pub(crate) encoded_footer: Box<[u8]>,
75 pub(crate) footer: F,
76 pub(crate) _version: PhantomData<V>,
77 pub(crate) _purpose: PhantomData<P>,
78 pub(crate) _message: PhantomData<M>,
79}
80
81impl<V, T, M, F> SealedToken<V, T, M, F> {
82 pub fn unverified_footer(&self) -> &F {
84 &self.footer
85 }
86}
87
88impl<V, P, M, F> SealedToken<V, P, M, F>
89where
90 V: version::UnsealingVersion<P>,
91 P: version::Purpose,
92 M: Payload,
93 F: Footer,
94{
95 #[doc(alias = "decrypt")]
97 #[doc(alias = "verify")]
98 pub fn unseal(
99 mut self,
100 key: &Key<V, P>,
101 aad: &[u8],
102 v: &impl Validate<Claims = M>,
103 ) -> Result<UnsealedToken<V, P, M, F>, PasetoError> {
104 let cleartext = V::unseal(
105 &key.0,
106 M::SUFFIX,
107 &mut self.payload,
108 &self.encoded_footer,
109 aad,
110 )?;
111
112 let message = M::decode(cleartext).map_err(PasetoError::PayloadError)?;
113
114 v.validate(&message)?;
115
116 Ok(UnsealedToken {
117 claims: message,
118 footer: self.footer,
119 _version: PhantomData,
120 _purpose: PhantomData,
121 })
122 }
123}
124
125impl<V, P, M, F> UnsealedToken<V, P, M, F>
126where
127 V: version::SealingVersion<P>,
128 P: version::Purpose,
129 M: Payload,
130 F: Footer,
131{
132 #[doc(alias = "encrypt")]
134 #[doc(alias = "sign")]
135 #[inline(always)]
136 pub fn seal(
137 self,
138 key: &Key<V, P::SealingKey>,
139 aad: &[u8],
140 ) -> Result<SealedToken<V, P, M, F>, PasetoError> {
141 self.dangerous_seal_with_nonce(key, aad, V::nonce()?)
142 }
143
144 pub fn dangerous_seal_with_nonce(
149 self,
150 key: &Key<V, P::SealingKey>,
151 aad: &[u8],
152 nonce: Vec<u8>,
153 ) -> Result<SealedToken<V, P, M, F>, PasetoError> {
154 let mut footer = Vec::new();
155 self.footer
156 .encode(&mut footer)
157 .map_err(PasetoError::PayloadError)?;
158 let footer = footer.into_boxed_slice();
159
160 let mut payload = nonce;
161 self.claims
162 .encode(&mut payload)
163 .map_err(PasetoError::PayloadError)?;
164
165 let payload = V::dangerous_seal_with_nonce(&key.0, M::SUFFIX, payload, &footer, aad)?
166 .into_boxed_slice();
167
168 Ok(SealedToken {
169 payload,
170 encoded_footer: footer,
171 footer: self.footer,
172 _version: PhantomData,
173 _purpose: PhantomData,
174 _message: PhantomData,
175 })
176 }
177}
178
179impl<V, M, F> EncryptedToken<V, M, F>
180where
181 V: version::UnsealingVersion<Local>,
182 M: Payload,
183 F: Footer,
184{
185 #[inline(always)]
187 pub fn decrypt(
188 self,
189 key: &LocalKey<V>,
190 v: &impl Validate<Claims = M>,
191 ) -> Result<UnencryptedToken<V, M, F>, PasetoError> {
192 self.decrypt_with_aad(key, &[], v)
193 }
194
195 #[inline(always)]
197 pub fn decrypt_with_aad(
198 self,
199 key: &LocalKey<V>,
200 aad: &[u8],
201 v: &impl Validate<Claims = M>,
202 ) -> Result<UnencryptedToken<V, M, F>, PasetoError> {
203 self.unseal(key, aad, v)
204 }
205}
206
207impl<V, M, F> UnencryptedToken<V, M, F>
208where
209 V: version::SealingVersion<Local>,
210 M: Payload,
211 F: Footer,
212{
213 #[inline(always)]
215 pub fn encrypt(self, key: &LocalKey<V>) -> Result<EncryptedToken<V, M, F>, PasetoError> {
216 self.encrypt_with_aad(key, &[])
217 }
218
219 #[inline(always)]
221 pub fn encrypt_with_aad(
222 self,
223 key: &LocalKey<V>,
224 aad: &[u8],
225 ) -> Result<EncryptedToken<V, M, F>, PasetoError> {
226 self.seal(key, aad)
227 }
228}
229
230impl<V, M, F> SignedToken<V, M, F>
231where
232 V: version::UnsealingVersion<Public>,
233 M: Payload,
234 F: Footer,
235{
236 #[inline(always)]
238 pub fn verify(
239 self,
240 key: &PublicKey<V>,
241 v: &impl Validate<Claims = M>,
242 ) -> Result<UnsignedToken<V, M, F>, PasetoError> {
243 self.verify_with_aad(key, &[], v)
244 }
245
246 #[inline(always)]
248 pub fn verify_with_aad(
249 self,
250 key: &PublicKey<V>,
251 aad: &[u8],
252 v: &impl Validate<Claims = M>,
253 ) -> Result<UnsignedToken<V, M, F>, PasetoError> {
254 self.unseal(key, aad, v)
255 }
256}
257
258impl<V, M, F> UnsignedToken<V, M, F>
259where
260 V: version::SealingVersion<Public>,
261 M: Payload,
262 F: Footer,
263{
264 #[inline(always)]
266 pub fn sign(self, key: &SecretKey<V>) -> Result<SignedToken<V, M, F>, PasetoError> {
267 self.sign_with_aad(key, &[])
268 }
269
270 #[inline(always)]
272 pub fn sign_with_aad(
273 self,
274 key: &SecretKey<V>,
275 aad: &[u8],
276 ) -> Result<SignedToken<V, M, F>, PasetoError> {
277 self.seal(key, aad)
278 }
279}