// Copyright (c) Meta Platforms, Inc. and affiliates. // // This source code is dual-licensed under either the MIT license found in the // LICENSE-MIT file in the root directory of this source tree or the Apache // License, Version 2.0 found in the LICENSE-APACHE file in the root directory // of this source tree. You may select, at your option, one of the above-listed // licenses. //! Handles the serialization of each of the components used in the VOPRF //! protocol use core::ops::Add; use digest::core_api::BlockSizeUser; use digest::OutputSizeUser; use generic_array::sequence::Concat; use generic_array::typenum::{IsLess, IsLessOrEqual, Sum, Unsigned, U256}; use generic_array::{ArrayLength, GenericArray}; use crate::{ BlindedElement, CipherSuite, Error, EvaluationElement, Group, OprfClient, OprfServer, PoprfClient, PoprfServer, Proof, Result, VoprfClient, VoprfServer, }; ////////////////////////////////////////////////////////// // Serialization and Deserialization for High-Level API // // ==================================================== // ////////////////////////////////////////////////////////// /// Length of [`OprfClient`] in bytes for serialization. pub type OprfClientLen = <::Group as Group>::ScalarLen; impl OprfClient where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> { CS::Group::serialize_scalar(self.blind) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let blind = deserialize_scalar::(&mut input)?; Ok(Self { blind }) } } /// Length of [`VoprfClient`] in bytes for serialization. pub type VoprfClientLen = Sum< <::Group as Group>::ScalarLen, <::Group as Group>::ElemLen, >; impl VoprfClient where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where ::ScalarLen: Add<::ElemLen>, VoprfClientLen: ArrayLength, { ::serialize_scalar(self.blind) .concat(::serialize_elem(self.blinded_element)) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let blind = deserialize_scalar::(&mut input)?; let blinded_element = deserialize_elem::(&mut input)?; Ok(Self { blind, blinded_element, }) } } /// Length of [`PoprfClient`] in bytes for serialization. pub type PoprfClientLen = Sum< <::Group as Group>::ScalarLen, <::Group as Group>::ElemLen, >; impl PoprfClient where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where ::ScalarLen: Add<::ElemLen>, PoprfClientLen: ArrayLength, { ::serialize_scalar(self.blind) .concat(::serialize_elem(self.blinded_element)) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let blind = deserialize_scalar::(&mut input)?; let blinded_element = deserialize_elem::(&mut input)?; Ok(Self { blind, blinded_element, }) } } /// Length of [`OprfServer`] in bytes for serialization. pub type OprfServerLen = <::Group as Group>::ScalarLen; impl OprfServer where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> { CS::Group::serialize_scalar(self.sk) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let sk = deserialize_scalar::(&mut input)?; Ok(Self { sk }) } } /// Length of [`VoprfServer`] in bytes for serialization. pub type VoprfServerLen = Sum< <::Group as Group>::ScalarLen, <::Group as Group>::ElemLen, >; impl VoprfServer where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where ::ScalarLen: Add<::ElemLen>, VoprfServerLen: ArrayLength, { CS::Group::serialize_scalar(self.sk).concat(CS::Group::serialize_elem(self.pk)) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let sk = deserialize_scalar::(&mut input)?; let pk = deserialize_elem::(&mut input)?; Ok(Self { sk, pk }) } } /// Length of [`PoprfServer`] in bytes for serialization. pub type PoprfServerLen = Sum< <::Group as Group>::ScalarLen, <::Group as Group>::ElemLen, >; impl PoprfServer where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where ::ScalarLen: Add<::ElemLen>, PoprfServerLen: ArrayLength, { CS::Group::serialize_scalar(self.sk).concat(CS::Group::serialize_elem(self.pk)) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let sk = deserialize_scalar::(&mut input)?; let pk = deserialize_elem::(&mut input)?; Ok(Self { sk, pk }) } } /// Length of [`Proof`] in bytes for serialization. pub type ProofLen = Sum< <::Group as Group>::ScalarLen, <::Group as Group>::ScalarLen, >; impl Proof where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where ::ScalarLen: Add<::ScalarLen>, ProofLen: ArrayLength, { CS::Group::serialize_scalar(self.c_scalar) .concat(CS::Group::serialize_scalar(self.s_scalar)) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let c_scalar = deserialize_scalar::(&mut input)?; let s_scalar = deserialize_scalar::(&mut input)?; Ok(Proof { c_scalar, s_scalar }) } } /// Length of [`BlindedElement`] in bytes for serialization. pub type BlindedElementLen = <::Group as Group>::ElemLen; impl BlindedElement where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> { CS::Group::serialize_elem(self.0) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let value = deserialize_elem::(&mut input)?; Ok(Self(value)) } } /// Length of [`EvaluationElement`] in bytes for serialization. pub type EvaluationElementLen = <::Group as Group>::ElemLen; impl EvaluationElement where ::OutputSize: IsLess + IsLessOrEqual<::BlockSize>, { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> { CS::Group::serialize_elem(self.0) } /// Deserialization from bytes /// /// # Errors /// [`Error::Deserialization`] if failed to deserialize `input`. pub fn deserialize(mut input: &[u8]) -> Result { let value = deserialize_elem::(&mut input)?; Ok(Self(value)) } } fn deserialize_elem(input: &mut &[u8]) -> Result { let input = input .take_ext(G::ElemLen::USIZE) .ok_or(Error::Deserialization)?; G::deserialize_elem(input) } fn deserialize_scalar(input: &mut &[u8]) -> Result { let input = input .take_ext(G::ScalarLen::USIZE) .ok_or(Error::Deserialization)?; G::deserialize_scalar(input) } trait SliceExt { fn take_ext<'a>(self: &mut &'a Self, take: usize) -> Option<&'a Self>; } impl SliceExt for [T] { fn take_ext<'a>(self: &mut &'a Self, take: usize) -> Option<&'a Self> { if take > self.len() { return None; } let (front, back) = self.split_at(take); *self = back; Some(front) } } #[cfg(feature = "serde")] pub(crate) mod serde { use core::marker::PhantomData; use generic_array::GenericArray; use serde::de::{Deserializer, Error}; use serde::ser::Serializer; use serde::{Deserialize, Serialize}; use crate::Group; pub(crate) struct Element(PhantomData); impl<'de, G: Group> Element { pub(crate) fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { GenericArray::<_, G::ElemLen>::deserialize(deserializer) .and_then(|bytes| G::deserialize_elem(&bytes).map_err(D::Error::custom)) } pub(crate) fn serialize(self_: &G::Elem, serializer: S) -> Result where S: Serializer, { G::serialize_elem(*self_).serialize(serializer) } } pub(crate) struct Scalar(PhantomData); impl<'de, G: Group> Scalar { pub(crate) fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { GenericArray::<_, G::ScalarLen>::deserialize(deserializer) .and_then(|bytes| G::deserialize_scalar(&bytes).map_err(D::Error::custom)) } pub(crate) fn serialize(self_: &G::Scalar, serializer: S) -> Result where S: Serializer, { G::serialize_scalar(*self_).serialize(serializer) } } } #[cfg(test)] mod test { use proptest::collection::vec; use proptest::prelude::*; use crate::{ BlindedElement, EvaluationElement, OprfClient, OprfServer, PoprfClient, PoprfServer, Proof, VoprfClient, VoprfServer, }; macro_rules! test_deserialize { ($item:ident, $bytes:ident) => { #[cfg(feature = "ristretto255")] { let _ = $item::::deserialize(&$bytes[..]); } let _ = $item::::deserialize(&$bytes[..]); let _ = $item::::deserialize(&$bytes[..]); let _ = $item::::deserialize(&$bytes[..]); }; } proptest! { #[test] fn test_nocrash_oprf_client(bytes in vec(any::(), 0..200)) { test_deserialize!(OprfClient, bytes); } #[test] fn test_nocrash_voprf_client(bytes in vec(any::(), 0..200)) { test_deserialize!(VoprfClient, bytes); } #[test] fn test_nocrash_poprf_client(bytes in vec(any::(), 0..200)) { test_deserialize!(PoprfClient, bytes); } #[test] fn test_nocrash_oprf_server(bytes in vec(any::(), 0..200)) { test_deserialize!(OprfServer, bytes); } #[test] fn test_nocrash_voprf_server(bytes in vec(any::(), 0..200)) { test_deserialize!(VoprfServer, bytes); } #[test] fn test_nocrash_poprf_server(bytes in vec(any::(), 0..200)) { test_deserialize!(PoprfServer, bytes); } #[test] fn test_nocrash_blinded_element(bytes in vec(any::(), 0..200)) { test_deserialize!(BlindedElement, bytes); } #[test] fn test_nocrash_evaluation_element(bytes in vec(any::(), 0..200)) { test_deserialize!(EvaluationElement, bytes); } #[test] fn test_nocrash_proof(bytes in vec(any::(), 0..200)) { test_deserialize!(Proof, bytes); } } }