hashing_serializer/
lib.rs

1#![no_std]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![doc = include_str!("../README.md")]
4#![deny(unsafe_code)]
5#![warn(
6    clippy::unwrap_used,
7    missing_docs,
8    rust_2018_idioms,
9    trivial_casts,
10    trivial_numeric_casts,
11    unused_qualifications
12)]
13
14#[cfg(feature = "alloc")]
15extern crate alloc;
16
17#[cfg(feature = "alloc")]
18use alloc::{format, string::String};
19
20use core::fmt;
21
22use digest::Update;
23use serde::{
24    ser::{
25        self, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
26        SerializeTupleStruct, SerializeTupleVariant,
27    },
28    Serialize, Serializer,
29};
30
31/// A serializer that hashes the data instead of serializing it.
32pub struct HashingSerializer<'a, T: Update> {
33    /// A reference to the digest that will accumulate the data.
34    pub digest: &'a mut T,
35}
36
37/// Possible errors during serialization.
38#[derive(Debug, PartialEq, Eq, Clone)]
39pub enum Error {
40    /// The type's [`serde::Serialize`] impl tried to serialize a sequence of undefined length.
41    UndefinedSequenceLength,
42
43    /// Sequence length does not fit into `u128`.
44    ///
45    /// Really, this shouldn't ever happen.
46    SequenceLengthTooLarge,
47
48    /// [`Serializer::collect_str`] got called, but heap memory allocation is not available.
49    ///
50    /// Can only be returned if `alloc` feature not enabled.
51    CannotCollectStr,
52
53    /// Custom `serde` error, but memory allocation is not available.
54    /// Set a breakpoint where this is thrown for more information.
55    ///
56    /// Can only be returned if `alloc` feature not enabled).
57    CustomErrorNoAlloc,
58
59    /// Custom `serde` error.
60    #[cfg(feature = "alloc")]
61    CustomError(String),
62}
63
64#[cfg(feature = "alloc")]
65impl ser::Error for Error {
66    fn custom<T: fmt::Display>(msg: T) -> Self {
67        Self::CustomError(format!("{}", msg))
68    }
69}
70
71#[cfg(not(feature = "alloc"))]
72impl ser::Error for Error {
73    fn custom<T: fmt::Display>(_msg: T) -> Self {
74        Self::CustomErrorNoAlloc
75    }
76}
77
78impl ser::StdError for Error {}
79
80impl fmt::Display for Error {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        write!(f, "{:?}", self)
83    }
84}
85
86/// Converts the `usize` sequence length to a fixed length type,
87/// since we want the result to be portable.
88fn try_into_sequence_length(len: usize) -> Result<u128, Error> {
89    u128::try_from(len)
90        .ok()
91        .ok_or(Error::SequenceLengthTooLarge)
92}
93
94impl<'a, T: Update> Serializer for HashingSerializer<'a, T> {
95    type Ok = ();
96    type Error = Error;
97    type SerializeSeq = Self;
98    type SerializeTuple = Self;
99    type SerializeTupleStruct = Self;
100    type SerializeTupleVariant = Self;
101    type SerializeMap = Self;
102    type SerializeStruct = Self;
103    type SerializeStructVariant = Self;
104
105    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
106        self.digest.update(&(v as u8).to_be_bytes());
107        Ok(())
108    }
109
110    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
111        self.digest.update(&v.to_be_bytes());
112        Ok(())
113    }
114
115    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
116        self.digest.update(&v.to_be_bytes());
117        Ok(())
118    }
119
120    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
121        self.digest.update(&v.to_be_bytes());
122        Ok(())
123    }
124
125    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
126        self.digest.update(&v.to_be_bytes());
127        Ok(())
128    }
129
130    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
131        self.digest.update(&v.to_be_bytes());
132        Ok(())
133    }
134
135    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
136        self.digest.update(&v.to_be_bytes());
137        Ok(())
138    }
139
140    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
141        self.digest.update(&v.to_be_bytes());
142        Ok(())
143    }
144
145    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
146        self.digest.update(&v.to_be_bytes());
147        Ok(())
148    }
149
150    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
151        self.digest.update(&v.to_be_bytes());
152        Ok(())
153    }
154
155    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
156        self.digest.update(&v.to_be_bytes());
157        Ok(())
158    }
159    fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
160        // `char` is always at most 4 bytes, regardless of the platform,
161        // so this conversion is safe.
162        self.digest.update(&u64::from(v).to_be_bytes());
163        Ok(())
164    }
165
166    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
167        self.digest.update(v.as_ref());
168        Ok(())
169    }
170
171    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
172        self.digest.update(v);
173        Ok(())
174    }
175
176    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
177        self.digest.update(&[0]);
178        Ok(())
179    }
180
181    fn serialize_some<V: ?Sized + Serialize>(self, value: &V) -> Result<Self::Ok, Self::Error> {
182        self.digest.update(&[1]);
183        value.serialize(self)
184    }
185
186    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
187        Ok(())
188    }
189
190    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
191        Ok(())
192    }
193
194    fn serialize_unit_variant(
195        self,
196        _name: &'static str,
197        variant_index: u32,
198        _variant: &'static str,
199    ) -> Result<Self::Ok, Self::Error> {
200        self.digest.update(&variant_index.to_be_bytes());
201        Ok(())
202    }
203
204    fn serialize_newtype_struct<V: ?Sized + Serialize>(
205        self,
206        _name: &'static str,
207        value: &V,
208    ) -> Result<Self::Ok, Self::Error> {
209        value.serialize(self)
210    }
211
212    fn serialize_newtype_variant<V: ?Sized + Serialize>(
213        self,
214        _name: &'static str,
215        variant_index: u32,
216        _variant: &'static str,
217        value: &V,
218    ) -> Result<Self::Ok, Self::Error> {
219        self.digest.update(&variant_index.to_be_bytes());
220        value.serialize(self)
221    }
222
223    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
224        let len = len.ok_or(Error::UndefinedSequenceLength)?;
225        self.digest
226            .update(&try_into_sequence_length(len)?.to_be_bytes());
227        Ok(self)
228    }
229
230    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
231        self.digest
232            .update(&try_into_sequence_length(len)?.to_be_bytes());
233        Ok(self)
234    }
235
236    fn serialize_tuple_struct(
237        self,
238        _name: &'static str,
239        len: usize,
240    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
241        self.digest
242            .update(&try_into_sequence_length(len)?.to_be_bytes());
243        Ok(self)
244    }
245
246    fn serialize_tuple_variant(
247        self,
248        _name: &'static str,
249        variant_index: u32,
250        _variant: &'static str,
251        len: usize,
252    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
253        self.digest.update(&variant_index.to_be_bytes());
254        self.digest
255            .update(&try_into_sequence_length(len)?.to_be_bytes());
256        Ok(self)
257    }
258
259    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
260        let len = len.ok_or(Error::UndefinedSequenceLength)?;
261        self.digest
262            .update(&try_into_sequence_length(len)?.to_be_bytes());
263        Ok(self)
264    }
265
266    fn serialize_struct(
267        self,
268        _name: &'static str,
269        len: usize,
270    ) -> Result<Self::SerializeStruct, Self::Error> {
271        self.digest
272            .update(&try_into_sequence_length(len)?.to_be_bytes());
273        Ok(self)
274    }
275
276    fn serialize_struct_variant(
277        self,
278        _name: &'static str,
279        variant_index: u32,
280        _variant: &'static str,
281        len: usize,
282    ) -> Result<Self::SerializeStructVariant, Self::Error> {
283        self.digest.update(&variant_index.to_be_bytes());
284        self.digest
285            .update(&try_into_sequence_length(len)?.to_be_bytes());
286        Ok(self)
287    }
288
289    #[cfg(not(feature = "alloc"))]
290    fn collect_str<V: fmt::Display + ?Sized>(self, _: &V) -> Result<Self::Ok, Self::Error> {
291        Err(Error::CannotCollectStr)
292    }
293
294    fn is_human_readable(&self) -> bool {
295        false
296    }
297}
298
299impl<'a, T: Update> SerializeSeq for HashingSerializer<'a, T> {
300    type Ok = ();
301    type Error = Error;
302
303    fn serialize_element<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
304        value.serialize(HashingSerializer {
305            digest: self.digest,
306        })?;
307        Ok(())
308    }
309
310    fn end(self) -> Result<Self::Ok, Error> {
311        Ok(())
312    }
313}
314
315impl<'a, T: Update> SerializeTuple for HashingSerializer<'a, T> {
316    type Ok = ();
317    type Error = Error;
318
319    fn serialize_element<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
320        value.serialize(HashingSerializer {
321            digest: self.digest,
322        })?;
323        Ok(())
324    }
325
326    fn end(self) -> Result<Self::Ok, Error> {
327        Ok(())
328    }
329}
330
331impl<'a, T: Update> SerializeTupleStruct for HashingSerializer<'a, T> {
332    type Ok = ();
333    type Error = Error;
334
335    fn serialize_field<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
336        value.serialize(HashingSerializer {
337            digest: self.digest,
338        })?;
339        Ok(())
340    }
341
342    fn end(self) -> Result<Self::Ok, Error> {
343        Ok(())
344    }
345}
346
347impl<'a, T: Update> SerializeTupleVariant for HashingSerializer<'a, T> {
348    type Ok = ();
349    type Error = Error;
350
351    fn serialize_field<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
352        value.serialize(HashingSerializer {
353            digest: self.digest,
354        })?;
355        Ok(())
356    }
357
358    fn end(self) -> Result<Self::Ok, Error> {
359        Ok(())
360    }
361}
362
363impl<'a, T: Update> SerializeMap for HashingSerializer<'a, T> {
364    type Ok = ();
365    type Error = Error;
366
367    fn serialize_key<K: ?Sized + Serialize>(&mut self, key: &K) -> Result<Self::Ok, Error> {
368        key.serialize(HashingSerializer {
369            digest: self.digest,
370        })?;
371        Ok(())
372    }
373
374    fn serialize_value<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
375        value.serialize(HashingSerializer {
376            digest: self.digest,
377        })?;
378        Ok(())
379    }
380
381    fn end(self) -> Result<Self::Ok, Error> {
382        Ok(())
383    }
384}
385
386impl<'a, T: Update> SerializeStruct for HashingSerializer<'a, T> {
387    type Ok = ();
388    type Error = Error;
389
390    fn serialize_field<V: ?Sized + Serialize>(
391        &mut self,
392        _key: &'static str,
393        value: &V,
394    ) -> Result<Self::Ok, Error> {
395        value.serialize(HashingSerializer {
396            digest: self.digest,
397        })?;
398        Ok(())
399    }
400
401    fn end(self) -> Result<Self::Ok, Error> {
402        Ok(())
403    }
404}
405
406impl<'a, T: Update> SerializeStructVariant for HashingSerializer<'a, T> {
407    type Ok = ();
408    type Error = Error;
409
410    fn serialize_field<V: ?Sized + Serialize>(
411        &mut self,
412        _key: &'static str,
413        value: &V,
414    ) -> Result<Self::Ok, Error> {
415        value.serialize(HashingSerializer {
416            digest: self.digest,
417        })?;
418        Ok(())
419    }
420
421    fn end(self) -> Result<Self::Ok, Error> {
422        Ok(())
423    }
424}
425
426#[cfg(test)]
427#[allow(clippy::unwrap_used)]
428mod tests {
429    use digest::Digest;
430    use k256::ecdsa::SigningKey;
431    use rand_core::OsRng;
432    use serde::Serialize;
433    use sha2::Sha256;
434
435    use super::HashingSerializer;
436
437    #[test]
438    fn hash_serializable() {
439        let sk = SigningKey::random(&mut OsRng);
440        let vk = sk.verifying_key();
441
442        let mut digest = Sha256::new();
443        let serializer = HashingSerializer {
444            digest: &mut digest,
445        };
446        vk.serialize(serializer).unwrap();
447    }
448}