itsdangerous/
serde_serializer.rs

1use std::ops::Deref;
2use std::time::{Duration, SystemTime};
3
4use serde::{de::DeserializeOwned, Serialize};
5use serde_json;
6
7use crate::error::{BadSignature, BadTimedSignature, PayloadError, TimestampExpired};
8use crate::serializer_traits::UnsignToString;
9use crate::timestamp;
10use crate::{
11    base64, AsSigner, Encoding, Separator, Serializer, Signer, TimedSerializer, TimestampSigner,
12};
13
14pub struct NullEncoding;
15pub struct URLSafeEncoding;
16
17pub struct SerializerImpl<TSigner, TEncoding> {
18    signer: TSigner,
19    encoding: TEncoding,
20}
21
22pub struct TimedSerializerImpl<TSigner, TEncoding> {
23    signer: TSigner,
24    encoding: TEncoding,
25}
26
27impl<TSigner, TEncoding> TimedSerializerImpl<TSigner, TEncoding> {
28    pub fn signer(&self) -> &TSigner {
29        &self.signer
30    }
31}
32
33pub fn serializer_with_signer<TSigner, TEncoding>(
34    signer: TSigner,
35    encoding: TEncoding,
36) -> SerializerImpl<TSigner, TEncoding>
37where
38    TSigner: Signer,
39    TEncoding: Encoding,
40{
41    SerializerImpl { signer, encoding }
42}
43
44pub fn timed_serializer_with_signer<TSigner, TEncoding>(
45    signer: TSigner,
46    encoding: TEncoding,
47) -> TimedSerializerImpl<TSigner, TEncoding>
48where
49    TSigner: TimestampSigner,
50    TEncoding: Encoding,
51{
52    TimedSerializerImpl { signer, encoding }
53}
54
55impl Encoding for NullEncoding {
56    fn encode<'a>(&self, serialized_input: String) -> String {
57        serialized_input
58    }
59
60    fn decode<'a>(&self, encoded_input: String) -> Result<String, PayloadError> {
61        Ok(encoded_input)
62    }
63}
64
65impl Encoding for URLSafeEncoding {
66    fn encode<'a>(&self, serialized_input: String) -> String {
67        base64::encode(&serialized_input)
68    }
69
70    fn decode<'a>(&self, encoded_input: String) -> Result<String, PayloadError> {
71        // TODO: Handle decompression from... you know... python land.
72        let decoded = base64::decode_str(&encoded_input)?;
73        Ok(String::from_utf8(decoded).map_err(|e| e.utf8_error())?)
74    }
75}
76
77#[inline(always)]
78fn deserialize<'a, T: DeserializeOwned, Encoding: self::Encoding>(
79    value: &'a str,
80    encoding: &Encoding,
81) -> Result<T, BadSignature<'a>> {
82    let decoded = encoding
83        .decode(value.to_string())
84        .map_err(|e| BadSignature::PayloadInvalid {
85            value,
86            error: e.into(),
87        })?;
88    serde_json::from_str(&decoded).map_err(|e| BadSignature::PayloadInvalid {
89        value,
90        error: e.into(),
91    })
92}
93
94impl<TSigner, TEncoding> Serializer for SerializerImpl<TSigner, TEncoding>
95where
96    TSigner: Signer,
97    TEncoding: Encoding,
98{
99    fn sign<T: Serialize>(&self, value: &T) -> serde_json::Result<String> {
100        let serialized = serde_json::to_string(value)?;
101        let encoded = self.encoding.encode(serialized);
102        Ok(self.signer.sign(encoded))
103    }
104
105    fn unsign<'a, T: DeserializeOwned>(&'a self, value: &'a str) -> Result<T, BadSignature<'a>> {
106        let value = self.signer.unsign(value)?;
107        deserialize(value, &self.encoding)
108    }
109}
110
111impl<TSigner, TEncoding> UnsignToString for SerializerImpl<TSigner, TEncoding>
112where
113    TSigner: Signer,
114    TEncoding: Encoding,
115{
116    fn unsign_to_string<'a>(&'a self, value: &'a str) -> Result<String, BadSignature<'a>> {
117        let value = self.signer.unsign(value)?;
118        self.encoding
119            .decode(value.to_string())
120            .map_err(|e| BadSignature::PayloadInvalid {
121                value,
122                error: e.into(),
123            })
124    }
125}
126
127impl<TSigner, TEncoding> AsSigner for SerializerImpl<TSigner, TEncoding>
128where
129    TSigner: Signer,
130{
131    type Signer = TSigner;
132
133    fn as_signer(&self) -> &Self::Signer {
134        &self.signer
135    }
136}
137
138impl<TSigner, TEncoding> TimedSerializer for TimedSerializerImpl<TSigner, TEncoding>
139where
140    TSigner: TimestampSigner,
141    TEncoding: Encoding,
142{
143    fn sign<T: Serialize>(&self, value: &T) -> serde_json::Result<String> {
144        self.sign_with_timestamp(value, SystemTime::now())
145    }
146
147    fn sign_with_timestamp<T: Serialize>(
148        &self,
149        value: &T,
150        timestamp: SystemTime,
151    ) -> serde_json::Result<String> {
152        let serialized = serde_json::to_string(value)?;
153        let encoded = self.encoding.encode(serialized);
154        Ok(self.signer.sign_with_timestamp(encoded, timestamp))
155    }
156
157    fn unsign<'a, T: DeserializeOwned>(
158        &'a self,
159        value: &'a str,
160    ) -> Result<UnsignedTimedSerializerValue<T>, BadTimedSignature<'a>> {
161        let value = self.signer.unsign(value)?;
162        let timestamp = value.timestamp();
163        let value = value.value();
164        let deserialized_value = deserialize(value, &self.encoding)?;
165
166        Ok(UnsignedTimedSerializerValue {
167            value: deserialized_value,
168            timestamp,
169        })
170    }
171}
172
173/// Represents a value + timestamp that has been successfully unsigned by [`TimedSerializer::unsign`].
174pub struct UnsignedTimedSerializerValue<T> {
175    value: T,
176    timestamp: SystemTime,
177}
178
179impl<T> UnsignedTimedSerializerValue<T> {
180    /// The value that has been [`unsigned`]. This value is safe to use and
181    /// was part of a payload that has been successfully [`unsigned`].
182    ///
183    /// [`unsigned`]: TimedSerializer::unsign
184    pub fn value(self) -> T {
185        self.value
186    }
187
188    /// The timestamp that the value was signed with.
189    ///
190    /// For conveniently unwrapping the value and enforcing a max age,
191    /// consider using [`value_if_not_expired`].
192    ///
193    /// [`value_if_not_expired`]: UnsignedTimedSerializerValue::value_if_not_expired
194    pub fn timestamp(&self) -> SystemTime {
195        self.timestamp
196    }
197
198    /// Returns the value if the timestamp is not older than `max_age`.
199    /// In the event that the timestamp is in the future, we'll consider that valid.
200    ///
201    /// If the value is expired, returns [`TimestampExpired`].
202    pub fn value_if_not_expired(self, max_age: Duration) -> Result<T, TimestampExpired<T>> {
203        match self.timestamp.elapsed() {
204            Ok(duration) if duration > max_age => Err(TimestampExpired {
205                timestamp: self.timestamp,
206                value: self.value,
207                max_age,
208            }),
209            // Timestamp is in the future or hasn't expired yet.
210            Ok(_) | Err(_) => Ok(self.value),
211        }
212    }
213}
214
215impl<T> Deref for UnsignedTimedSerializerValue<T> {
216    type Target = T;
217    fn deref(&self) -> &Self::Target {
218        &self.value
219    }
220}
221
222/// An [`UnverifiedValue`] is just that. A deserialized value that has not been verified against
223/// against a signer. This is useful if you want to deserialize something without verifying
224/// the signature, because you might need data in the unsigned value in order to look up the
225/// signing key in a database somewhere.
226///
227/// # Example
228/// ```rust
229/// use itsdangerous::*;
230///
231/// // One could imagine this looking up a signing key from a databse or something.
232/// fn get_signing_key(user_id: u64) -> &'static str {
233///     match user_id {
234///         1 => "hello",
235///         2 => "world",
236///         _ => panic!("unexpected user {:?}", user_id)
237///     }
238/// }
239///
240/// fn get_serializer(user_id: u64) -> impl Serializer + AsSigner {
241///     serializer_with_signer(default_builder(get_signing_key(user_id)).build(), URLSafeEncoding)
242/// }
243///
244/// // Let's create a token for a user with id 1.
245/// let token = get_serializer(1).sign(&1).unwrap();
246///
247/// // Now, let's say we've gotten that token from somewhere. We need to deserialize it, in order
248/// // to determine the signing key to use. `from_str` will fail if deserialization fails, not if
249/// // the signature is invalid.
250/// let unverified_user_id = UnverifiedValue::<u64>::from_str(Separator::default(), URLSafeEncoding, &token).unwrap();
251/// let serializer = get_serializer(*unverified_user_id.unverified_value());
252/// // We can now attempt to verify the token with a given serializer.
253/// assert_eq!(unverified_user_id.verify(&serializer).unwrap(), 1);
254/// ```
255pub struct UnverifiedValue<'a, T> {
256    unverified_value: T,
257    unverified_raw_value: &'a str,
258    unverified_signature: &'a str,
259}
260
261impl<'a, T: DeserializeOwned> UnverifiedValue<'a, T> {
262    pub fn from_str<TEncoding: Encoding>(
263        separator: Separator,
264        encoding: TEncoding,
265        input: &'a str,
266    ) -> Result<Self, BadSignature> {
267        let (unverified_raw_value, unverified_signature) = separator.split(input)?;
268        let unverified_value = deserialize(unverified_raw_value, &encoding)?;
269
270        Ok(UnverifiedValue {
271            unverified_value,
272            unverified_raw_value,
273            unverified_signature,
274        })
275    }
276
277    // XXX: Doc
278    pub fn unverified_value(&self) -> &T {
279        &self.unverified_value
280    }
281
282    pub fn verify<TSigner: AsSigner>(self, signer: &TSigner) -> Result<T, BadSignature<'a>> {
283        let value = self.unverified_raw_value;
284        let signature = self.unverified_signature;
285
286        if signer
287            .as_signer()
288            .verify_encoded_signature(value.as_bytes(), signature.as_bytes())
289        {
290            Ok(self.unverified_value)
291        } else {
292            Err(BadSignature::SignatureMismatch { signature, value })
293        }
294    }
295}
296
297pub struct UnverifiedTimedValue<'a, T> {
298    unverified_value: T,
299    unverified_raw_value: &'a str,
300    unverified_signature: &'a str,
301    unverified_timestamp: SystemTime,
302}
303
304impl<'a, T: DeserializeOwned> UnverifiedTimedValue<'a, T> {
305    pub fn from_str<TEncoding: Encoding>(
306        separator: Separator,
307        encoding: TEncoding,
308        input: &'a str,
309    ) -> Result<Self, BadTimedSignature> {
310        let (unverified_raw_value, unverified_signature) = separator.split(input)?;
311        let (unverified_raw_serialized_value, unverified_timestamp) =
312            separator.split(unverified_raw_value)?;
313        let unverified_timestamp = timestamp::decode(unverified_timestamp)?;
314        let unverified_value = deserialize(unverified_raw_serialized_value, &encoding)?;
315
316        Ok(UnverifiedTimedValue {
317            unverified_value,
318            unverified_raw_value,
319            unverified_signature,
320            unverified_timestamp,
321        })
322    }
323
324    pub fn unverified_value(&self) -> &T {
325        &self.unverified_value
326    }
327
328    pub fn unverified_timestamp(&self) -> SystemTime {
329        self.unverified_timestamp
330    }
331
332    pub fn verify<TSigner: TimestampSigner + AsSigner>(
333        self,
334        timestamp_signer: &TSigner,
335    ) -> Result<UnsignedTimedSerializerValue<T>, BadTimedSignature<'a>> {
336        let value = self.unverified_raw_value;
337        let signature = self.unverified_signature;
338
339        if timestamp_signer
340            .as_signer()
341            .verify_encoded_signature(value.as_bytes(), signature.as_bytes())
342        {
343            Ok(UnsignedTimedSerializerValue {
344                value: self.unverified_value,
345                timestamp: self.unverified_timestamp,
346            })
347        } else {
348            Err(BadTimedSignature::SignatureMismatch { signature, value })
349        }
350    }
351}
352
353#[cfg(test)]
354mod tests {
355    use std::time::UNIX_EPOCH;
356
357    use super::*;
358    use crate::{default_builder, IntoTimestampSigner};
359    #[test]
360
361    fn test_null_encoding() {
362        let s = "hello world".to_owned();
363        let encoding = NullEncoding;
364        assert_eq!(encoding.encode(s.clone()), s);
365        assert_eq!(encoding.decode(s.clone()).unwrap(), s);
366    }
367
368    #[test]
369    fn test_url_safe_encoding() {
370        let s = "hello world".to_owned();
371        let encoded = "aGVsbG8gd29ybGQ".to_owned();
372        let encoding = URLSafeEncoding;
373        assert_eq!(encoding.encode(s.clone()), encoded);
374        assert_eq!(encoding.decode(encoded).unwrap(), s);
375    }
376
377    #[test]
378    fn test_sign_null_encoding() {
379        let signer = default_builder("hello world").build();
380        let serializer = serializer_with_signer(signer, NullEncoding);
381        let signed = "[1,2,3].bq_ST5hV4J35lKdovyr_ng-ZIxU";
382        assert_eq!(serializer.sign(&vec![1, 2, 3]).unwrap(), signed);
383        assert_eq!(serializer.unsign::<Vec<u8>>(signed).unwrap(), vec![1, 2, 3]);
384    }
385
386    #[test]
387    fn test_unsign_unverified_good_signature() {
388        let signer = default_builder("hello world").build();
389        let signed = "[1,2,3].bq_ST5hV4J35lKdovyr_ng-ZIxU";
390        let unverified_value: UnverifiedValue<Vec<u8>> =
391            UnverifiedValue::from_str(signer.separator, NullEncoding, signed).unwrap();
392        let expected = vec![1, 2, 3];
393        assert_eq!(unverified_value.unverified_value(), &expected);
394        assert_eq!(unverified_value.verify(&signer).unwrap(), expected);
395    }
396
397    #[test]
398    fn test_unsign_unverified_bad_signature() {
399        let signer = default_builder("not the right key lol").build();
400        let signed = "[1,2,3].bq_ST5hV4J35lKdovyr_ng-ZIxU";
401        let unverified_value: UnverifiedValue<Vec<u8>> =
402            UnverifiedValue::from_str(signer.separator, NullEncoding, signed).unwrap();
403        let expected = vec![1, 2, 3];
404        assert_eq!(unverified_value.unverified_value(), &expected);
405        assert!(unverified_value.verify(&signer).is_err());
406    }
407
408    #[test]
409    fn test_sign_url_safe_encoding() {
410        let signer = default_builder("hello world").build();
411        let serializer = serializer_with_signer(signer, URLSafeEncoding);
412        let signed = "WzEsMiwzXQ.ohh92zNcvFVoWHrPf5uumLp6mbQ";
413        assert_eq!(serializer.sign(&vec![1, 2, 3]).unwrap(), signed);
414        assert_eq!(serializer.unsign::<Vec<u8>>(signed).unwrap(), vec![1, 2, 3]);
415    }
416
417    #[test]
418    fn test_timed_sign_null_encoding() {
419        let signer = default_builder("hello world")
420            .build()
421            .into_timestamp_signer();
422        let serializer = timed_serializer_with_signer(signer, NullEncoding);
423        let timestamp = UNIX_EPOCH + Duration::from_secs(1560181622);
424        let signed = "[1,2,3].XP57dg.azFnnbv1s1cilwCeXmeVlMmbqD4";
425        assert_eq!(
426            serializer
427                .sign_with_timestamp(&vec![1, 2, 3], timestamp)
428                .unwrap(),
429            signed
430        );
431        let unsigned = serializer.unsign::<Vec<u8>>(signed).unwrap();
432        assert_eq!(unsigned.timestamp(), timestamp);
433        assert_eq!(unsigned.value(), vec![1, 2, 3]);
434    }
435
436    #[test]
437    fn test_unverified_timed_good_signature() {
438        let signer = default_builder("hello world")
439            .build()
440            .into_timestamp_signer();
441        let timestamp = UNIX_EPOCH + Duration::from_secs(1560181622);
442        let signed = "[1,2,3].XP57dg.azFnnbv1s1cilwCeXmeVlMmbqD4";
443        let unverified_value: UnverifiedTimedValue<Vec<u8>> =
444            UnverifiedTimedValue::from_str(signer.separator(), NullEncoding, signed).unwrap();
445        let expected = vec![1, 2, 3];
446        assert_eq!(unverified_value.unverified_timestamp(), timestamp);
447        assert_eq!(unverified_value.unverified_value(), &expected);
448        assert_eq!(unverified_value.verify(&signer).unwrap().value(), expected);
449    }
450
451    #[test]
452    fn test_unverified_timed_value_if_not_expired() {
453        let signer = default_builder("hello world")
454            .build()
455            .into_timestamp_signer();
456        let serializer = timed_serializer_with_signer(signer, NullEncoding);
457        let timestamp = SystemTime::now() - Duration::from_secs(30);
458        let signed = serializer
459            .sign_with_timestamp(&vec![1, 2, 3], timestamp)
460            .unwrap();
461
462        let unsigned = serializer.unsign::<Vec<u8>>(&signed).unwrap();
463        assert!(unsigned
464            .value_if_not_expired(Duration::from_secs(15))
465            .is_err());
466
467        let unsigned = serializer.unsign::<Vec<u8>>(&signed).unwrap();
468        assert_eq!(
469            unsigned
470                .value_if_not_expired(Duration::from_secs(60))
471                .unwrap(),
472            vec![1, 2, 3]
473        );
474    }
475
476    #[test]
477    fn test_timed_signer_impl_can_be_used_to_verify() {
478        let signer = default_builder("hello world")
479            .build()
480            .into_timestamp_signer();
481        let separator = signer.separator().clone();
482        let serializer = timed_serializer_with_signer(signer, URLSafeEncoding);
483        let signed = serializer.sign(&"whatever").unwrap();
484        let unverified: UnverifiedTimedValue<String> =
485            UnverifiedTimedValue::from_str(separator, URLSafeEncoding, &signed).unwrap();
486        assert_eq!(unverified.unverified_value(), "whatever");
487        let verified = unverified
488            .verify(serializer.signer())
489            .expect("Failed to verify");
490        assert_eq!(&verified.value(), "whatever");
491    }
492}
493
494#[cfg(all(test, feature = "nightly"))]
495mod bench {
496    use crate::*;
497    extern crate test;
498    use test::Bencher;
499
500    #[bench]
501    fn bench_sign(bench: &mut Bencher) {
502        let signer = default_builder("hello world").build();
503        let serializer = serializer_with_signer(signer, NullEncoding);
504
505        let value = vec![1, 2, 3];
506        bench.iter(|| serializer.sign(&value))
507    }
508
509    #[bench]
510    fn bench_unsign(bench: &mut Bencher) {
511        let signer = default_builder("hello world").build();
512        let serializer = serializer_with_signer(signer, NullEncoding);
513        let signed = "[1,2,3].D-AM9g.nHmuOEE3v5DuwHEW9noSBOvExO0";
514        bench.iter(|| serializer.unsign::<Vec<u8>>(&signed))
515    }
516}