1use generic_array::sequence::Concat;
7use generic_array::typenum::{Sum, Unsigned};
8use generic_array::GenericArray;
9
10use crate::{
11 BlindedElement, CipherSuite, Error, EvaluationElement, Group, OprfClient, OprfServer,
12 PoprfClient, PoprfServer, Proof, Result, VoprfClient, VoprfServer,
13};
14
15pub type OprfClientLen<CS> = <<CS as CipherSuite>::Group as Group>::ScalarLen;
22
23impl<CS: CipherSuite> OprfClient<CS> {
24 pub fn serialize(&self) -> GenericArray<u8, OprfClientLen<CS>> {
26 CS::Group::serialize_scalar(self.blind)
27 }
28
29 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
34 let blind = deserialize_scalar::<CS::Group>(&mut input)?;
35 check_consumed(input)?;
36
37 Ok(Self { blind })
38 }
39}
40
41pub type VoprfClientLen<CS> = Sum<
43 <<CS as CipherSuite>::Group as Group>::ScalarLen,
44 <<CS as CipherSuite>::Group as Group>::ElemLen,
45>;
46
47impl<CS: CipherSuite> VoprfClient<CS> {
48 pub fn serialize(&self) -> GenericArray<u8, VoprfClientLen<CS>> {
50 <CS::Group as Group>::serialize_scalar(self.blind)
51 .concat(<CS::Group as Group>::serialize_elem(self.blinded_element))
52 }
53
54 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
59 let blind = deserialize_scalar::<CS::Group>(&mut input)?;
60 let blinded_element = deserialize_elem::<CS::Group>(&mut input)?;
61 check_consumed(input)?;
62
63 Ok(Self {
64 blind,
65 blinded_element,
66 })
67 }
68}
69
70pub type PoprfClientLen<CS> = Sum<
72 <<CS as CipherSuite>::Group as Group>::ScalarLen,
73 <<CS as CipherSuite>::Group as Group>::ElemLen,
74>;
75
76impl<CS: CipherSuite> PoprfClient<CS> {
77 pub fn serialize(&self) -> GenericArray<u8, PoprfClientLen<CS>> {
79 <CS::Group as Group>::serialize_scalar(self.blind)
80 .concat(<CS::Group as Group>::serialize_elem(self.blinded_element))
81 }
82
83 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
88 let blind = deserialize_scalar::<CS::Group>(&mut input)?;
89 let blinded_element = deserialize_elem::<CS::Group>(&mut input)?;
90 check_consumed(input)?;
91
92 Ok(Self {
93 blind,
94 blinded_element,
95 })
96 }
97}
98
99pub type OprfServerLen<CS> = <<CS as CipherSuite>::Group as Group>::ScalarLen;
101
102impl<CS: CipherSuite> OprfServer<CS> {
103 pub fn serialize(&self) -> GenericArray<u8, OprfServerLen<CS>> {
105 CS::Group::serialize_scalar(self.sk)
106 }
107
108 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
113 let sk = deserialize_scalar::<CS::Group>(&mut input)?;
114 check_consumed(input)?;
115
116 Ok(Self { sk })
117 }
118}
119
120pub type VoprfServerLen<CS> = Sum<
122 <<CS as CipherSuite>::Group as Group>::ScalarLen,
123 <<CS as CipherSuite>::Group as Group>::ElemLen,
124>;
125
126impl<CS: CipherSuite> VoprfServer<CS> {
127 pub fn serialize(&self) -> GenericArray<u8, VoprfServerLen<CS>> {
129 CS::Group::serialize_scalar(self.sk).concat(CS::Group::serialize_elem(self.pk))
130 }
131
132 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
137 let sk = deserialize_scalar::<CS::Group>(&mut input)?;
138 let pk = deserialize_elem::<CS::Group>(&mut input)?;
139 check_consumed(input)?;
140
141 Ok(Self { sk, pk })
142 }
143}
144
145pub type PoprfServerLen<CS> = Sum<
147 <<CS as CipherSuite>::Group as Group>::ScalarLen,
148 <<CS as CipherSuite>::Group as Group>::ElemLen,
149>;
150
151impl<CS: CipherSuite> PoprfServer<CS> {
152 pub fn serialize(&self) -> GenericArray<u8, PoprfServerLen<CS>> {
154 CS::Group::serialize_scalar(self.sk).concat(CS::Group::serialize_elem(self.pk))
155 }
156
157 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
162 let sk = deserialize_scalar::<CS::Group>(&mut input)?;
163 let pk = deserialize_elem::<CS::Group>(&mut input)?;
164 check_consumed(input)?;
165
166 Ok(Self { sk, pk })
167 }
168}
169
170pub type ProofLen<CS> = Sum<
172 <<CS as CipherSuite>::Group as Group>::ScalarLen,
173 <<CS as CipherSuite>::Group as Group>::ScalarLen,
174>;
175
176impl<CS: CipherSuite> Proof<CS> {
177 pub fn serialize(&self) -> GenericArray<u8, ProofLen<CS>> {
179 CS::Group::serialize_scalar(self.c_scalar)
180 .concat(CS::Group::serialize_scalar(self.s_scalar))
181 }
182
183 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
188 let c_scalar = deserialize_scalar::<CS::Group>(&mut input)?;
189 let s_scalar = deserialize_scalar::<CS::Group>(&mut input)?;
190 check_consumed(input)?;
191
192 Ok(Proof { c_scalar, s_scalar })
193 }
194}
195
196pub type BlindedElementLen<CS> = <<CS as CipherSuite>::Group as Group>::ElemLen;
198
199impl<CS: CipherSuite> BlindedElement<CS> {
200 pub fn serialize(&self) -> GenericArray<u8, BlindedElementLen<CS>> {
202 CS::Group::serialize_elem(self.0)
203 }
204
205 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
210 let value = deserialize_elem::<CS::Group>(&mut input)?;
211 check_consumed(input)?;
212
213 Ok(Self(value))
214 }
215}
216
217pub type EvaluationElementLen<CS> = <<CS as CipherSuite>::Group as Group>::ElemLen;
219
220impl<CS: CipherSuite> EvaluationElement<CS> {
221 pub fn serialize(&self) -> GenericArray<u8, EvaluationElementLen<CS>> {
223 CS::Group::serialize_elem(self.0)
224 }
225
226 pub fn deserialize(mut input: &[u8]) -> Result<Self> {
231 let value = deserialize_elem::<CS::Group>(&mut input)?;
232 check_consumed(input)?;
233
234 Ok(Self(value))
235 }
236}
237
238fn check_consumed(input: &[u8]) -> Result<()> {
242 if input.is_empty() {
243 Ok(())
244 } else {
245 Err(Error::Deserialization)
246 }
247}
248
249fn deserialize_elem<G: Group>(input: &mut &[u8]) -> Result<G::Elem> {
250 let input = input
251 .take_ext(G::ElemLen::USIZE)
252 .ok_or(Error::Deserialization)?;
253 G::deserialize_elem(input)
254}
255
256fn deserialize_scalar<G: Group>(input: &mut &[u8]) -> Result<G::Scalar> {
257 let input = input
258 .take_ext(G::ScalarLen::USIZE)
259 .ok_or(Error::Deserialization)?;
260 G::deserialize_scalar(input)
261}
262
263trait SliceExt {
264 fn take_ext<'a>(self: &mut &'a Self, take: usize) -> Option<&'a Self>;
265}
266
267impl<T> SliceExt for [T] {
268 fn take_ext<'a>(self: &mut &'a Self, take: usize) -> Option<&'a Self> {
269 if take > self.len() {
270 return None;
271 }
272
273 let (front, back) = self.split_at(take);
274 *self = back;
275 Some(front)
276 }
277}
278
279#[cfg(feature = "serde")]
280pub(crate) mod serde {
281 use core::marker::PhantomData;
282
283 use generic_array::GenericArray;
284 use serde::de::{Deserializer, Error};
285 use serde::ser::Serializer;
286 use serde::{Deserialize, Serialize};
287
288 use crate::Group;
289
290 pub(crate) struct Element<G: Group>(PhantomData<G>);
291
292 impl<'de, G: Group> Element<G> {
293 pub(crate) fn deserialize<D>(deserializer: D) -> Result<G::Elem, D::Error>
294 where
295 D: Deserializer<'de>,
296 {
297 GenericArray::<_, G::ElemLen>::deserialize(deserializer)
298 .and_then(|bytes| G::deserialize_elem(&bytes).map_err(D::Error::custom))
299 }
300
301 pub(crate) fn serialize<S>(self_: &G::Elem, serializer: S) -> Result<S::Ok, S::Error>
302 where
303 S: Serializer,
304 {
305 G::serialize_elem(*self_).serialize(serializer)
306 }
307 }
308
309 pub(crate) struct Scalar<G: Group>(PhantomData<G>);
310
311 impl<'de, G: Group> Scalar<G> {
312 pub(crate) fn deserialize<D>(deserializer: D) -> Result<G::Scalar, D::Error>
313 where
314 D: Deserializer<'de>,
315 {
316 GenericArray::<_, G::ScalarLen>::deserialize(deserializer)
317 .and_then(|bytes| G::deserialize_scalar(&bytes).map_err(D::Error::custom))
318 }
319
320 pub(crate) fn serialize<S>(self_: &G::Scalar, serializer: S) -> Result<S::Ok, S::Error>
321 where
322 S: Serializer,
323 {
324 G::serialize_scalar(*self_).serialize(serializer)
325 }
326 }
327}
328
329#[cfg(test)]
330mod test {
331 use proptest::collection::vec;
332 use proptest::prelude::*;
333
334 use crate::{
335 BlindedElement, EvaluationElement, OprfClient, OprfServer, PoprfClient, PoprfServer, Proof,
336 VoprfClient, VoprfServer,
337 };
338
339 macro_rules! test_deserialize {
340 ($item:ident, $bytes:ident) => {
341 #[cfg(feature = "ristretto255")]
342 {
343 let _ = $item::<crate::Ristretto255>::deserialize(&$bytes[..]);
344 }
345
346 let _ = $item::<p256::NistP256>::deserialize(&$bytes[..]);
347 let _ = $item::<p384::NistP384>::deserialize(&$bytes[..]);
348 let _ = $item::<p521::NistP521>::deserialize(&$bytes[..]);
349 };
350 }
351
352 proptest! {
353 #[test]
354 fn test_nocrash_oprf_client(bytes in vec(any::<u8>(), 0..200)) {
355 test_deserialize!(OprfClient, bytes);
356 }
357
358 #[test]
359 fn test_nocrash_voprf_client(bytes in vec(any::<u8>(), 0..200)) {
360 test_deserialize!(VoprfClient, bytes);
361 }
362
363 #[test]
364 fn test_nocrash_poprf_client(bytes in vec(any::<u8>(), 0..200)) {
365 test_deserialize!(PoprfClient, bytes);
366 }
367
368 #[test]
369 fn test_nocrash_oprf_server(bytes in vec(any::<u8>(), 0..200)) {
370 test_deserialize!(OprfServer, bytes);
371 }
372
373 #[test]
374 fn test_nocrash_voprf_server(bytes in vec(any::<u8>(), 0..200)) {
375 test_deserialize!(VoprfServer, bytes);
376 }
377
378 #[test]
379 fn test_nocrash_poprf_server(bytes in vec(any::<u8>(), 0..200)) {
380 test_deserialize!(PoprfServer, bytes);
381 }
382
383
384 #[test]
385 fn test_nocrash_blinded_element(bytes in vec(any::<u8>(), 0..200)) {
386 test_deserialize!(BlindedElement, bytes);
387 }
388
389 #[test]
390 fn test_nocrash_evaluation_element(bytes in vec(any::<u8>(), 0..200)) {
391 test_deserialize!(EvaluationElement, bytes);
392 }
393
394 #[test]
395 fn test_nocrash_proof(bytes in vec(any::<u8>(), 0..200)) {
396 test_deserialize!(Proof, bytes);
397 }
398 }
399
400 use ::alloc::vec::Vec;
401 use rand::rngs::SysRng;
402
403 use crate::{CipherSuite, Error};
404
405 fn trailing_bytes_rejected<CS: CipherSuite>() {
406 let mut rng = SysRng;
407 let server = VoprfServer::<CS>::new(&mut rng).unwrap();
408 let blind_result = VoprfClient::<CS>::blind(b"input", &mut rng).unwrap();
409
410 let server_bytes = server.serialize().to_vec();
413 VoprfServer::<CS>::deserialize(&server_bytes).unwrap();
414 assert!(matches!(
415 VoprfServer::<CS>::deserialize(&extend(&server_bytes)),
416 Err(Error::Deserialization)
417 ));
418
419 let client_bytes = blind_result.state.serialize().to_vec();
420 VoprfClient::<CS>::deserialize(&client_bytes).unwrap();
421 assert!(matches!(
422 VoprfClient::<CS>::deserialize(&extend(&client_bytes)),
423 Err(Error::Deserialization)
424 ));
425
426 let element_bytes = blind_result.message.serialize().to_vec();
427 BlindedElement::<CS>::deserialize(&element_bytes).unwrap();
428 assert!(matches!(
429 BlindedElement::<CS>::deserialize(&extend(&element_bytes)),
430 Err(Error::Deserialization)
431 ));
432 }
433
434 fn extend(bytes: &[u8]) -> Vec<u8> {
435 let mut extended = bytes.to_vec();
436 extended.push(0);
437 extended
438 }
439
440 #[test]
441 fn test_trailing_bytes_rejected() {
442 #[cfg(feature = "ristretto255")]
443 trailing_bytes_rejected::<crate::Ristretto255>();
444
445 trailing_bytes_rejected::<p256::NistP256>();
446 trailing_bytes_rejected::<p384::NistP384>();
447 trailing_bytes_rejected::<p521::NistP521>();
448 }
449}