Skip to main content

pg_core/
artifacts.rs

1//! Artifacts of the PostGuard protocol.
2//!
3//! This module implements constant-time serde serialization and deserialization for artifacts.
4//!
5//! # Notes
6//!
7//! Some artifacts do no require serialization to be constant-time, but we want to limit the
8//! dependency graph.
9
10use crate::identity::Policy;
11use crate::util::open_ct;
12use base64ct::{Base64, Encoding};
13use core::fmt;
14use ibe::{
15    kem::{cgw_kv::CGWKV, mkem::Ciphertext as MkemCt, IBKEM},
16    Compress,
17};
18use serde::de::{Error, SeqAccess, Visitor};
19use serde::{ser::SerializeTuple, Deserialize, Deserializer, Serialize, Serializer};
20
21// Computes the byte length of raw bytes encoded in (padded) b64.
22// We use this to preallocate a buffer to encode into.
23const fn b64len(raw_len: usize) -> usize {
24    // use next line when unwrap() becomes stable as a const fn:
25    // .checked_mul(4).unwrap()
26    // this will cause a compiler error when the multiplication overflows,
27    // making this function "safe" for all input.
28    (((raw_len - 1) / 3) + 1) * 4
29}
30
31pub(crate) fn serialize_bin_or_b64<S, T>(val: &T, serializer: S) -> Result<S::Ok, S::Error>
32where
33    S: Serializer,
34    T: AsRef<[u8]>,
35{
36    if serializer.is_human_readable() {
37        let mut enc_buf = vec![0u8; b64len(val.as_ref().len())];
38        let encoded = Base64::encode(val.as_ref(), &mut enc_buf)
39            .map_err(|e| serde::ser::Error::custom(format!("base64ct serialization error: {e}")))?;
40        serializer.serialize_str(encoded)
41    } else {
42        let mut seq = serializer.serialize_tuple(val.as_ref().len())?;
43        for b in val.as_ref() {
44            seq.serialize_element(b)?;
45        }
46        seq.end()
47    }
48}
49
50pub(crate) fn deserialize_bin_or_b64<'de, D: Deserializer<'de>>(
51    buf: &mut [u8],
52    deserializer: D,
53) -> Result<(), D::Error> {
54    if deserializer.is_human_readable() {
55        struct StrVisitor<'b>(&'b mut [u8]);
56
57        impl<'de> Visitor<'de> for StrVisitor<'_> {
58            type Value = ();
59
60            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
61                write!(formatter, "a string of length {}", b64len(self.0.len()))
62            }
63
64            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
65            where
66                E: Error,
67            {
68                if v.len() != b64len(self.0.len()) {
69                    return Err(Error::invalid_length(v.len(), &self));
70                }
71
72                Base64::decode(v, self.0).map_err(|e| {
73                    serde::de::Error::custom(format!("base64ct decoding error: {e}"))
74                })?;
75
76                Ok(())
77            }
78        }
79
80        deserializer.deserialize_str(StrVisitor(buf))
81    } else {
82        struct ArrayVisitor<'b>(&'b mut [u8]);
83
84        impl<'de> Visitor<'de> for ArrayVisitor<'_> {
85            type Value = ();
86
87            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
88                write!(formatter, "an array of length {}", self.0.len())
89            }
90
91            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
92            where
93                A: SeqAccess<'de>,
94            {
95                for (index, byte) in self.0.iter_mut().enumerate() {
96                    *byte = match seq.next_element()? {
97                        Some(byte) => byte,
98                        None => return Err(Error::invalid_length(index, &self)),
99                    };
100                }
101
102                Ok(())
103            }
104        }
105
106        deserializer.deserialize_tuple(buf.len(), ArrayVisitor(buf))
107    }
108}
109
110/// Master public keys.
111#[derive(Debug, Clone, Copy)]
112pub struct PublicKey<K: IBKEM>(pub K::Pk);
113
114/// Secret keys.
115#[derive(Debug, Clone, Copy)]
116pub struct SecretKey<K: IBKEM>(pub K::Sk);
117
118/// User secret keys.
119#[derive(Debug, Clone)]
120pub struct UserSecretKey<K: IBKEM>(pub K::Usk);
121
122/// Ciphertexts.
123#[derive(Debug, Clone)]
124pub struct Ciphertext<K: IBKEM>(pub K::Ct);
125
126/// Multi-recipient ciphertexts.
127#[derive(Debug, Clone)]
128pub struct MultiRecipientCiphertext<K: IBKEM>(pub MkemCt<K>);
129
130// Note:
131// We cannot make these implementations generic over the scheme parameter because of a constant
132// expression depending on a generic parameter, see https://github.com/rust-lang/rust/issues/68436.
133// For now, the solutions are these deserialize impl macros, creating encoding/decoding buffer for
134// each scheme specifically.
135
136/// Implements [`serde::ser::Serialize`] and [`serde::de::Deserialize`] for encapsulation wrapper types.
137macro_rules! impl_serialize {
138    ($type: ty, $inner: ty) => {
139        impl Serialize for $type {
140            fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
141                serialize_bin_or_b64(&self.0.to_bytes(), serializer)
142            }
143        }
144
145        impl<'de> Deserialize<'de> for $type {
146            fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
147                let mut buf = [0u8; <$inner as Compress>::OUTPUT_SIZE];
148                deserialize_bin_or_b64(&mut buf, deserializer)?;
149
150                let artifact = open_ct(<$inner as Compress>::from_bytes(&buf)).ok_or(
151                    serde::de::Error::custom(format!("not a valid {}", stringify!($type))),
152                )?;
153
154                Ok(Self(artifact))
155            }
156        }
157    };
158}
159
160impl_serialize!(PublicKey<CGWKV>, <CGWKV as IBKEM>::Pk);
161impl_serialize!(SecretKey<CGWKV>, <CGWKV as IBKEM>::Sk);
162impl_serialize!(UserSecretKey<CGWKV>, <CGWKV as IBKEM>::Usk);
163impl_serialize!(Ciphertext<CGWKV>, <CGWKV as IBKEM>::Ct);
164impl_serialize!(MultiRecipientCiphertext<CGWKV>, MkemCt<CGWKV>);
165
166/// Identity-based signing key including its claims.
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct SigningKeyExt {
169    /// The signing key.
170    pub key: SigningKey,
171
172    /// The [`Policy`] associated with this signing key.
173    ///
174    /// The timestamp represents the issuing time by the PKG.
175    /// The identity is the identity for whom the key is issued.
176    pub policy: Policy,
177}
178
179/// Identity-based signing keys.
180#[derive(Debug, Clone)]
181pub struct SigningKey(pub ibs::gg::UserSecretKey);
182
183impl Serialize for SigningKey {
184    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185    where
186        S: Serializer,
187    {
188        let bytes = crate::bincode_compat::serialize(&self.0).map_err(|e| {
189            serde::ser::Error::custom(format!("could not serialize signing key: {e}"))
190        })?;
191
192        debug_assert_eq!(bytes.len(), ibs::gg::USK_BYTES);
193
194        serialize_bin_or_b64(&bytes, serializer)
195    }
196}
197
198impl<'de> Deserialize<'de> for SigningKey {
199    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
200        let mut buf = [0u8; ibs::gg::USK_BYTES];
201        deserialize_bin_or_b64(&mut buf, deserializer)?;
202
203        let usk = crate::bincode_compat::deserialize(&buf).map_err(|e| {
204            serde::de::Error::custom(format!("could not deserialize signing key: {e}"))
205        })?;
206
207        Ok(SigningKey(usk))
208    }
209}
210
211/// Identity-based public master key (signing).
212#[doc(hidden)]
213#[derive(Debug, Clone)]
214pub struct VerifyingKey(pub ibs::gg::PublicKey);
215
216impl Serialize for VerifyingKey {
217    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
218    where
219        S: Serializer,
220    {
221        let bytes = crate::bincode_compat::serialize(&self.0).map_err(|e| {
222            serde::ser::Error::custom(format!("could not serialize public key: {e}"))
223        })?;
224
225        debug_assert_eq!(bytes.len(), ibs::gg::PK_BYTES);
226
227        serialize_bin_or_b64(&bytes, serializer)
228    }
229}
230
231impl<'de> Deserialize<'de> for VerifyingKey {
232    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
233        let mut buf = [0u8; ibs::gg::PK_BYTES];
234        deserialize_bin_or_b64(&mut buf, deserializer)?;
235
236        let pk: ibs::gg::PublicKey = crate::bincode_compat::deserialize(&buf).map_err(|e| {
237            serde::de::Error::custom(format!("could not deserialize public key: {e}"))
238        })?;
239
240        Ok(VerifyingKey(pk))
241    }
242}
243
244#[cfg(test)]
245mod tests {
246    mod kem {
247        use super::super::*;
248        use alloc::vec::Vec;
249        use ibe::kem::mkem::MultiRecipient;
250        use ibe::Derive;
251
252        struct KEMSetup<K: IBKEM> {
253            pk: K::Pk,
254            sk: K::Sk,
255            ct: K::Ct,
256            usk: K::Usk,
257            mct: MkemCt<K>,
258        }
259
260        fn default_encryption_setup<K>() -> KEMSetup<K>
261        where
262            K: IBKEM,
263            K: MultiRecipient,
264        {
265            let mut rng = rand::thread_rng();
266            let (pk, sk) = K::setup(&mut rng);
267            let id1 = <K as IBKEM>::Id::derive_str("test1");
268            let id2 = <K as IBKEM>::Id::derive_str("test2");
269            let usk = K::extract_usk(Some(&pk), &sk, &id1, &mut rng);
270            let (ct, _) = K::encaps(&pk, &id1, &mut rng);
271            let ids = [id1, id2];
272            let (cts, _) = K::multi_encaps(&pk, &ids, &mut rng);
273            let mcts: Vec<MkemCt<K>> = cts.collect();
274            let mct = mcts[0].clone();
275
276            KEMSetup {
277                pk,
278                sk,
279                ct,
280                usk,
281                mct,
282            }
283        }
284
285        #[test]
286        fn test_serialize_pk_json() {
287            let KEMSetup { pk, .. } = default_encryption_setup::<CGWKV>();
288
289            let wrapped_pk = PublicKey::<CGWKV>(pk);
290            let pk_encoded = serde_json::to_string(&wrapped_pk).unwrap();
291            let pk_decoded: PublicKey<CGWKV> = serde_json::from_str(&pk_encoded).unwrap();
292
293            assert_eq!(&wrapped_pk.0, &pk_decoded.0);
294        }
295
296        #[test]
297        fn test_serialize_sk_json() {
298            let KEMSetup { sk, .. } = default_encryption_setup::<CGWKV>();
299
300            let wrapped_sk = SecretKey::<CGWKV>(sk);
301            let sk_encoded = serde_json::to_string(&wrapped_sk).unwrap();
302            let sk_decoded: SecretKey<CGWKV> = serde_json::from_str(&sk_encoded).unwrap();
303
304            assert_eq!(&wrapped_sk.0, &sk_decoded.0);
305        }
306
307        #[test]
308        fn test_serialize_usk_json() {
309            let KEMSetup { usk, .. } = default_encryption_setup::<CGWKV>();
310
311            let wrapped_usk = UserSecretKey::<CGWKV>(usk);
312            let usk_encoded = serde_json::to_string(&wrapped_usk).unwrap();
313            let usk_decoded: UserSecretKey<CGWKV> = serde_json::from_str(&usk_encoded).unwrap();
314
315            assert_eq!(&wrapped_usk.0, &usk_decoded.0);
316        }
317
318        #[test]
319        fn test_serialize_ct_json() {
320            let KEMSetup { ct, .. } = default_encryption_setup::<CGWKV>();
321
322            let wrapped_ct = Ciphertext::<CGWKV>(ct);
323            let ct_encoded = serde_json::to_string(&wrapped_ct).unwrap();
324            let ct_decoded: Ciphertext<CGWKV> = serde_json::from_str(&ct_encoded).unwrap();
325
326            assert_eq!(&wrapped_ct.0, &ct_decoded.0);
327        }
328
329        #[test]
330        fn test_serialize_mkemct_json() {
331            let KEMSetup { mct, .. } = default_encryption_setup::<CGWKV>();
332
333            let wrapped_mct = MultiRecipientCiphertext::<CGWKV>(mct);
334            let mct_encoded = serde_json::to_string(&wrapped_mct).unwrap();
335            let mct_decoded: MultiRecipientCiphertext<CGWKV> =
336                serde_json::from_str(&mct_encoded).unwrap();
337
338            assert_eq!(&wrapped_mct.0.to_bytes(), &mct_decoded.0.to_bytes());
339        }
340
341        #[test]
342        fn test_serialize_pk_bin() {
343            let KEMSetup { pk, .. } = default_encryption_setup::<CGWKV>();
344
345            let wrapped_pk = PublicKey::<CGWKV>(pk);
346            let pk_encoded = crate::bincode_compat::serialize(&wrapped_pk).unwrap();
347            let pk_decoded: PublicKey<CGWKV> =
348                crate::bincode_compat::deserialize(&pk_encoded[..]).unwrap();
349
350            assert_eq!(&wrapped_pk.0, &pk_decoded.0);
351        }
352
353        #[test]
354        fn test_serialize_sk_bin() {
355            let KEMSetup { sk, .. } = default_encryption_setup::<CGWKV>();
356
357            let wrapped_sk = SecretKey::<CGWKV>(sk);
358            let sk_encoded = crate::bincode_compat::serialize(&wrapped_sk).unwrap();
359            let sk_decoded: SecretKey<CGWKV> =
360                crate::bincode_compat::deserialize(&sk_encoded[..]).unwrap();
361
362            assert_eq!(&wrapped_sk.0, &sk_decoded.0);
363        }
364
365        #[test]
366        fn test_serialize_usk_bin() {
367            let KEMSetup { usk, .. } = default_encryption_setup::<CGWKV>();
368
369            let wrapped_usk = UserSecretKey::<CGWKV>(usk);
370            let usk_encoded = crate::bincode_compat::serialize(&wrapped_usk).unwrap();
371            let usk_decoded: UserSecretKey<CGWKV> =
372                crate::bincode_compat::deserialize(&usk_encoded[..]).unwrap();
373
374            assert_eq!(&wrapped_usk.0, &usk_decoded.0);
375        }
376
377        #[test]
378        fn test_serialize_ct_bin() {
379            let KEMSetup { ct, .. } = default_encryption_setup::<CGWKV>();
380
381            let wrapped_ct = Ciphertext::<CGWKV>(ct);
382            let ct_encoded = crate::bincode_compat::serialize(&wrapped_ct).unwrap();
383            let ct_decoded: Ciphertext<CGWKV> =
384                crate::bincode_compat::deserialize(&ct_encoded[..]).unwrap();
385
386            assert_eq!(&wrapped_ct.0, &ct_decoded.0);
387        }
388
389        #[test]
390        fn test_serialize_mkemct_bin() {
391            let KEMSetup { mct, .. } = default_encryption_setup::<CGWKV>();
392
393            let wrapped_mct = MultiRecipientCiphertext::<CGWKV>(mct);
394            let mct_encoded = crate::bincode_compat::serialize(&wrapped_mct).unwrap();
395            let mct_decoded: MultiRecipientCiphertext<CGWKV> =
396                crate::bincode_compat::deserialize(&mct_encoded).unwrap();
397
398            assert_eq!(&wrapped_mct.0.to_bytes(), &mct_decoded.0.to_bytes());
399        }
400
401        #[test]
402        fn test_kem_regression_json() {
403            let pk ="\"g2sPj5dg1SH15TwQ9k0YsFrpUJbLgxK67mGezYZeB6Zl22AnTnkmHVXv06E44Ev1qd4nsj6SK3l6O21N/J/0/zM36vZhEF56/Kyt2qd93ovZJHqPqCMmYY3pi2d2DP9vt9w/Y0T7LXOKJZLzFzyoXR+ca/quRbQrJRrvz1YZdz36ehJ1CFO63HbqZhUIE21XjL9KKdx3S91cclj337f/FXNF5uPb+6E/6oKh0VniGPArspFhQ5ca/h+k6DsVgpYXgRohU5jqT3FYtx82OewAMo+GGUEmejGgnJwF/V69y6tH16ohZ24RVetn8F8qKkeYhLfMmnWIsjAoD/TIkznRyuQOBhR6bQhNdFP3WM2Z6a6bt/y8NVqDgGhr+hBrD8los9RZAlMlNYLHQgxiSuj3k84FHdX22QpEiUpXWJttwmzLKJyP1lhhmO98+T5Em347hsvLellKAEUABl3lr+Z5Pu6/RKz0ZOsD3fxeGzbPDtxuzqc3uXbrMe0jpG5kwR8B1lLaSs/aychKaSJ5znt9zllzzXjPIuE/+UTXcjmYmO837UVMajj5pZrPOcuf9mLEBoq82irr21UBzHJawgNAStpdWVz5Ie22dDKytdeJv1S1Se4tiZfbJTpRM0FmIX8ZEyfXwehUWFS5GCnwkwkhWyzWMGeDXb2AT+OLDSH7MqWneh2KqjtW6bBEs0XcyvSLEtApi/NDfJk3OZ0/SAJb3tH2c7HN1X0l+HJxuHtT1sDzg3JVizwJwd53mKwgFAnWDkYRScKdAEv+EM0upC5YVhnUYYLfJ8YhC8RTU4W5cvg7Q9rfKonDmZLnJTr2aRo3D9CpfjUffuxBUoARSwJlH14KlI0Id91I8z/Fy1jo22x1dP7gHSl/fto+tGnbpYvj\"";
404            let sk = "\"im1K0e1zoEmOoBtWEhMEFbK7BiQrGYh37ua2FX/bCg+cNyUEsE0ObpqZQG5t4ZAFFMsOR/f2HgLGZRbhHdXLCSIxJ5NzjtVUT5KQrbu81D9n/jUOWF47Mp5Sp+b9WzJiVWaakn7j7HuRH4uRJJTg69W+fhBj8eJFoFJL0FEGLgpyiLR1OTLSN6hrxJxQhfGkOvSAPocMw5SNGdtDS+8MDbnuK5+P/bKlTNgg0Tn5sw0wnQ5hluc4flkrcWv+E0wR98sPiRbpLK5qFYmcttzrafpbacj4RwolTrkr0fgdVzBpVhODC0WmFV07ml8t+Q8l3TBmXuZQNF2hF51d1+LabvEToP+g7NHdYoqw4cqw/7hziz52k3HYQ/oICYL/7mAs1kZxbbxtLRK3/FqleG9RrjFkerfV0P47MKNuOlX5Fl97+3/vu47MKVBGJIDUPeh/jKEczw3Pc2CZN8O6XOmRIsj626Hh3nSZ+W0fmhPTjY8gf4nHpOylHvZIMoAe/REv+KMHOMAFwc19fMGUZN/iXqKRp6Tgvao7/o6w1DJsQigDDnyQPhsWqgGIrV2OCTpKRuIOa16EYafbJFPDMlmRLgdIjw4sWXvnFjI45Oqem02RmhBSArR7HxEb0g1QUkEA/XNZI/l/8R241k4BRWZKebfqhqx5JxIe55F6JsqhvRQ=\"";
405            let usk = "\"mXLtWwa0YF2+nhiYn7AvG+Fkf4ih6orDMCnDeXxit4ejBLUkyAY0PowIF/UigkU9CygnZEmw09oFM5DxHjeYXB79ck3V8slKANxwXqxmrShf8YGR6BqpLugZW/jWATKZslKVFeDPs8gh0xCbejdBlX2lJLgNB9M5t/NxSuqnNUyCb/zYPGC1ElE3mcUWu8fsDFfIBFveQ/7b5Y8HQOyEUBwYlAbJmQs9XPSJ19WIWoqZNulhkFlcsjW8cj5cquNvpz4NEXKlkz46YMto+wyafbrcBfDbhDHPDFYEVRzGx1JrQ+tVGlJYskCtHMCzdPYfGROot2NcPcP18WB4oIppe1RBglgkM6uZx2kRYsOmJteHfYhjy5rAUTqG52BXqH24o64RNMWKDlL+/hkkqsMCT6UEvdS18xaQBc5mcQ5Hxcwl+sYuZvyy+3ZyE08zVjjrCvy+qa8DViT4ThAvM0phg6EngAhzZVONEPRuglKsd4LlDtk/Qx+pkjvAdMJvkP2qkqhmyZarWAQWHY5jOEl5t7WQNhKSRJkj4NQLMAZ+cxhQxpNy63+p1ejGsWlcjIejCPTeHjP/IJdtdaIYXjBFqsRUpi1Cd27XapHq3fntAYab+jG0TagGdHJbIMkdR6K+sRgA8QjiQsSEElzhZ/hIEDqxq1QkFllltFNodx+zTO7IowNRgJxUtkUUDRvUmNpRA+L2Wl2/Nv2CW+KNiuizwPDzsGs46c29DR5AYHVPEJOsvkzdHEa/IMxXnuqdSTsl\"";
406            let ct = "\"pjhu9vnHq7VoT+O0jftONe+9U7NhJ+jqHxV0KQczBgBQ/gaUO30kaYbSlc4IEQHeqOeUitp1I3JAD+juoprsiau6kKWw6gu0mJp/YsTF3b6SQ0q2Mhl3RxzCuWfWVZR8hR7DcQHlyoG1FMbj8tTE2Hsv8BBb0JghwedYmWXhe/7U+DkEEYQKcHPaq5pVfF1HkKnMdwA935uIULIFXGcC3Z3q56PwDCAjjv+lzkpRAlx8kPgyv9IKdhNHhLfJNuAUkzFzYSy08udRKvq0eCl/VH4mWvmWcbQOMn/BguwdGok=\"";
407            let mrct = "\"kDxkcKzqw67KhSGYkN6Lbc3PaZmyZZACvHpk5nnC17hneJUi6rDzmbvi21YJ1nrQuQMA4nIb1uuw2akHVajdv/V56G5fpyYUAzrb6IvltPxQbo/7dBsteYyD+OGwVKEho0zPr3yWVhNt9BGwGJvwXClVmmX2MRYVmQ1Gq55TON91VK/upr8Hr3XWRGwR8lhQjy0etI/v7K7UKp90nhQY4JcXlwk666YoDjhLs+gFCOxUpY1bIswJpDVr9mCXMXujdPqiRpoltYYEhdBInhID0WjA5zxvr4zobNxMSZWfk5eAcCHYxItjHX4FCYqrGcPFc5uOUhWOZmay7iNwjczcmMAlMYbSx3ppfDjGfQd06lSygsATkQmTgCMZrwM=\"";
408
409            let _pk_decoded: PublicKey<CGWKV> = serde_json::from_str(pk).unwrap();
410            let _sk_decoded: SecretKey<CGWKV> = serde_json::from_str(sk).unwrap();
411            let _ct_decoded: Ciphertext<CGWKV> = serde_json::from_str(ct).unwrap();
412            let _usk_decoded: UserSecretKey<CGWKV> = serde_json::from_str(usk).unwrap();
413            let _mct_decoded: MultiRecipientCiphertext<CGWKV> = serde_json::from_str(mrct).unwrap();
414        }
415    }
416
417    mod sign {
418        use super::super::{SigningKey, VerifyingKey};
419        use ibs::gg::*;
420        use rand::Rng;
421
422        struct SignSetup {
423            pk: PublicKey,
424            usk: UserSecretKey,
425        }
426
427        fn default_signing_setup() -> SignSetup {
428            let mut rng = rand::thread_rng();
429            let (pk, sk) = ibs::gg::setup(&mut rng);
430
431            let id = Identity::from(rng.gen::<[u8; IDENTITY_BYTES]>());
432            let usk = ibs::gg::keygen(&sk, &id, &mut rng);
433
434            SignSetup { pk, usk }
435        }
436
437        #[test]
438        fn test_signing_regression() {
439            let pk = "\"XMTJUg+94jtBhy/z655djL97gFLeDfANA9mhnQ+2tzE=\"";
440            let usk = "\"K3Ijgx5lgGA/wD+/rzVVQ6l4xF4N/zxMQPTbsP4c0wJkf/Q1Q3z8STL0Qg1E+b3upqRKNivYKzPZ0246z09bLst0nqGC69fa6PRpG2kEOAXS8B/h6fI/B/I0D9BfQmbU\"";
441            let sk = [
442                3, 156, 140, 183, 148, 171, 164, 239, 191, 152, 103, 133, 137, 241, 96, 169, 157,
443                199, 137, 169, 187, 204, 85, 118, 79, 35, 52, 83, 37, 217, 230, 13,
444            ];
445
446            let _pk: VerifyingKey = serde_json::from_str(&pk).unwrap();
447            let _usk: SigningKey = serde_json::from_str(&usk).unwrap();
448            let _sk: SecretKey = crate::bincode_compat::deserialize(&sk).unwrap();
449        }
450
451        macro_rules! test_serialize {
452            ($name: ident, $setup: ident, $type: tt, $ser: path, $de: path, $member: tt) => {
453                #[test]
454                fn $name() {
455                    let setup = $setup();
456
457                    let wrapped = $type(setup.$member.clone());
458                    let serialized = $ser(&wrapped).unwrap();
459                    let deserialized: $type = $de(&serialized).unwrap();
460
461                    assert_eq!(&setup.$member, &deserialized.0);
462                }
463            };
464        }
465
466        test_serialize!(
467            test_serialize_verifying_key_bin,
468            default_signing_setup,
469            VerifyingKey,
470            crate::bincode_compat::serialize,
471            crate::bincode_compat::deserialize,
472            pk
473        );
474
475        test_serialize!(
476            test_serialize_signing_key_bin,
477            default_signing_setup,
478            SigningKey,
479            crate::bincode_compat::serialize,
480            crate::bincode_compat::deserialize,
481            usk
482        );
483
484        test_serialize!(
485            test_serialize_verifying_key_json,
486            default_signing_setup,
487            VerifyingKey,
488            serde_json::to_string,
489            serde_json::from_str,
490            pk
491        );
492
493        test_serialize!(
494            test_serialize_signing_key_json,
495            default_signing_setup,
496            SigningKey,
497            serde_json::to_string,
498            serde_json::from_str,
499            usk
500        );
501    }
502}