Skip to main content

frost_core/
serialization.rs

1//! Serialization support.
2
3#[cfg(feature = "serde")]
4use alloc::collections::BTreeMap;
5use alloc::vec::Vec;
6#[cfg(feature = "serde")]
7use core::fmt::Formatter;
8#[cfg(feature = "serde")]
9use core::marker::PhantomData;
10use zeroize::Zeroize;
11
12#[cfg(feature = "serde")]
13use crate::keys::PublicKeyPackage;
14#[cfg(feature = "serde")]
15use crate::keys::VerifyingShare;
16use crate::{Ciphersuite, FieldError};
17#[cfg(feature = "serde")]
18use crate::{Header, Identifier, VerifyingKey};
19
20use crate::{Element, Error, Field, Group};
21
22#[derive(Clone, Copy, PartialEq, Eq)]
23#[cfg_attr(feature = "internals", visibility::make(pub))]
24#[cfg_attr(docsrs, doc(cfg(feature = "internals")))]
25/// Helper struct to serialize a Scalar.
26pub(crate) struct SerializableScalar<C: Ciphersuite>(
27    pub <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar,
28);
29
30impl<C> SerializableScalar<C>
31where
32    C: Ciphersuite,
33{
34    /// Serialize a Scalar.
35    pub fn serialize(&self) -> Vec<u8> {
36        <<C::Group as Group>::Field>::serialize(&self.0)
37            .as_ref()
38            .to_vec()
39    }
40
41    /// Deserialize a Scalar from a serialized buffer.
42    pub fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>> {
43        let serialized: <<C::Group as Group>::Field as Field>::Serialization =
44            bytes.try_into().map_err(|_| FieldError::MalformedScalar)?;
45        let scalar = <<C::Group as Group>::Field>::deserialize(&serialized)?;
46        Ok(Self(scalar))
47    }
48}
49
50impl<C> Zeroize for SerializableScalar<C>
51where
52    C: Ciphersuite,
53{
54    fn zeroize(&mut self) {
55        self.0 = <<C::Group as Group>::Field as Field>::zero();
56    }
57}
58
59#[cfg(feature = "serde")]
60impl<C> serde::Serialize for SerializableScalar<C>
61where
62    C: Ciphersuite,
63{
64    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65    where
66        S: serde::Serializer,
67    {
68        let serialized = <<C as Ciphersuite>::Group as Group>::Field::serialize(&self.0);
69        serdect::array::serialize_hex_lower_or_bin(&serialized.as_ref(), serializer)
70    }
71}
72
73#[cfg(feature = "serde")]
74impl<'de, C> serde::Deserialize<'de> for SerializableScalar<C>
75where
76    C: Ciphersuite,
77{
78    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79    where
80        D: serde::Deserializer<'de>,
81    {
82        // Get serialization buffer from the zero scalar
83        let zero = <<C::Group as Group>::Field as Field>::zero();
84        let mut serialization = <<C::Group as Group>::Field as Field>::serialize(&zero);
85
86        serdect::array::deserialize_hex_or_bin(serialization.as_mut(), deserializer)?;
87
88        <<C as Ciphersuite>::Group as Group>::Field::deserialize(&serialization)
89            .map(|scalar| Self(scalar))
90            .map_err(serde::de::Error::custom)
91    }
92}
93
94#[derive(Clone, Copy, PartialEq, Eq)]
95pub(crate) struct SerializableElement<C: Ciphersuite>(pub(crate) Element<C>);
96
97impl<C> SerializableElement<C>
98where
99    C: Ciphersuite,
100{
101    /// Serialize an Element. Returns an error if it's the identity.
102    pub fn serialize(&self) -> Result<Vec<u8>, Error<C>> {
103        Ok(<C::Group as Group>::serialize(&self.0)?.as_ref().to_vec())
104    }
105
106    /// Deserialize an Element. Returns an error if it's malformed or is the
107    /// identity.
108    pub fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>> {
109        let serialized: <C::Group as Group>::Serialization =
110            bytes.try_into().map_err(|_| FieldError::MalformedScalar)?;
111        let scalar = <C::Group as Group>::deserialize(&serialized)?;
112        Ok(Self(scalar))
113    }
114}
115
116#[cfg(feature = "serde")]
117impl<C> serde::Serialize for SerializableElement<C>
118where
119    C: Ciphersuite,
120{
121    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122    where
123        S: serde::Serializer,
124    {
125        let serialized =
126            <C::Group as Group>::serialize(&self.0).map_err(serde::ser::Error::custom)?;
127        serdect::array::serialize_hex_lower_or_bin(&serialized.as_ref(), serializer)
128    }
129}
130
131#[cfg(feature = "serde")]
132impl<'de, C> serde::Deserialize<'de> for SerializableElement<C>
133where
134    C: Ciphersuite,
135{
136    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
137    where
138        D: serde::Deserializer<'de>,
139    {
140        // Get serialization buffer from the generator
141        let generator = <C::Group>::generator();
142        let mut serialization =
143            <C::Group>::serialize(&generator).expect("serializing the generator always works");
144
145        serdect::array::deserialize_hex_or_bin(serialization.as_mut(), deserializer)?;
146
147        <C::Group as Group>::deserialize(&serialization)
148            .map(|element| Self(element))
149            .map_err(serde::de::Error::custom)
150    }
151}
152
153// The short 4-byte ID. Derived as the CRC-32 of the UTF-8
154// encoded ID in big endian format.
155#[cfg(feature = "serde")]
156const fn short_id<C>() -> [u8; 4]
157where
158    C: Ciphersuite,
159{
160    const_crc32::crc32(C::ID.as_bytes()).to_be_bytes()
161}
162
163/// Serialize a placeholder ciphersuite field with the ciphersuite ID string.
164#[cfg(feature = "serde")]
165pub(crate) fn ciphersuite_serialize<S, C>(_: &(), s: S) -> Result<S::Ok, S::Error>
166where
167    S: serde::Serializer,
168    C: Ciphersuite,
169{
170    use serde::Serialize;
171
172    if s.is_human_readable() {
173        C::ID.serialize(s)
174    } else {
175        serde::Serialize::serialize(&short_id::<C>(), s)
176    }
177}
178
179/// Deserialize a placeholder ciphersuite field, checking if it's the ciphersuite ID string.
180#[cfg(feature = "serde")]
181pub(crate) fn ciphersuite_deserialize<'de, D, C>(deserializer: D) -> Result<(), D::Error>
182where
183    D: serde::Deserializer<'de>,
184    C: Ciphersuite,
185{
186    if deserializer.is_human_readable() {
187        let s: alloc::string::String = serde::de::Deserialize::deserialize(deserializer)?;
188        if s != C::ID {
189            Err(serde::de::Error::custom("wrong ciphersuite"))
190        } else {
191            Ok(())
192        }
193    } else {
194        let buffer: [u8; 4] = serde::de::Deserialize::deserialize(deserializer)?;
195        if buffer != short_id::<C>() {
196            Err(serde::de::Error::custom("wrong ciphersuite"))
197        } else {
198            Ok(())
199        }
200    }
201}
202
203/// Deserialize a version. For now, since there is a single version 0,
204/// simply validate if it's 0.
205#[cfg(feature = "serde")]
206pub(crate) fn version_deserialize<'de, D>(deserializer: D) -> Result<u8, D::Error>
207where
208    D: serde::Deserializer<'de>,
209{
210    let version: u8 = serde::de::Deserialize::deserialize(deserializer)?;
211    if version != 0 {
212        Err(serde::de::Error::custom(
213            "wrong format version, only 0 supported",
214        ))
215    } else {
216        Ok(version)
217    }
218}
219
220// Default byte-oriented serialization for structs that need to be communicated.
221//
222// Note that we still manually implement these methods in each applicable type,
223// instead of making these traits `pub` and asking users to import the traits.
224// The reason is that ciphersuite traits would need to re-export these traits,
225// parametrized with the ciphersuite, but trait aliases are not currently
226// supported: <https://github.com/rust-lang/rust/issues/41517>
227
228#[cfg(feature = "serialization")]
229pub(crate) trait Serialize<C: Ciphersuite> {
230    /// Serialize the struct into a Vec.
231    fn serialize(&self) -> Result<Vec<u8>, Error<C>>;
232}
233
234#[cfg(feature = "serialization")]
235pub(crate) trait Deserialize<C: Ciphersuite> {
236    /// Deserialize the struct from a slice of bytes.
237    fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>>
238    where
239        Self: core::marker::Sized;
240}
241
242#[cfg(feature = "serialization")]
243impl<T: serde::Serialize, C: Ciphersuite> Serialize<C> for T {
244    fn serialize(&self) -> Result<Vec<u8>, Error<C>> {
245        postcard::to_allocvec(self).map_err(|_| Error::SerializationError)
246    }
247}
248
249#[cfg(feature = "serialization")]
250impl<T: for<'de> serde::Deserialize<'de>, C: Ciphersuite> Deserialize<C> for T {
251    fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>> {
252        postcard::from_bytes(bytes).map_err(|_| Error::DeserializationError)
253    }
254}
255
256/// Custom deserializer for PublicKeyPackage, which allows a non-existing
257/// `min_signers` field for the `postcard` encoding.
258#[cfg(feature = "serde")]
259impl<'de, C: Ciphersuite> serde::Deserialize<'de> for PublicKeyPackage<C>
260where
261    C: Ciphersuite,
262{
263    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
264    where
265        D: serde::Deserializer<'de>,
266    {
267        use core::fmt;
268
269        // The following are copied from the `serde::Deserialize` derive, and
270        // are required to support `visit_map()` which in turn is required for
271        // `serde_json`.
272
273        enum Field {
274            Field0,
275            Field1,
276            Field2,
277            Field3,
278        }
279
280        struct FieldVisitor;
281
282        impl<'de> serde::de::Visitor<'de> for FieldVisitor {
283            type Value = Field;
284
285            fn expecting(&self, __formatter: &mut Formatter) -> fmt::Result {
286                Formatter::write_str(__formatter, "field identifier")
287            }
288
289            fn visit_u64<__E>(self, __value: u64) -> Result<Self::Value, __E>
290            where
291                __E: serde::de::Error,
292            {
293                match __value {
294                    0u64 => Ok(Field::Field0),
295                    1u64 => Ok(Field::Field1),
296                    2u64 => Ok(Field::Field2),
297                    3u64 => Ok(Field::Field3),
298                    _ => Err(serde::de::Error::invalid_value(
299                        serde::de::Unexpected::Unsigned(__value),
300                        &"field index 0 <= i < 4",
301                    )),
302                }
303            }
304
305            fn visit_str<__E>(self, __value: &str) -> Result<Self::Value, __E>
306            where
307                __E: serde::de::Error,
308            {
309                match __value {
310                    "header" => Ok(Field::Field0),
311                    "verifying_shares" => Ok(Field::Field1),
312                    "verifying_key" => Ok(Field::Field2),
313                    "min_signers" => Ok(Field::Field3),
314                    _ => Err(serde::de::Error::unknown_field(__value, FIELDS)),
315                }
316            }
317
318            fn visit_bytes<__E>(self, __value: &[u8]) -> Result<Self::Value, __E>
319            where
320                __E: serde::de::Error,
321            {
322                match __value {
323                    b"header" => Ok(Field::Field0),
324                    b"verifying_shares" => Ok(Field::Field1),
325                    b"verifying_key" => Ok(Field::Field2),
326                    b"min_signers" => Ok(Field::Field3),
327                    _ => {
328                        let __value = &alloc::string::String::from_utf8_lossy(__value);
329                        Err(serde::de::Error::unknown_field(__value, FIELDS))
330                    }
331                }
332            }
333        }
334
335        impl<'de> serde::Deserialize<'de> for Field {
336            #[inline]
337            fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
338            where
339                __D: serde::Deserializer<'de>,
340            {
341                serde::Deserializer::deserialize_identifier(__deserializer, FieldVisitor)
342            }
343        }
344
345        struct Visitor<C> {
346            marker: PhantomData<C>,
347        }
348
349        impl<'de, C: Ciphersuite> serde::de::Visitor<'de> for Visitor<C>
350        where
351            C: Ciphersuite,
352        {
353            type Value = PublicKeyPackage<C>;
354
355            fn expecting(&self, fmt: &mut Formatter) -> core::fmt::Result {
356                Formatter::write_str(fmt, "struct PublicKeyPackage")
357            }
358
359            // Postcard serializes structs as sequences, so we override
360            // `visit_seq` to deserialize the struct from a sequence of elements.
361            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
362            where
363                A: serde::de::SeqAccess<'de>,
364            {
365                // Read the first three fields as usual.
366
367                let header = seq.next_element::<Header<C>>()?.ok_or_else(|| {
368                    serde::de::Error::invalid_length(
369                        0usize,
370                        &"struct PublicKeyPackage with 4 elements",
371                    )
372                })?;
373                let verifying_shares = seq
374                    .next_element::<BTreeMap<Identifier<C>, VerifyingShare<C>>>()?
375                    .ok_or_else(|| {
376                        serde::de::Error::invalid_length(
377                            1usize,
378                            &"struct PublicKeyPackage with 4 elements",
379                        )
380                    })?;
381                let verifying_key = seq.next_element::<VerifyingKey<C>>()?.ok_or_else(|| {
382                    serde::de::Error::invalid_length(
383                        2usize,
384                        &"struct PublicKeyPackage with 4 elements",
385                    )
386                })?;
387
388                // For the `min_signers` field, fill it with None if
389                // `next_element()` fails (i.e. there are no other elements)
390                let min_signers = match seq.next_element::<Option<u16>>() {
391                    Ok(Some(min_signers)) => min_signers,
392                    _ => None,
393                };
394
395                Ok(PublicKeyPackage {
396                    header,
397                    verifying_shares,
398                    verifying_key,
399                    min_signers,
400                })
401            }
402
403            // Again this is copied from the `serde::Deserialize` derive;
404            // the only change is not requiring `min_signers` to be present.
405            fn visit_map<__A>(self, mut __map: __A) -> Result<Self::Value, __A::Error>
406            where
407                __A: serde::de::MapAccess<'de>,
408            {
409                let mut __field0: Option<Header<C>> = None;
410                let mut __field1: Option<BTreeMap<Identifier<C>, VerifyingShare<C>>> = None;
411                let mut __field2: Option<VerifyingKey<C>> = None;
412                let mut __field3: Option<Option<u16>> = None;
413                while let Some(__key) = serde::de::MapAccess::next_key::<Field>(&mut __map)? {
414                    match __key {
415                        Field::Field0 => {
416                            if Option::is_some(&__field0) {
417                                return Err(<__A::Error as serde::de::Error>::duplicate_field(
418                                    "header",
419                                ));
420                            }
421                            __field0 =
422                                Some(serde::de::MapAccess::next_value::<Header<C>>(&mut __map)?);
423                        }
424                        Field::Field1 => {
425                            if Option::is_some(&__field1) {
426                                return Err(<__A::Error as serde::de::Error>::duplicate_field(
427                                    "verifying_shares",
428                                ));
429                            }
430                            __field1 = Some(serde::de::MapAccess::next_value::<
431                                BTreeMap<Identifier<C>, VerifyingShare<C>>,
432                            >(&mut __map)?);
433                        }
434                        Field::Field2 => {
435                            if Option::is_some(&__field2) {
436                                return Err(<__A::Error as serde::de::Error>::duplicate_field(
437                                    "verifying_key",
438                                ));
439                            }
440                            __field2 = Some(serde::de::MapAccess::next_value::<VerifyingKey<C>>(
441                                &mut __map,
442                            )?);
443                        }
444                        Field::Field3 => {
445                            if Option::is_some(&__field3) {
446                                return Err(<__A::Error as serde::de::Error>::duplicate_field(
447                                    "min_signers",
448                                ));
449                            }
450                            __field3 =
451                                Some(serde::de::MapAccess::next_value::<Option<u16>>(&mut __map)?);
452                        }
453                    }
454                }
455                let __field0 = match __field0 {
456                    Some(__field0) => __field0,
457                    None => Err(<__A::Error as serde::de::Error>::missing_field("header"))?,
458                };
459                let __field1 = match __field1 {
460                    Some(__field1) => __field1,
461                    None => Err(<__A::Error as serde::de::Error>::missing_field(
462                        "verifying_shares",
463                    ))?,
464                };
465                let __field2 = match __field2 {
466                    Some(__field2) => __field2,
467                    None => Err(<__A::Error as serde::de::Error>::missing_field(
468                        "verifying_key",
469                    ))?,
470                };
471                let __field3 = __field3.unwrap_or_default();
472                Ok(PublicKeyPackage {
473                    header: __field0,
474                    verifying_shares: __field1,
475                    verifying_key: __field2,
476                    min_signers: __field3,
477                })
478            }
479        }
480
481        const FIELDS: &[&str] = &["header", "verifying_shares", "verifying_key", "min_signers"];
482        deserializer.deserialize_struct(
483            "PublicKeyPackage",
484            FIELDS,
485            Visitor {
486                marker: PhantomData::<C>,
487            },
488        )
489    }
490}