frost_core/
serialization.rs

1//! Serialization support.
2
3use alloc::vec::Vec;
4
5use crate::{Ciphersuite, FieldError};
6
7use crate::{Element, Error, Field, Group};
8
9#[derive(Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "internals", visibility::make(pub))]
11#[cfg_attr(docsrs, doc(cfg(feature = "internals")))]
12/// Helper struct to serialize a Scalar.
13pub(crate) struct SerializableScalar<C: Ciphersuite>(
14    pub <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar,
15);
16
17impl<C> SerializableScalar<C>
18where
19    C: Ciphersuite,
20{
21    /// Serialize a Scalar.
22    pub fn serialize(&self) -> Vec<u8> {
23        <<C::Group as Group>::Field>::serialize(&self.0)
24            .as_ref()
25            .to_vec()
26    }
27
28    /// Deserialize a Scalar from a serialized buffer.
29    pub fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>> {
30        let serialized: <<C::Group as Group>::Field as Field>::Serialization = bytes
31            .to_vec()
32            .try_into()
33            .map_err(|_| FieldError::MalformedScalar)?;
34        let scalar = <<C::Group as Group>::Field>::deserialize(&serialized)?;
35        Ok(Self(scalar))
36    }
37}
38
39#[cfg(feature = "serde")]
40impl<C> serde::Serialize for SerializableScalar<C>
41where
42    C: Ciphersuite,
43{
44    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45    where
46        S: serde::Serializer,
47    {
48        let serialized = <<C as Ciphersuite>::Group as Group>::Field::serialize(&self.0);
49        serdect::array::serialize_hex_lower_or_bin(&serialized.as_ref(), serializer)
50    }
51}
52
53#[cfg(feature = "serde")]
54impl<'de, C> serde::Deserialize<'de> for SerializableScalar<C>
55where
56    C: Ciphersuite,
57{
58    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
59    where
60        D: serde::Deserializer<'de>,
61    {
62        // Get size from the size of the zero scalar
63        let zero = <<C::Group as Group>::Field as Field>::zero();
64        let len = <<C::Group as Group>::Field as Field>::serialize(&zero)
65            .as_ref()
66            .len();
67
68        let mut bytes = vec![0u8; len];
69        serdect::array::deserialize_hex_or_bin(&mut bytes[..], deserializer)?;
70        let array = bytes
71            .try_into()
72            .map_err(|_| serde::de::Error::custom("invalid byte length"))?;
73        <<C as Ciphersuite>::Group as Group>::Field::deserialize(&array)
74            .map(|scalar| Self(scalar))
75            .map_err(serde::de::Error::custom)
76    }
77}
78
79#[derive(Clone, Copy, PartialEq, Eq)]
80pub(crate) struct SerializableElement<C: Ciphersuite>(pub(crate) Element<C>);
81
82impl<C> SerializableElement<C>
83where
84    C: Ciphersuite,
85{
86    /// Serialize an Element. Returns an error if it's the identity.
87    pub fn serialize(&self) -> Result<Vec<u8>, Error<C>> {
88        Ok(<C::Group as Group>::serialize(&self.0)?.as_ref().to_vec())
89    }
90
91    /// Deserialize an Element. Returns an error if it's malformed or is the
92    /// identity.
93    pub fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>> {
94        let serialized: <C::Group as Group>::Serialization = bytes
95            .to_vec()
96            .try_into()
97            .map_err(|_| FieldError::MalformedScalar)?;
98        let scalar = <C::Group as Group>::deserialize(&serialized)?;
99        Ok(Self(scalar))
100    }
101}
102
103#[cfg(feature = "serde")]
104impl<C> serde::Serialize for SerializableElement<C>
105where
106    C: Ciphersuite,
107{
108    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
109    where
110        S: serde::Serializer,
111    {
112        let serialized =
113            <C::Group as Group>::serialize(&self.0).map_err(serde::ser::Error::custom)?;
114        serdect::array::serialize_hex_lower_or_bin(&serialized.as_ref(), serializer)
115    }
116}
117
118#[cfg(feature = "serde")]
119impl<'de, C> serde::Deserialize<'de> for SerializableElement<C>
120where
121    C: Ciphersuite,
122{
123    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
124    where
125        D: serde::Deserializer<'de>,
126    {
127        // Get size from the size of the generator
128        let generator = <C::Group>::generator();
129        let len = <C::Group>::serialize(&generator)
130            .expect("serializing the generator always works")
131            .as_ref()
132            .len();
133
134        let mut bytes = vec![0u8; len];
135        serdect::array::deserialize_hex_or_bin(&mut bytes[..], deserializer)?;
136        let array = bytes
137            .try_into()
138            .map_err(|_| serde::de::Error::custom("invalid byte length"))?;
139        <C::Group as Group>::deserialize(&array)
140            .map(|element| Self(element))
141            .map_err(serde::de::Error::custom)
142    }
143}
144
145// The short 4-byte ID. Derived as the CRC-32 of the UTF-8
146// encoded ID in big endian format.
147#[cfg(feature = "serde")]
148const fn short_id<C>() -> [u8; 4]
149where
150    C: Ciphersuite,
151{
152    const_crc32::crc32(C::ID.as_bytes()).to_be_bytes()
153}
154
155/// Serialize a placeholder ciphersuite field with the ciphersuite ID string.
156#[cfg(feature = "serde")]
157pub(crate) fn ciphersuite_serialize<S, C>(_: &(), s: S) -> Result<S::Ok, S::Error>
158where
159    S: serde::Serializer,
160    C: Ciphersuite,
161{
162    use serde::Serialize;
163
164    if s.is_human_readable() {
165        C::ID.serialize(s)
166    } else {
167        serde::Serialize::serialize(&short_id::<C>(), s)
168    }
169}
170
171/// Deserialize a placeholder ciphersuite field, checking if it's the ciphersuite ID string.
172#[cfg(feature = "serde")]
173pub(crate) fn ciphersuite_deserialize<'de, D, C>(deserializer: D) -> Result<(), D::Error>
174where
175    D: serde::Deserializer<'de>,
176    C: Ciphersuite,
177{
178    if deserializer.is_human_readable() {
179        let s: alloc::string::String = serde::de::Deserialize::deserialize(deserializer)?;
180        if s != C::ID {
181            Err(serde::de::Error::custom("wrong ciphersuite"))
182        } else {
183            Ok(())
184        }
185    } else {
186        let buffer: [u8; 4] = serde::de::Deserialize::deserialize(deserializer)?;
187        if buffer != short_id::<C>() {
188            Err(serde::de::Error::custom("wrong ciphersuite"))
189        } else {
190            Ok(())
191        }
192    }
193}
194
195/// Deserialize a version. For now, since there is a single version 0,
196/// simply validate if it's 0.
197#[cfg(feature = "serde")]
198pub(crate) fn version_deserialize<'de, D>(deserializer: D) -> Result<u8, D::Error>
199where
200    D: serde::Deserializer<'de>,
201{
202    let version: u8 = serde::de::Deserialize::deserialize(deserializer)?;
203    if version != 0 {
204        Err(serde::de::Error::custom(
205            "wrong format version, only 0 supported",
206        ))
207    } else {
208        Ok(version)
209    }
210}
211
212// Default byte-oriented serialization for structs that need to be communicated.
213//
214// Note that we still manually implement these methods in each applicable type,
215// instead of making these traits `pub` and asking users to import the traits.
216// The reason is that ciphersuite traits would need to re-export these traits,
217// parametrized with the ciphersuite, but trait aliases are not currently
218// supported: <https://github.com/rust-lang/rust/issues/41517>
219
220#[cfg(feature = "serialization")]
221pub(crate) trait Serialize<C: Ciphersuite> {
222    /// Serialize the struct into a Vec.
223    fn serialize(&self) -> Result<Vec<u8>, Error<C>>;
224}
225
226#[cfg(feature = "serialization")]
227pub(crate) trait Deserialize<C: Ciphersuite> {
228    /// Deserialize the struct from a slice of bytes.
229    fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>>
230    where
231        Self: core::marker::Sized;
232}
233
234#[cfg(feature = "serialization")]
235impl<T: serde::Serialize, C: Ciphersuite> Serialize<C> for T {
236    fn serialize(&self) -> Result<Vec<u8>, Error<C>> {
237        postcard::to_allocvec(self).map_err(|_| Error::SerializationError)
238    }
239}
240
241#[cfg(feature = "serialization")]
242impl<T: for<'de> serde::Deserialize<'de>, C: Ciphersuite> Deserialize<C> for T {
243    fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>> {
244        postcard::from_bytes(bytes).map_err(|_| Error::DeserializationError)
245    }
246}