General improvements (#56)
* Apply Rust traits to all public types and other improvements * Move methods into appropriate section * Check for zero scalars * Change element and scalar de/serialization from `GenericArray` to slice * Customize `serde` serialization
This commit is contained in:
+2
-1
@@ -22,6 +22,7 @@ ristretto255-fiat-u64 = ["curve25519-dalek/fiat_u64_backend", "ristretto255"]
|
||||
ristretto255-simd = ["curve25519-dalek/simd_backend", "ristretto255"]
|
||||
ristretto255-u32 = ["curve25519-dalek/u32_backend", "ristretto255"]
|
||||
ristretto255-u64 = ["curve25519-dalek/u64_backend", "ristretto255"]
|
||||
serde = ["generic-array/serde", "serde_"]
|
||||
std = ["alloc"]
|
||||
|
||||
[dependencies]
|
||||
@@ -36,7 +37,7 @@ elliptic-curve = { version = "0.12.0-pre.1", features = [
|
||||
] }
|
||||
generic-array = "0.14"
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
serde = { version = "1", default-features = false, features = [
|
||||
serde_ = { version = "1", package = "serde", default-features = false, features = [
|
||||
"derive",
|
||||
], optional = true }
|
||||
sha2 = { version = "0.10", default-features = false, optional = true }
|
||||
|
||||
@@ -27,6 +27,8 @@ pub enum Error {
|
||||
ProofVerification,
|
||||
/// Size of seed is longer then [`u16::MAX`].
|
||||
Seed,
|
||||
/// The protocol has failed and can't be completed.
|
||||
Protocol,
|
||||
}
|
||||
|
||||
/// Only used to implement [`Group`](crate::Group).
|
||||
|
||||
@@ -89,7 +89,7 @@ where
|
||||
result
|
||||
}
|
||||
|
||||
fn deserialize_elem(element_bits: &GenericArray<u8, Self::ElemLen>) -> Result<Self::Elem> {
|
||||
fn deserialize_elem(element_bits: &[u8]) -> Result<Self::Elem> {
|
||||
PublicKey::<Self>::from_sec1_bytes(element_bits)
|
||||
.map(|public_key| public_key.to_projective())
|
||||
.map_err(|_| Error::Deserialization)
|
||||
@@ -103,6 +103,10 @@ where
|
||||
Option::from(scalar.invert()).unwrap()
|
||||
}
|
||||
|
||||
fn is_zero_scalar(scalar: Self::Scalar) -> subtle::Choice {
|
||||
scalar.is_zero()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn zero_scalar() -> Self::Scalar {
|
||||
Scalar::<Self>::zero()
|
||||
@@ -112,7 +116,7 @@ where
|
||||
scalar.into()
|
||||
}
|
||||
|
||||
fn deserialize_scalar(scalar_bits: &GenericArray<u8, Self::ScalarLen>) -> Result<Self::Scalar> {
|
||||
fn deserialize_scalar(scalar_bits: &[u8]) -> Result<Self::Scalar> {
|
||||
SecretKey::<Self>::from_be_bytes(scalar_bits)
|
||||
.map(|secret_key| *secret_key.to_nonzero_scalar())
|
||||
.map_err(|_| Error::Deserialization)
|
||||
|
||||
+6
-3
@@ -20,7 +20,7 @@ use generic_array::{ArrayLength, GenericArray};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
#[cfg(feature = "ristretto255")]
|
||||
pub use ristretto::Ristretto255;
|
||||
use subtle::ConstantTimeEq;
|
||||
use subtle::{Choice, ConstantTimeEq};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::voprf::Mode;
|
||||
@@ -93,7 +93,7 @@ pub trait Group {
|
||||
/// # Errors
|
||||
/// [`Error::Deserialization`](crate::Error::Deserialization) if the element
|
||||
/// is not a valid point on the group or the identity element.
|
||||
fn deserialize_elem(element_bits: &GenericArray<u8, Self::ElemLen>) -> Result<Self::Elem>;
|
||||
fn deserialize_elem(element_bits: &[u8]) -> Result<Self::Elem>;
|
||||
|
||||
/// picks a scalar at random
|
||||
fn random_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar;
|
||||
@@ -101,6 +101,9 @@ pub trait Group {
|
||||
/// The multiplicative inverse of this scalar
|
||||
fn invert_scalar(scalar: Self::Scalar) -> Self::Scalar;
|
||||
|
||||
/// Returns `true` if the scalar is zero.
|
||||
fn is_zero_scalar(scalar: Self::Scalar) -> Choice;
|
||||
|
||||
/// Returns the scalar representing zero
|
||||
#[cfg(test)]
|
||||
fn zero_scalar() -> Self::Scalar;
|
||||
@@ -114,7 +117,7 @@ pub trait Group {
|
||||
/// # Errors
|
||||
/// [`Error::Deserialization`](crate::Error::Deserialization) if the scalar
|
||||
/// is not a valid point on the group or zero.
|
||||
fn deserialize_scalar(scalar_bits: &GenericArray<u8, Self::ScalarLen>) -> Result<Self::Scalar>;
|
||||
fn deserialize_scalar(scalar_bits: &[u8]) -> Result<Self::Scalar>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
+14
-3
@@ -16,12 +16,16 @@ use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, U256, U32, U64};
|
||||
use generic_array::GenericArray;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
use super::{Group, STR_HASH_TO_GROUP, STR_HASH_TO_SCALAR};
|
||||
use crate::voprf::{self, Mode};
|
||||
use crate::{CipherSuite, Error, InternalError, Result};
|
||||
|
||||
/// [`Group`] implementation for Ristretto255.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
// `cfg` here is only needed because of a bug in Rust's crate feature documentation. See: https://github.com/rust-lang/rust/issues/83428
|
||||
#[cfg(feature = "ristretto255")]
|
||||
pub struct Ristretto255;
|
||||
|
||||
#[cfg(feature = "ristretto255-ciphersuite")]
|
||||
@@ -99,7 +103,7 @@ impl Group for Ristretto255 {
|
||||
elem.compress().to_bytes().into()
|
||||
}
|
||||
|
||||
fn deserialize_elem(element_bits: &GenericArray<u8, Self::ElemLen>) -> Result<Self::Elem> {
|
||||
fn deserialize_elem(element_bits: &[u8]) -> Result<Self::Elem> {
|
||||
CompressedRistretto::from_slice(element_bits)
|
||||
.decompress()
|
||||
.filter(|point| point != &RistrettoPoint::identity())
|
||||
@@ -124,6 +128,10 @@ impl Group for Ristretto255 {
|
||||
scalar.invert()
|
||||
}
|
||||
|
||||
fn is_zero_scalar(scalar: Self::Scalar) -> subtle::Choice {
|
||||
scalar.ct_eq(&Scalar::zero())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn zero_scalar() -> Self::Scalar {
|
||||
Scalar::zero()
|
||||
@@ -133,8 +141,11 @@ impl Group for Ristretto255 {
|
||||
scalar.to_bytes().into()
|
||||
}
|
||||
|
||||
fn deserialize_scalar(scalar_bits: &GenericArray<u8, Self::ScalarLen>) -> Result<Self::Scalar> {
|
||||
Scalar::from_canonical_bytes((*scalar_bits).into())
|
||||
fn deserialize_scalar(scalar_bits: &[u8]) -> Result<Self::Scalar> {
|
||||
scalar_bits
|
||||
.try_into()
|
||||
.ok()
|
||||
.and_then(Scalar::from_canonical_bytes)
|
||||
.filter(|scalar| scalar != &Scalar::zero())
|
||||
.ok_or(Error::Deserialization)
|
||||
}
|
||||
|
||||
+18
-10
@@ -88,9 +88,8 @@
|
||||
//!
|
||||
//! In the second step, the server takes as input the message from
|
||||
//! [NonVerifiableClient::blind] (a [BlindedElement]), and runs
|
||||
//! [NonVerifiableServer::evaluate] to produce a
|
||||
//! [NonVerifiableServerEvaluateResult], which consists of an
|
||||
//! [EvaluationElement] to be sent to the client.
|
||||
//! [NonVerifiableServer::evaluate] to produce [EvaluationElement] to be sent to
|
||||
//! the client.
|
||||
//!
|
||||
//! ```
|
||||
//! # #[cfg(feature = "ristretto255")]
|
||||
@@ -135,13 +134,13 @@
|
||||
//! # use voprf::NonVerifiableServer;
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! # let server = NonVerifiableServer::<CipherSuite>::new(&mut server_rng);
|
||||
//! # let server_evaluate_result = server.evaluate(
|
||||
//! # let message = server.evaluate(
|
||||
//! # &client_blind_result.message,
|
||||
//! # None,
|
||||
//! # ).expect("Unable to perform server evaluate");
|
||||
//! let client_finalize_result = client_blind_result
|
||||
//! .state
|
||||
//! .finalize(b"input", &server_evaluate_result.message, None)
|
||||
//! .finalize(b"input", &message, None)
|
||||
//! .expect("Unable to perform client finalization");
|
||||
//!
|
||||
//! println!("VOPRF output: {:?}", client_finalize_result.to_vec());
|
||||
@@ -479,7 +478,12 @@
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![no_std]
|
||||
#![warn(clippy::cargo, clippy::missing_errors_doc, missing_docs)]
|
||||
#![warn(
|
||||
clippy::cargo,
|
||||
clippy::missing_errors_doc,
|
||||
missing_debug_implementations,
|
||||
missing_docs
|
||||
)]
|
||||
#![allow(clippy::multiple_crate_versions)]
|
||||
|
||||
#[cfg(any(feature = "alloc", test))]
|
||||
@@ -488,6 +492,9 @@ extern crate alloc;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde_ as serde;
|
||||
|
||||
mod ciphersuite;
|
||||
mod error;
|
||||
mod group;
|
||||
@@ -513,8 +520,9 @@ pub use crate::serialization::{
|
||||
pub use crate::voprf::VerifiableServerBatchEvaluateResult;
|
||||
pub use crate::voprf::{
|
||||
BlindedElement, EvaluationElement, Mode, NonVerifiableClient, NonVerifiableClientBlindResult,
|
||||
NonVerifiableServer, NonVerifiableServerEvaluateResult, PreparedEvaluationElement,
|
||||
PreparedTscalar, Proof, VerifiableClient, VerifiableClientBatchFinalizeResult,
|
||||
VerifiableClientBlindResult, VerifiableServer, VerifiableServerBatchEvaluateFinishResult,
|
||||
VerifiableServerBatchEvaluatePrepareResult, VerifiableServerEvaluateResult,
|
||||
NonVerifiableServer, PreparedEvaluationElement, PreparedTscalar, Proof, VerifiableClient,
|
||||
VerifiableClientBatchFinalizeResult, VerifiableClientBlindResult, VerifiableServer,
|
||||
VerifiableServerBatchEvaluateFinishResult, VerifiableServerBatchEvaluateFinishedMessages,
|
||||
VerifiableServerBatchEvaluatePrepareResult,
|
||||
VerifiableServerBatchEvaluatePreparedEvaluationElements, VerifiableServerEvaluateResult,
|
||||
};
|
||||
|
||||
+73
-16
@@ -13,7 +13,7 @@ use core::ops::Add;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::OutputSizeUser;
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, Sum, U256};
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, Sum, Unsigned, U256};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
use crate::{
|
||||
@@ -46,7 +46,7 @@ where
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self> {
|
||||
let mut input = input.iter().copied();
|
||||
|
||||
let blind = CS::Group::deserialize_scalar(&deserialize(&mut input)?)?;
|
||||
let blind = deserialize_scalar::<CS::Group, _>(&mut input)?;
|
||||
|
||||
Ok(Self { blind })
|
||||
}
|
||||
@@ -80,8 +80,8 @@ where
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self> {
|
||||
let mut input = input.iter().copied();
|
||||
|
||||
let blind = CS::Group::deserialize_scalar(&deserialize(&mut input)?)?;
|
||||
let blinded_element = CS::Group::deserialize_elem(&deserialize(&mut input)?)?;
|
||||
let blind = deserialize_scalar::<CS::Group, _>(&mut input)?;
|
||||
let blinded_element = deserialize_elem::<CS::Group, _>(&mut input)?;
|
||||
|
||||
Ok(Self {
|
||||
blind,
|
||||
@@ -110,7 +110,7 @@ where
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self> {
|
||||
let mut input = input.iter().copied();
|
||||
|
||||
let sk = CS::Group::deserialize_scalar(&deserialize(&mut input)?)?;
|
||||
let sk = deserialize_scalar::<CS::Group, _>(&mut input)?;
|
||||
|
||||
Ok(Self { sk })
|
||||
}
|
||||
@@ -143,8 +143,8 @@ where
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self> {
|
||||
let mut input = input.iter().copied();
|
||||
|
||||
let sk = CS::Group::deserialize_scalar(&deserialize(&mut input)?)?;
|
||||
let pk = CS::Group::deserialize_elem(&deserialize(&mut input)?)?;
|
||||
let sk = deserialize_scalar::<CS::Group, _>(&mut input)?;
|
||||
let pk = deserialize_elem::<CS::Group, _>(&mut input)?;
|
||||
|
||||
Ok(Self { sk, pk })
|
||||
}
|
||||
@@ -178,8 +178,8 @@ where
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self> {
|
||||
let mut input = input.iter().copied();
|
||||
|
||||
let c_scalar = CS::Group::deserialize_scalar(&deserialize(&mut input)?)?;
|
||||
let s_scalar = CS::Group::deserialize_scalar(&deserialize(&mut input)?)?;
|
||||
let c_scalar = deserialize_scalar::<CS::Group, _>(&mut input)?;
|
||||
let s_scalar = deserialize_scalar::<CS::Group, _>(&mut input)?;
|
||||
|
||||
Ok(Proof { c_scalar, s_scalar })
|
||||
}
|
||||
@@ -205,7 +205,7 @@ where
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self> {
|
||||
let mut input = input.iter().copied();
|
||||
|
||||
let value = CS::Group::deserialize_elem(&deserialize(&mut input)?)?;
|
||||
let value = deserialize_elem::<CS::Group, _>(&mut input)?;
|
||||
|
||||
Ok(Self(value))
|
||||
}
|
||||
@@ -231,15 +231,72 @@ where
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self> {
|
||||
let mut input = input.iter().copied();
|
||||
|
||||
let value = CS::Group::deserialize_elem(&deserialize(&mut input)?)?;
|
||||
let value = deserialize_elem::<CS::Group, _>(&mut input)?;
|
||||
|
||||
Ok(Self(value))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize<L: ArrayLength<u8>>(
|
||||
input: &mut impl Iterator<Item = u8>,
|
||||
) -> Result<GenericArray<u8, L>> {
|
||||
let input = input.by_ref().take(L::USIZE);
|
||||
GenericArray::from_exact_iter(input).ok_or(Error::Deserialization)
|
||||
fn deserialize_elem<G: Group, I: Iterator<Item = u8>>(input: &mut I) -> Result<G::Elem> {
|
||||
let input = input.by_ref().take(G::ElemLen::USIZE);
|
||||
GenericArray::<_, G::ElemLen>::from_exact_iter(input)
|
||||
.ok_or(Error::Deserialization)
|
||||
.and_then(|bytes| G::deserialize_elem(&bytes))
|
||||
}
|
||||
|
||||
fn deserialize_scalar<G: Group, I: Iterator<Item = u8>>(input: &mut I) -> Result<G::Scalar> {
|
||||
let input = input.by_ref().take(G::ScalarLen::USIZE);
|
||||
GenericArray::<_, G::ScalarLen>::from_exact_iter(input)
|
||||
.ok_or(Error::Deserialization)
|
||||
.and_then(|bytes| G::deserialize_scalar(&bytes))
|
||||
}
|
||||
|
||||
#[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<G: Group>(PhantomData<G>);
|
||||
|
||||
impl<'de, G: Group> Element<G> {
|
||||
pub(crate) fn deserialize<D>(deserializer: D) -> Result<G::Elem, D::Error>
|
||||
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<S>(self_: &G::Elem, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
G::serialize_elem(*self_).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Scalar<G: Group>(PhantomData<G>);
|
||||
|
||||
impl<'de, G: Group> Scalar<G> {
|
||||
pub(crate) fn deserialize<D>(deserializer: D) -> Result<G::Scalar, D::Error>
|
||||
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<S>(self_: &G::Scalar, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
G::serialize_scalar(*self_).serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use core::ops::Add;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::OutputSizeUser;
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, Sum, U256};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use generic_array::ArrayLength;
|
||||
use json::JsonValue;
|
||||
|
||||
use crate::tests::mock_rng::CycleRng;
|
||||
@@ -183,9 +183,7 @@ where
|
||||
{
|
||||
for parameters in tvs {
|
||||
for i in 0..parameters.input.len() {
|
||||
let blind = CS::Group::deserialize_scalar(&GenericArray::clone_from_slice(
|
||||
¶meters.blind[i],
|
||||
))?;
|
||||
let blind = CS::Group::deserialize_scalar(¶meters.blind[i])?;
|
||||
let client_result = NonVerifiableClient::<CS>::deterministic_blind_unchecked(
|
||||
¶meters.input[i],
|
||||
blind,
|
||||
@@ -212,9 +210,7 @@ where
|
||||
{
|
||||
for parameters in tvs {
|
||||
for i in 0..parameters.input.len() {
|
||||
let blind = CS::Group::deserialize_scalar(&GenericArray::clone_from_slice(
|
||||
¶meters.blind[i],
|
||||
))?;
|
||||
let blind = CS::Group::deserialize_scalar(¶meters.blind[i])?;
|
||||
let client_blind_result =
|
||||
VerifiableClient::<CS>::deterministic_blind_unchecked(¶meters.input[i], blind)?;
|
||||
|
||||
@@ -240,14 +236,14 @@ where
|
||||
for parameters in tvs {
|
||||
for i in 0..parameters.input.len() {
|
||||
let server = NonVerifiableServer::<CS>::new_with_key(¶meters.sksm)?;
|
||||
let server_result = server.evaluate(
|
||||
let message = server.evaluate(
|
||||
&BlindedElement::deserialize(¶meters.blinded_element[i])?,
|
||||
Some(¶meters.info),
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
¶meters.evaluation_element[i],
|
||||
&server_result.message.serialize().as_slice()
|
||||
&message.serialize().as_slice()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -306,7 +302,7 @@ where
|
||||
for parameters in tvs {
|
||||
for i in 0..parameters.input.len() {
|
||||
let client = NonVerifiableClient::<CS>::from_blind(CS::Group::deserialize_scalar(
|
||||
&GenericArray::clone_from_slice(¶meters.blind[i]),
|
||||
¶meters.blind[i],
|
||||
)?);
|
||||
|
||||
let client_finalize_result = client.finalize(
|
||||
@@ -330,12 +326,8 @@ where
|
||||
let mut clients = vec![];
|
||||
for i in 0..parameters.input.len() {
|
||||
let client = VerifiableClient::<CS>::from_blind_and_element(
|
||||
CS::Group::deserialize_scalar(&GenericArray::clone_from_slice(
|
||||
¶meters.blind[i],
|
||||
))?,
|
||||
CS::Group::deserialize_elem(&GenericArray::clone_from_slice(
|
||||
¶meters.blinded_element[i],
|
||||
))?,
|
||||
CS::Group::deserialize_scalar(¶meters.blind[i])?,
|
||||
CS::Group::deserialize_elem(¶meters.blinded_element[i])?,
|
||||
);
|
||||
clients.push(client.clone());
|
||||
}
|
||||
@@ -351,7 +343,7 @@ where
|
||||
&clients,
|
||||
&messages,
|
||||
&Proof::deserialize(¶meters.proof)?,
|
||||
CS::Group::deserialize_elem(GenericArray::from_slice(¶meters.pksm))?,
|
||||
CS::Group::deserialize_elem(¶meters.pksm)?,
|
||||
Some(¶meters.info),
|
||||
)?;
|
||||
|
||||
|
||||
+221
-193
@@ -20,6 +20,8 @@ use generic_array::GenericArray;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use crate::serialization::serde::{Element, Scalar};
|
||||
use crate::util::{i2osp_2, i2osp_2_array};
|
||||
use crate::{CipherSuite, Error, Group, Result};
|
||||
|
||||
@@ -37,7 +39,7 @@ const STR_VOPRF: [u8; 8] = *b"VOPRF08-";
|
||||
|
||||
/// Determines the mode of operation (either base mode or verifiable mode). This
|
||||
/// is only used for custom implementations for [`Group`].
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Mode {
|
||||
/// Non-verifiable mode.
|
||||
Base,
|
||||
@@ -68,16 +70,14 @@ impl Mode {
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound(
|
||||
deserialize = "<CS::Group as Group>::Scalar: serde::Deserialize<'de>",
|
||||
serialize = "<CS::Group as Group>::Scalar: serde::Serialize"
|
||||
))
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct NonVerifiableClient<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
#[cfg_attr(feature = "serde", serde(with = "Scalar::<CS::Group>"))]
|
||||
pub(crate) blind: <CS::Group as Group>::Scalar,
|
||||
}
|
||||
|
||||
@@ -89,19 +89,16 @@ where
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound(
|
||||
deserialize = "<CS::Group as Group>::Scalar: serde::Deserialize<'de>, <CS::Group as \
|
||||
Group>::Elem: serde::Deserialize<'de>",
|
||||
serialize = "<CS::Group as Group>::Scalar: serde::Serialize, <CS::Group as Group>::Elem: \
|
||||
serde::Serialize"
|
||||
))
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct VerifiableClient<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
#[cfg_attr(feature = "serde", serde(with = "Scalar::<CS::Group>"))]
|
||||
pub(crate) blind: <CS::Group as Group>::Scalar,
|
||||
#[cfg_attr(feature = "serde", serde(with = "Element::<CS::Group>"))]
|
||||
pub(crate) blinded_element: <CS::Group as Group>::Elem,
|
||||
}
|
||||
|
||||
@@ -113,16 +110,14 @@ where
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound(
|
||||
deserialize = "<CS::Group as Group>::Scalar: serde::Deserialize<'de>",
|
||||
serialize = "<CS::Group as Group>::Scalar: serde::Serialize"
|
||||
))
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct NonVerifiableServer<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
#[cfg_attr(feature = "serde", serde(with = "Scalar::<CS::Group>"))]
|
||||
pub(crate) sk: <CS::Group as Group>::Scalar,
|
||||
}
|
||||
|
||||
@@ -134,19 +129,16 @@ where
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound(
|
||||
deserialize = "<CS::Group as Group>::Scalar: serde::Deserialize<'de>, <CS::Group as \
|
||||
Group>::Elem: serde::Deserialize<'de>",
|
||||
serialize = "<CS::Group as Group>::Scalar: serde::Serialize, <CS::Group as Group>::Elem: \
|
||||
serde::Serialize"
|
||||
))
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct VerifiableServer<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
#[cfg_attr(feature = "serde", serde(with = "Scalar::<CS::Group>"))]
|
||||
pub(crate) sk: <CS::Group as Group>::Scalar,
|
||||
#[cfg_attr(feature = "serde", serde(with = "Element::<CS::Group>"))]
|
||||
pub(crate) pk: <CS::Group as Group>::Elem,
|
||||
}
|
||||
|
||||
@@ -158,17 +150,16 @@ where
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound(
|
||||
deserialize = "<CS::Group as Group>::Scalar: serde::Deserialize<'de>",
|
||||
serialize = "<CS::Group as Group>::Scalar: serde::Serialize"
|
||||
))
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct Proof<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
#[cfg_attr(feature = "serde", serde(with = "Scalar::<CS::Group>"))]
|
||||
pub(crate) c_scalar: <CS::Group as Group>::Scalar,
|
||||
#[cfg_attr(feature = "serde", serde(with = "Scalar::<CS::Group>"))]
|
||||
pub(crate) s_scalar: <CS::Group as Group>::Scalar,
|
||||
}
|
||||
|
||||
@@ -180,12 +171,12 @@ where
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound(
|
||||
deserialize = "<CS::Group as Group>::Elem: serde::Deserialize<'de>",
|
||||
serialize = "<CS::Group as Group>::Elem: serde::Serialize"
|
||||
))
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct BlindedElement<CS: CipherSuite>(pub(crate) <CS::Group as Group>::Elem)
|
||||
pub struct BlindedElement<CS: CipherSuite>(
|
||||
#[cfg_attr(feature = "serde", serde(with = "Element::<CS::Group>"))]
|
||||
pub(crate) <CS::Group as Group>::Elem,
|
||||
)
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>;
|
||||
@@ -198,12 +189,12 @@ where
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound(
|
||||
deserialize = "<CS::Group as Group>::Elem: serde::Deserialize<'de>",
|
||||
serialize = "<CS::Group as Group>::Elem: serde::Serialize"
|
||||
))
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct EvaluationElement<CS: CipherSuite>(pub(crate) <CS::Group as Group>::Elem)
|
||||
pub struct EvaluationElement<CS: CipherSuite>(
|
||||
#[cfg_attr(feature = "serde", serde(with = "Element::<CS::Group>"))]
|
||||
pub(crate) <CS::Group as Group>::Elem,
|
||||
)
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>;
|
||||
@@ -447,7 +438,7 @@ where
|
||||
/// [`Error::Deserialization`] if the private key is not a valid point on
|
||||
/// the group or zero.
|
||||
pub fn new_with_key(private_key_bytes: &[u8]) -> Result<Self> {
|
||||
let sk = CS::Group::deserialize_scalar(private_key_bytes.into())?;
|
||||
let sk = CS::Group::deserialize_scalar(private_key_bytes)?;
|
||||
Ok(Self { sk })
|
||||
}
|
||||
|
||||
@@ -474,12 +465,13 @@ where
|
||||
/// to the client.
|
||||
///
|
||||
/// # Errors
|
||||
/// [`Error::Metadata`] if the `metadata` is longer then `u16::MAX - 21`.
|
||||
/// - [`Error::Metadata`] if the `metadata` is longer then `u16::MAX - 21`.
|
||||
/// - [`Error::Protocol`] if the protocol fails and can't be completed.
|
||||
pub fn evaluate(
|
||||
&self,
|
||||
blinded_element: &BlindedElement<CS>,
|
||||
metadata: Option<&[u8]>,
|
||||
) -> Result<NonVerifiableServerEvaluateResult<CS>> {
|
||||
) -> Result<EvaluationElement<CS>> {
|
||||
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-08.html#section-3.3.1.1-1
|
||||
|
||||
let context_string = get_context_string::<CS>(Mode::Base);
|
||||
@@ -496,12 +488,17 @@ where
|
||||
CS::Group::hash_to_scalar::<CS>(&context, Mode::Base).map_err(|_| Error::Metadata)?;
|
||||
// t = skS + m
|
||||
let t = self.sk + &m;
|
||||
|
||||
// if t == 0:
|
||||
if bool::from(CS::Group::is_zero_scalar(t)) {
|
||||
// raise InverseError
|
||||
return Err(Error::Protocol);
|
||||
}
|
||||
|
||||
// Z = t^(-1) * R
|
||||
let z = blinded_element.0 * &CS::Group::invert_scalar(t);
|
||||
|
||||
Ok(NonVerifiableServerEvaluateResult {
|
||||
message: EvaluationElement(z),
|
||||
})
|
||||
Ok(EvaluationElement(z))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,7 +522,7 @@ where
|
||||
/// [`Error::Deserialization`] if the private key is not a valid point on
|
||||
/// the group or zero.
|
||||
pub fn new_with_key(key: &[u8]) -> Result<Self> {
|
||||
let sk = CS::Group::deserialize_scalar(key.into())?;
|
||||
let sk = CS::Group::deserialize_scalar(key)?;
|
||||
let pk = CS::Group::base_elem() * &sk;
|
||||
Ok(Self { sk, pk })
|
||||
}
|
||||
@@ -555,7 +552,8 @@ where
|
||||
/// to the client.
|
||||
///
|
||||
/// # Errors
|
||||
/// [`Error::Metadata`] if the `metadata` is longer then `u16::MAX - 21`.
|
||||
/// - [`Error::Metadata`] if the `metadata` is longer then `u16::MAX - 21`.
|
||||
/// - [`Error::Protocol`] if the protocol fails and can't be completed.
|
||||
pub fn evaluate<R: RngCore + CryptoRng>(
|
||||
&self,
|
||||
rng: &mut R,
|
||||
@@ -586,7 +584,8 @@ where
|
||||
/// messages from a [VerifiableClient]
|
||||
///
|
||||
/// # Errors
|
||||
/// [`Error::Metadata`] if the `metadata` is longer then `u16::MAX - 21`.
|
||||
/// - [`Error::Metadata`] if the `metadata` is longer then `u16::MAX - 21`.
|
||||
/// - [`Error::Protocol`] if the protocol fails and can't be completed.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub fn batch_evaluate<'a, R: RngCore + CryptoRng, I>(
|
||||
&self,
|
||||
@@ -628,7 +627,8 @@ where
|
||||
/// [`batch_evaluate_finish`](Self::batch_evaluate_finish).
|
||||
///
|
||||
/// # Errors
|
||||
/// [`Error::Metadata`] if the `metadata` is longer then `u16::MAX - 21`.
|
||||
/// - [`Error::Metadata`] if the `metadata` is longer then `u16::MAX - 21`.
|
||||
/// - [`Error::Protocol`] if the protocol fails and can't be completed.
|
||||
pub fn batch_evaluate_prepare<'a, I: Iterator<Item = &'a BlindedElement<CS>>>(
|
||||
&self,
|
||||
blinded_elements: I,
|
||||
@@ -648,6 +648,13 @@ where
|
||||
let m = CS::Group::hash_to_scalar::<CS>(&context, Mode::Verifiable)
|
||||
.map_err(|_| Error::Metadata)?;
|
||||
let t = self.sk + &m;
|
||||
|
||||
// if t == 0:
|
||||
if bool::from(CS::Group::is_zero_scalar(t)) {
|
||||
// raise InverseError
|
||||
return Err(Error::Protocol);
|
||||
}
|
||||
|
||||
let evaluation_elements = blinded_elements
|
||||
// To make a return type possible, we have to convert to a `fn` pointer, which isn't
|
||||
// possible if we `move` from context.
|
||||
@@ -690,14 +697,14 @@ where
|
||||
u,
|
||||
evaluation_elements
|
||||
.into_iter()
|
||||
.map(|element| element.0.copy()),
|
||||
blinded_elements.map(BlindedElement::copy),
|
||||
.map(|element| element.0.clone()),
|
||||
blinded_elements.cloned(),
|
||||
)?;
|
||||
let messages =
|
||||
evaluation_elements
|
||||
.into_iter()
|
||||
.map(<fn(&PreparedEvaluationElement<CS>) -> _>::from(|element| {
|
||||
element.0.copy()
|
||||
element.0.clone()
|
||||
}));
|
||||
|
||||
Ok(VerifiableServerBatchEvaluateFinishResult { messages, proof })
|
||||
@@ -709,146 +716,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// Convenience Structs //
|
||||
//==================== //
|
||||
/////////////////////////
|
||||
|
||||
/// Contains the fields that are returned by a non-verifiable client blind
|
||||
pub struct NonVerifiableClientBlindResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The state to be persisted on the client
|
||||
pub state: NonVerifiableClient<CS>,
|
||||
/// The message to send to the server
|
||||
pub message: BlindedElement<CS>,
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a non-verifiable server evaluate
|
||||
pub struct NonVerifiableServerEvaluateResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The message to send to the client
|
||||
pub message: EvaluationElement<CS>,
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a verifiable client blind
|
||||
pub struct VerifiableClientBlindResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The state to be persisted on the client
|
||||
pub state: VerifiableClient<CS>,
|
||||
/// The message to send to the server
|
||||
pub message: BlindedElement<CS>,
|
||||
}
|
||||
|
||||
/// Concrete return type for [`VerifiableClient::batch_finalize`].
|
||||
pub type VerifiableClientBatchFinalizeResult<'a, C, I, II, IC, IM> = FinalizeAfterUnblindResult<
|
||||
'a,
|
||||
C,
|
||||
I,
|
||||
Zip<<&'a II as IntoIterator>::IntoIter, VerifiableUnblindResult<'a, C, IC, IM>>,
|
||||
>;
|
||||
|
||||
/// Contains the fields that are returned by a verifiable server evaluate
|
||||
pub struct VerifiableServerEvaluateResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The message to send to the client
|
||||
pub message: EvaluationElement<CS>,
|
||||
/// The proof for the client to verify
|
||||
pub proof: Proof<CS>,
|
||||
}
|
||||
|
||||
/// Contains prepared [`EvaluationElement`]s by a verifiable server batch
|
||||
/// evaluate preparation.
|
||||
pub struct PreparedEvaluationElement<CS: CipherSuite>(EvaluationElement<CS>)
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>;
|
||||
|
||||
/// Contains the prepared `t` by a verifiable server batch evaluate preparation.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Zeroize(drop))]
|
||||
pub struct PreparedTscalar<CS: CipherSuite>(<CS::Group as Group>::Scalar)
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>;
|
||||
|
||||
/// Contains the fields that are returned by a verifiable server batch evaluate
|
||||
/// preparation.
|
||||
pub struct VerifiableServerBatchEvaluatePrepareResult<
|
||||
'a,
|
||||
CS: 'a + CipherSuite,
|
||||
I: Iterator<Item = &'a BlindedElement<CS>>,
|
||||
> where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// Prepared [`EvaluationElement`]s that will become messages.
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub prepared_evaluation_elements: Map<
|
||||
Zip<I, Repeat<<CS::Group as Group>::Scalar>>,
|
||||
fn((&BlindedElement<CS>, <CS::Group as Group>::Scalar)) -> PreparedEvaluationElement<CS>,
|
||||
>,
|
||||
/// Prepared `t` needed to finish the verifiable server batch evaluation.
|
||||
pub t: PreparedTscalar<CS>,
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a verifiable server batch evaluate
|
||||
/// finish.
|
||||
pub struct VerifiableServerBatchEvaluateFinishResult<'a, CS: 'a + CipherSuite, I>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
&'a I: IntoIterator<Item = &'a PreparedEvaluationElement<CS>>,
|
||||
{
|
||||
/// The messages to send to the client
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub messages: Map<
|
||||
<&'a I as IntoIterator>::IntoIter,
|
||||
fn(&PreparedEvaluationElement<CS>) -> EvaluationElement<CS>,
|
||||
>,
|
||||
/// The proof for the client to verify
|
||||
pub proof: Proof<CS>,
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a verifiable server batch evaluate
|
||||
#[cfg(feature = "alloc")]
|
||||
pub struct VerifiableServerBatchEvaluateResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The messages to send to the client
|
||||
pub messages: alloc::vec::Vec<EvaluationElement<CS>>,
|
||||
/// The proof for the client to verify
|
||||
pub proof: Proof<CS>,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// Inner functions and Trait Implementations //
|
||||
// ========================================= //
|
||||
///////////////////////////////////////////////
|
||||
|
||||
impl<CS: CipherSuite> BlindedElement<CS>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// Only used to easier validate allocation
|
||||
fn copy(&self) -> Self {
|
||||
Self(self.0)
|
||||
}
|
||||
|
||||
#[cfg(feature = "danger")]
|
||||
/// Creates a [BlindedElement] from a raw group element.
|
||||
///
|
||||
@@ -872,11 +744,6 @@ where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// Only used to easier validate allocation
|
||||
fn copy(&self) -> Self {
|
||||
Self(self.0)
|
||||
}
|
||||
|
||||
#[cfg(feature = "danger")]
|
||||
/// Creates an [EvaluationElement] from a raw group element.
|
||||
///
|
||||
@@ -895,6 +762,167 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// Convenience Structs //
|
||||
//==================== //
|
||||
/////////////////////////
|
||||
|
||||
/// Contains the fields that are returned by a non-verifiable client blind
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Debug; <CS::Group as Group>::Scalar, <CS::Group as Group>::Elem)]
|
||||
pub struct NonVerifiableClientBlindResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The state to be persisted on the client
|
||||
pub state: NonVerifiableClient<CS>,
|
||||
/// The message to send to the server
|
||||
pub message: BlindedElement<CS>,
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a verifiable client blind
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Debug; <CS::Group as Group>::Scalar, <CS::Group as Group>::Elem)]
|
||||
pub struct VerifiableClientBlindResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The state to be persisted on the client
|
||||
pub state: VerifiableClient<CS>,
|
||||
/// The message to send to the server
|
||||
pub message: BlindedElement<CS>,
|
||||
}
|
||||
|
||||
/// Concrete return type for [`VerifiableClient::batch_finalize`].
|
||||
pub type VerifiableClientBatchFinalizeResult<'a, C, I, II, IC, IM> = FinalizeAfterUnblindResult<
|
||||
'a,
|
||||
C,
|
||||
I,
|
||||
Zip<<&'a II as IntoIterator>::IntoIter, VerifiableUnblindResult<'a, C, IC, IM>>,
|
||||
>;
|
||||
|
||||
/// Contains the fields that are returned by a verifiable server evaluate
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Debug; <CS::Group as Group>::Scalar, <CS::Group as Group>::Elem)]
|
||||
pub struct VerifiableServerEvaluateResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The message to send to the client
|
||||
pub message: EvaluationElement<CS>,
|
||||
/// The proof for the client to verify
|
||||
pub proof: Proof<CS>,
|
||||
}
|
||||
|
||||
/// Contains prepared [`EvaluationElement`]s by a verifiable server batch
|
||||
/// evaluate preparation.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; <CS::Group as Group>::Elem)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct PreparedEvaluationElement<CS: CipherSuite>(EvaluationElement<CS>)
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>;
|
||||
|
||||
/// Contains the prepared `t` by a verifiable server batch evaluate preparation.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; <CS::Group as Group>::Scalar)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(crate = "serde", bound = "")
|
||||
)]
|
||||
pub struct PreparedTscalar<CS: CipherSuite>(
|
||||
#[cfg_attr(feature = "serde", serde(with = "Scalar::<CS::Group>"))]
|
||||
<CS::Group as Group>::Scalar,
|
||||
)
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>;
|
||||
|
||||
/// Concrete type of [`EvaluationElement`]s in
|
||||
/// [`VerifiableServerBatchEvaluatePrepareResult`].
|
||||
pub type VerifiableServerBatchEvaluatePreparedEvaluationElements<CS, I> = Map<
|
||||
Zip<I, Repeat<<<CS as CipherSuite>::Group as Group>::Scalar>>,
|
||||
fn(
|
||||
(
|
||||
&BlindedElement<CS>,
|
||||
<<CS as CipherSuite>::Group as Group>::Scalar,
|
||||
),
|
||||
) -> PreparedEvaluationElement<CS>,
|
||||
>;
|
||||
|
||||
/// Contains the fields that are returned by a verifiable server batch evaluate
|
||||
/// preparation.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Debug; I, <CS::Group as Group>::Scalar)]
|
||||
pub struct VerifiableServerBatchEvaluatePrepareResult<
|
||||
'a,
|
||||
CS: 'a + CipherSuite,
|
||||
I: Iterator<Item = &'a BlindedElement<CS>>,
|
||||
> where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// Prepared [`EvaluationElement`]s that will become messages.
|
||||
pub prepared_evaluation_elements:
|
||||
VerifiableServerBatchEvaluatePreparedEvaluationElements<CS, I>,
|
||||
/// Prepared `t` needed to finish the verifiable server batch evaluation.
|
||||
pub t: PreparedTscalar<CS>,
|
||||
}
|
||||
|
||||
/// Concrete type of [`EvaluationElement`]s in
|
||||
/// [`VerifiableServerBatchEvaluateFinishResult`].
|
||||
pub type VerifiableServerBatchEvaluateFinishedMessages<'a, CS, I> = Map<
|
||||
<&'a I as IntoIterator>::IntoIter,
|
||||
fn(&PreparedEvaluationElement<CS>) -> EvaluationElement<CS>,
|
||||
>;
|
||||
|
||||
/// Contains the fields that are returned by a verifiable server batch evaluate
|
||||
/// finish.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Debug; <&'a I as core::iter::IntoIterator>::IntoIter, <CS::Group as Group>::Scalar)]
|
||||
pub struct VerifiableServerBatchEvaluateFinishResult<'a, CS: 'a + CipherSuite, I>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
&'a I: IntoIterator<Item = &'a PreparedEvaluationElement<CS>>,
|
||||
{
|
||||
/// The [`EvaluationElement`]s to send to the client
|
||||
pub messages: VerifiableServerBatchEvaluateFinishedMessages<'a, CS, I>,
|
||||
/// The proof for the client to verify
|
||||
pub proof: Proof<CS>,
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a verifiable server batch evaluate
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Debug; <CS::Group as Group>::Scalar, <CS::Group as Group>::Elem)]
|
||||
#[cfg(feature = "alloc")]
|
||||
pub struct VerifiableServerBatchEvaluateResult<CS: CipherSuite>
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The messages to send to the client
|
||||
pub messages: alloc::vec::Vec<EvaluationElement<CS>>,
|
||||
/// The proof for the client to verify
|
||||
pub proof: Proof<CS>,
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
// Inner functions //
|
||||
// =============== //
|
||||
/////////////////////
|
||||
|
||||
type BlindResult<C> = (
|
||||
<<C as CipherSuite>::Group as Group>::Scalar,
|
||||
<<C as CipherSuite>::Group as Group>::Elem,
|
||||
@@ -991,7 +1019,7 @@ where
|
||||
.into_iter()
|
||||
// Convert to `fn` pointer to make a return type possible.
|
||||
.map(<fn(&VerifiableClient<CS>) -> _>::from(|x| x.blind));
|
||||
let evaluation_elements = messages.into_iter().map(EvaluationElement::copy);
|
||||
let evaluation_elements = messages.into_iter().cloned();
|
||||
let blinded_elements = clients
|
||||
.into_iter()
|
||||
.map(|client| BlindedElement(client.blinded_element));
|
||||
@@ -1338,12 +1366,12 @@ mod tests {
|
||||
let mut rng = OsRng;
|
||||
let client_blind_result = NonVerifiableClient::<CS>::blind(input, &mut rng).unwrap();
|
||||
let server = NonVerifiableServer::<CS>::new(&mut rng);
|
||||
let server_result = server
|
||||
let message = server
|
||||
.evaluate(&client_blind_result.message, Some(info))
|
||||
.unwrap();
|
||||
let client_finalize_result = client_blind_result
|
||||
.state
|
||||
.finalize(input, &server_result.message, Some(info))
|
||||
.finalize(input, &message, Some(info))
|
||||
.unwrap();
|
||||
let res2 = prf::<CS>(input, server.get_private_key(), info, Mode::Base);
|
||||
assert_eq!(client_finalize_result, res2);
|
||||
@@ -1589,7 +1617,7 @@ mod tests {
|
||||
let mut rng = OsRng;
|
||||
let client_blind_result = NonVerifiableClient::<CS>::blind(input, &mut rng).unwrap();
|
||||
let server = NonVerifiableServer::<CS>::new(&mut rng);
|
||||
let server_result = server
|
||||
let message = server
|
||||
.evaluate(&client_blind_result.message, Some(info))
|
||||
.unwrap();
|
||||
|
||||
@@ -1597,7 +1625,7 @@ mod tests {
|
||||
Zeroize::zeroize(&mut state);
|
||||
assert!(state.serialize().iter().all(|&x| x == 0));
|
||||
|
||||
let mut message = server_result.message;
|
||||
let mut message = message;
|
||||
Zeroize::zeroize(&mut message);
|
||||
assert!(message.serialize().iter().all(|&x| x == 0));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user