Remove CipherSuite (#20)

* Remove `Hash`

* Remove `CipherSuite`

* Remove single field `struct`s
This commit is contained in:
daxpedda
2021-10-05 15:53:18 -07:00
committed by GitHub
parent 2d8780476a
commit 6fb4cad59c
13 changed files with 519 additions and 569 deletions
-17
View File
@@ -1,17 +0,0 @@
// Copyright (c) Facebook, Inc. and its affiliates.
//
// This source code is licensed under both the MIT license found in the
// LICENSE-MIT file in the root directory of this source tree and the Apache
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
// of this source tree.
//! Defines the CipherSuite trait to specify the underlying primitives for VOPRF
/// Configures the underlying primitives used in VOPRF
pub trait CipherSuite {
/// A finite cyclic group along with a point representation that allows some
/// customization on how to hash an input to a curve point. See `group::Group`.
type Group: crate::group::Group;
/// The main hash function to use (for HKDF computations and hashing transcripts).
type Hash: crate::hash::Hash;
}
+1 -2
View File
@@ -6,7 +6,6 @@
// of this source tree.
use crate::errors::InternalError;
use crate::hash::Hash;
use crate::serialization::i2osp;
use alloc::vec::Vec;
use digest::{BlockInput, Digest};
@@ -28,7 +27,7 @@ fn xor(x: &[u8], y: &[u8]) -> Result<Vec<u8>, InternalError> {
/// Corresponds to the expand_message_xmd() function defined in
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt>
pub fn expand_message_xmd<H: Hash>(
pub fn expand_message_xmd<H: BlockInput + Digest>(
msg: &[u8],
dst: &[u8],
len_in_bytes: usize,
+7 -3
View File
@@ -14,8 +14,8 @@ pub(crate) mod p256;
mod ristretto;
use crate::errors::InternalError;
use crate::hash::Hash;
use core::ops::{Add, Mul, Sub};
use digest::{BlockInput, Digest};
use generic_array::{ArrayLength, GenericArray};
use rand::{CryptoRng, RngCore};
use zeroize::Zeroize;
@@ -33,10 +33,14 @@ pub trait Group:
const SUITE_ID: usize;
/// transforms a password and domain separation tag (DST) into a curve point
fn hash_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, InternalError>;
fn hash_to_curve<H: BlockInput + Digest>(msg: &[u8], dst: &[u8])
-> Result<Self, InternalError>;
/// Hashes a slice of pseudo-random bytes to a scalar
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8]) -> Result<Self::Scalar, InternalError>;
fn hash_to_scalar<H: BlockInput + Digest>(
input: &[u8],
dst: &[u8],
) -> Result<Self::Scalar, InternalError>;
/// The type of base field scalars
type Scalar: Zeroize
+9 -3
View File
@@ -15,9 +15,9 @@
use super::Group;
use crate::errors::InternalError;
use crate::hash::Hash;
use core::ops::{Add, Div, Mul, Neg};
use core::str::FromStr;
use digest::{BlockInput, Digest};
use generic_array::typenum::{U32, U33};
use generic_array::{ArrayLength, GenericArray};
use num_bigint::{BigInt, Sign};
@@ -41,7 +41,10 @@ impl Group for ProjectivePoint {
// Implements the `hash_to_curve()` function from
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
fn hash_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, InternalError> {
fn hash_to_curve<H: BlockInput + Digest>(
msg: &[u8],
dst: &[u8],
) -> Result<Self, InternalError> {
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2
// `p: 2^256 - 2^224 + 2^192 + 2^96 - 1`
const P: Lazy<BigInt> = Lazy::new(|| {
@@ -89,7 +92,10 @@ impl Group for ProjectivePoint {
// Implements the `HashToScalar()` function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.3
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8]) -> Result<Self::Scalar, InternalError> {
fn hash_to_scalar<H: BlockInput + Digest>(
input: &[u8],
dst: &[u8],
) -> Result<Self::Scalar, InternalError> {
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#[{%22num%22:211,%22gen%22:0},{%22name%22:%22XYZ%22},70,700,0]
// P-256 `n` is defined as `115792089210356248762697446949407573529996955224135760342 422259061068512044369`
const N: Lazy<BigInt> = Lazy::new(|| {
+9 -3
View File
@@ -7,7 +7,6 @@
use super::Group;
use crate::errors::InternalError;
use crate::hash::Hash;
use core::convert::TryInto;
use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_POINT,
@@ -15,6 +14,7 @@ use curve25519_dalek::{
scalar::Scalar,
traits::Identity,
};
use digest::{BlockInput, Digest};
use generic_array::{typenum::U32, GenericArray};
use rand::{CryptoRng, RngCore};
use subtle::ConstantTimeEq;
@@ -25,7 +25,10 @@ impl Group for RistrettoPoint {
// Implements the `hash_to_ristretto255()` function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt
fn hash_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, InternalError> {
fn hash_to_curve<H: BlockInput + Digest>(
msg: &[u8],
dst: &[u8],
) -> Result<Self, InternalError> {
let uniform_bytes = super::expand::expand_message_xmd::<H>(msg, dst, 64)?;
Ok(RistrettoPoint::from_uniform_bytes(
@@ -38,7 +41,10 @@ impl Group for RistrettoPoint {
// Implements the `HashToScalar()` function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.1
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8]) -> Result<Self::Scalar, InternalError> {
fn hash_to_scalar<H: BlockInput + Digest>(
input: &[u8],
dst: &[u8],
) -> Result<Self::Scalar, InternalError> {
let uniform_bytes = super::expand::expand_message_xmd::<H>(input, dst, 64)?;
Ok(Scalar::from_bytes_mod_order_wide(
+12 -13
View File
@@ -9,42 +9,41 @@
use crate::errors::InternalError;
use crate::group::Group;
use crate::CipherSuite;
// Test that the deserialization of a group element should throw an error
// if the identity element can be deserialized properly
#[test]
fn test_group_properties() -> Result<(), InternalError> {
use crate::tests::Ristretto255Sha512;
use curve25519_dalek::ristretto::RistrettoPoint;
test_identity_element_error::<Ristretto255Sha512>()?;
test_zero_scalar_error::<Ristretto255Sha512>()?;
test_identity_element_error::<RistrettoPoint>()?;
test_zero_scalar_error::<RistrettoPoint>()?;
#[cfg(feature = "p256")]
{
use crate::tests::P256Sha256;
use p256_::ProjectivePoint;
test_identity_element_error::<P256Sha256>()?;
test_zero_scalar_error::<P256Sha256>()?;
test_identity_element_error::<ProjectivePoint>()?;
test_zero_scalar_error::<ProjectivePoint>()?;
}
Ok(())
}
// Checks that the identity element cannot be deserialized
fn test_identity_element_error<CS: CipherSuite>() -> Result<(), InternalError> {
let identity = CS::Group::identity();
let result = CS::Group::from_element_slice(&identity.to_arr());
fn test_identity_element_error<G: Group>() -> Result<(), InternalError> {
let identity = G::identity();
let result = G::from_element_slice(&identity.to_arr());
assert!(matches!(result, Err(InternalError::PointError)));
Ok(())
}
// Checks that the zero scalar cannot be deserialized
fn test_zero_scalar_error<CS: CipherSuite>() -> Result<(), InternalError> {
let zero_scalar = CS::Group::scalar_zero();
let result = CS::Group::from_scalar_slice(&CS::Group::scalar_as_bytes(zero_scalar));
fn test_zero_scalar_error<G: Group>() -> Result<(), InternalError> {
let zero_scalar = G::scalar_zero();
let result = G::from_scalar_slice(&G::scalar_as_bytes(zero_scalar));
assert!(matches!(result, Err(InternalError::ZeroScalarError)));
Ok(())
-17
View File
@@ -1,17 +0,0 @@
// Copyright (c) Facebook, Inc. and its affiliates.
//
// This source code is licensed under both the MIT license found in the
// LICENSE-MIT file in the root directory of this source tree and the Apache
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
// of this source tree.
//! A convenience trait for digest bounds used throughout the library
use digest::{BlockInput, FixedOutput, Reset, Update};
/// Trait inheriting the requirements from digest::Digest for compatibility with HKDF and HMAC
// Associated types could be simplified when they are made as defaults:
// https://github.com/rust-lang/rust/issues/29661
pub trait Hash: Update + BlockInput + FixedOutput + Reset + Default + Clone {}
impl<T: Update + BlockInput + FixedOutput + Reset + Default + Clone> Hash for T {}
+50 -42
View File
@@ -6,8 +6,8 @@
// of this source tree.
macro_rules! impl_debug_eq_hash_for {
(struct $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound)?),+>)? core::fmt::Debug for $name$(<$($gen),+>)?
(struct $name:ident$(<$($gen:ident$(: $bound1:tt$( + $bound2:tt)*)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound1$( + $bound2)*)?),+>)? core::fmt::Debug for $name$(<$($gen),+>)?
$(where $($type: core::fmt::Debug,)+)?
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
@@ -18,11 +18,11 @@ macro_rules! impl_debug_eq_hash_for {
}
}
impl$(<$($gen$(: $bound)?),+>)? Eq for $name$(<$($gen),+>)?
impl$(<$($gen$(: $bound1$( + $bound2)*)?),+>)? Eq for $name$(<$($gen),+>)?
$(where $($type: Eq,)+)?
{}
impl$(<$($gen$(: $bound)?),+>)? PartialEq for $name$(<$($gen),+>)?
impl$(<$($gen$(: $bound1$( + $bound2)*)?),+>)? PartialEq for $name$(<$($gen),+>)?
$(where $($type: PartialEq,)+)?
{
fn eq(&self, other: &Self) -> bool {
@@ -31,17 +31,17 @@ macro_rules! impl_debug_eq_hash_for {
}
}
impl$(<$($gen$(: $bound)?),+>)? core::hash::Hash for $name$(<$($gen),+>)?
impl$(<$($gen$(: $bound1$( + $bound2)*)?),+>)? core::hash::Hash for $name$(<$($gen),+>)?
$(where $($type: core::hash::Hash,)+)?
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
fn hash<_H: core::hash::Hasher>(&self, state: &mut _H) {
core::hash::Hash::hash(&self.$field1, state);
$(core::hash::Hash::hash(&self.$field2, state);)*
}
}
};
(tuple $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:tt$(, $field2:tt)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound)?),+>)? core::fmt::Debug for $name$(<$($gen),+>)?
(tuple $name:ident$(<$($gen:ident$(: $bound1:tt$( + $bound2:tt)*)?),+$(,)?>)?, [$field1:tt$(, $field2:tt)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? core::fmt::Debug for $name$(<$($gen),+>)?
$(where $($type: core::fmt::Debug,)+)?
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
@@ -52,11 +52,11 @@ macro_rules! impl_debug_eq_hash_for {
}
}
impl$(<$($gen$(: $bound)?),+>)? Eq for $name$(<$($gen),+>)?
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? Eq for $name$(<$($gen),+>)?
$(where $($type: Eq,)+)?
{}
impl$(<$($gen$(: $bound)?),+>)? PartialEq for $name$(<$($gen),+>)?
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? PartialEq for $name$(<$($gen),+>)?
$(where $($type: PartialEq,)+)?
{
fn eq(&self, other: &Self) -> bool {
@@ -65,7 +65,7 @@ macro_rules! impl_debug_eq_hash_for {
}
}
impl$(<$($gen$(: $bound)?),+>)? core::hash::Hash for $name$(<$($gen),+>)?
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? core::hash::Hash for $name$(<$($gen),+>)?
$(where $($type: core::hash::Hash,)+)?
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
@@ -77,8 +77,8 @@ macro_rules! impl_debug_eq_hash_for {
}
macro_rules! impl_clone_for {
(struct $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound)?),+>)? Clone for $name$(<$($gen),+>)?
(struct $name:ident$(<$($gen:ident$(: $bound1:tt$( + $bound2:tt)*)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? Clone for $name$(<$($gen),+>)?
$(where $($type: Clone,)+)?
{
fn clone(&self) -> Self {
@@ -89,8 +89,8 @@ macro_rules! impl_clone_for {
}
}
};
(tuple $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:tt$(, $field2:tt)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound)?),+>)? Clone for $name$(<$($gen),+>)?
(tuple $name:ident$(<$($gen:ident$(: $bound1:tt$( + $bound2:tt)*)?),+$(,)?>)?, [$field1:tt$(, $field2:tt)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? Clone for $name$(<$($gen),+>)?
$(where $($type: Clone,)+)?
{
fn clone(&self) -> Self {
@@ -103,23 +103,30 @@ macro_rules! impl_clone_for {
};
}
macro_rules! impl_zeroize_field_skip_pd {
($self_:ident, $field:ident, PH) => {};
($self_:ident, $field:ident) => {
$self_.$field.zeroize();
};
}
macro_rules! impl_zeroize_on_drop_for {
(struct $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound)?),+>)? zeroize::Zeroize for $name$(<$($gen),+>)?
(struct $name:ident$(<$($gen:ident$(: $bound1:tt$( + $bound2:tt)*)?),+$(,)?>)?, [$(#[$pd1:ident] )?$field1:ident$(, $(#[$pd2:ident] )?$field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? zeroize::Zeroize for $name$(<$($gen),+>)?
{
fn zeroize(&mut self) {
self.$field1.zeroize();
$(self.$field2.zeroize();)*
impl_zeroize_field_skip_pd!(self, $field1$(, $pd1)?);
$(impl_zeroize_field_skip_pd!(self, $field2$(, $pd2)?);)*
}
}
impl$(<$($gen$(: $bound)?),+>)? Drop for $name$(<$($gen),+>)?
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? Drop for $name$(<$($gen),+>)?
{
fn drop(&mut self) {
#[allow(unused_imports)]
use zeroize::Zeroize;
self.$field1.zeroize();
$(self.$field2.zeroize();)*
impl_zeroize_field_skip_pd!(self, $field1$(, $pd1)?);
$(impl_zeroize_field_skip_pd!(self, $field2$(, $pd2)?);)*
}
}
};
@@ -127,10 +134,10 @@ macro_rules! impl_zeroize_on_drop_for {
/// Inner macro used for deriving `serde`'s `Serialize` and `Deserialize` traits.
macro_rules! impl_serialize_and_deserialize_for {
($t:ident) => {
($name:ident$(<$($gen:ident$(: $bound1:tt$( + $bound2:tt)*)?),+$(,)?>)?) => {
#[cfg(feature = "serialize")]
#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
impl<CS: CipherSuite> serde::Serialize for $t<CS> {
impl$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)? serde::Serialize for $name$(<$($gen),+>)? {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
@@ -145,28 +152,29 @@ macro_rules! impl_serialize_and_deserialize_for {
#[cfg(feature = "serialize")]
#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
impl<'de, CS: CipherSuite> serde::Deserialize<'de> for $t<CS> {
impl<'de$(, $($gen$(: $bound1$(+ $bound2)*)?),+)?> serde::Deserialize<'de> for $name$(<$($gen),+>)? {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
if deserializer.is_human_readable() {
let s = <&str>::deserialize(deserializer)?;
$t::<CS>::deserialize(&base64::decode(s).map_err(serde::de::Error::custom)?)
$name$(::<$($gen),+>)?::deserialize(&base64::decode(s).map_err(serde::de::Error::custom)?)
.map_err(serde::de::Error::custom)
} else {
struct ByteVisitor<CS: CipherSuite> {
marker: core::marker::PhantomData<CS>,
}
impl<'de, CS: CipherSuite> serde::de::Visitor<'de> for ByteVisitor<CS> {
type Value = $t<CS>;
struct ByteVisitor$(<$($gen$(: $bound1$(+ $bound2)*)?),+> (
#[allow(unused_parens)]
core::marker::PhantomData<($($gen),+)>,
))?;
impl<'de$(, $($gen$(: $bound1$(+ $bound2)*)?),+)?> serde::de::Visitor<'de> for ByteVisitor$(<$($gen),+>)? {
type Value = $name$(<$($gen),+>)?;
fn expecting(
&self,
formatter: &mut core::fmt::Formatter,
) -> core::fmt::Result {
formatter.write_str(core::concat!(
"the byte representation of a ",
core::stringify!($t)
core::stringify!($name)
))
}
@@ -174,20 +182,20 @@ macro_rules! impl_serialize_and_deserialize_for {
where
E: serde::de::Error,
{
$t::<CS>::deserialize(value).map_err(|_| {
$name$(::<$($gen),+>)?::deserialize(value).map_err(|_| {
serde::de::Error::invalid_value(
serde::de::Unexpected::Bytes(value),
&core::concat!(
"invalid byte sequence for ",
core::stringify!($t)
core::stringify!($name)
),
)
})
}
}
deserializer.deserialize_bytes(ByteVisitor::<CS> {
marker: core::marker::PhantomData,
})
deserializer.deserialize_bytes(ByteVisitor$(::<$($gen),+> (
core::marker::PhantomData,
))?)
}
}
}
@@ -196,10 +204,10 @@ macro_rules! impl_serialize_and_deserialize_for {
// Convenience macro for implementing all of the above traits
macro_rules! impl_traits_for {
(struct $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl_debug_eq_hash_for!(struct $name$(<$($gen$(: $bound)?),+>)?, [$field1$(, $field2)*], $([$($type),+])?);
impl_clone_for!(struct $name$(<$($gen$(: $bound)?),+>)?, [$field1$(, $field2)*], $([$($type),+])?);
impl_zeroize_on_drop_for!(struct $name$(<$($gen$(: $bound)?),+>)?, [$field1$(, $field2)*], $([$($type),+])?);
impl_serialize_and_deserialize_for!($name);
(struct $name:ident$(<$($gen:ident$(: $bound1:tt$( + $bound2:tt)*)?),+$(,)?>)?, [$(#[$pd1:ident] )?$field1:ident$(, $(#[$pd2:ident] )?$field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl_debug_eq_hash_for!(struct $name$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)?, [$field1$(, $field2)*], $([$($type),+])?);
impl_clone_for!(struct $name$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)?, [$field1$(, $field2)*], $([$($type),+])?);
impl_zeroize_on_drop_for!(struct $name$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)?, [$(#[$pd1] )?$field1$(, $(#[$pd2] )?$field2)*], $([$($type),+])?);
impl_serialize_and_deserialize_for!($name$(<$($gen$(: $bound1$(+ $bound2)*)?),+>)?);
}
}
+24 -75
View File
@@ -24,12 +24,8 @@
//! We will use the following choices in this example:
//!
//! ```
//! use voprf::CipherSuite;
//! struct Default;
//! impl CipherSuite for Default {
//! type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! type Hash = sha2::Sha512;
//! }
//! ```
//!
//! ## Modes of Operation
@@ -56,17 +52,13 @@
//! client evaluations.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! use voprf::NonVerifiableServer;
//! use rand::{rngs::OsRng, RngCore};
//!
//! let mut server_rng = OsRng;
//! let server = NonVerifiableServer::<Default>::new(&mut server_rng)
//! let server = NonVerifiableServer::<Group, Hash>::new(&mut server_rng)
//! .expect("Unable to construct server");
//! ```
//!
@@ -79,17 +71,13 @@
//! step of the VOPRF protocol.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! use voprf::NonVerifiableClient;
//! use rand::{rngs::OsRng, RngCore};
//!
//! let mut client_rng = OsRng;
//! let client_blind_result = NonVerifiableClient::<Default>::blind(
//! let client_blind_result = NonVerifiableClient::<Group, Hash>::blind(
//! b"input",
//! &mut client_rng,
//! ).expect("Unable to construct client");
@@ -104,23 +92,19 @@
//! [EvaluationElement] to be sent to the client.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! # use voprf::NonVerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
//! # let mut client_rng = OsRng;
//! # let client_blind_result = NonVerifiableClient::<Default>::blind(
//! # let client_blind_result = NonVerifiableClient::<Group, Hash>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
//! # use voprf::NonVerifiableServer;
//! # let mut server_rng = OsRng;
//! # let server = NonVerifiableServer::<Default>::new(&mut server_rng)
//! # let server = NonVerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server");
//! use voprf::Metadata;
//! let server_evaluate_result = server.evaluate(
@@ -138,23 +122,19 @@
//! output for the protocol.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! # use voprf::NonVerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
//! # let mut client_rng = OsRng;
//! # let client_blind_result = NonVerifiableClient::<Default>::blind(
//! # let client_blind_result = NonVerifiableClient::<Group, Hash>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
//! # use voprf::NonVerifiableServer;
//! # let mut server_rng = OsRng;
//! # let server = NonVerifiableServer::<Default>::new(&mut server_rng)
//! # let server = NonVerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server");
//! # let server_evaluate_result = server.evaluate(
//! # client_blind_result.message,
@@ -166,7 +146,7 @@
//! &Metadata::none(),
//! ).expect("Unable to perform client finalization");
//!
//! println!("VOPRF output: {:?}", client_finalize_result.output.to_vec());
//! println!("VOPRF output: {:?}", client_finalize_result.to_vec());
//! ```
//!
//! ## Verifiable Mode
@@ -189,17 +169,13 @@
//! client evaluations.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! use voprf::VerifiableServer;
//! use rand::{rngs::OsRng, RngCore};
//!
//! let mut server_rng = OsRng;
//! let server = VerifiableServer::<Default>::new(&mut server_rng)
//! let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
//! .expect("Unable to construct server");
//!
//! // To be sent to the client
@@ -219,17 +195,13 @@
//! step of the VOPRF protocol.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! use voprf::VerifiableClient;
//! use rand::{rngs::OsRng, RngCore};
//!
//! let mut client_rng = OsRng;
//! let client_blind_result = VerifiableClient::<Default>::blind(
//! let client_blind_result = VerifiableClient::<Group, Hash>::blind(
//! b"input",
//! &mut client_rng,
//! ).expect("Unable to construct client");
@@ -244,23 +216,19 @@
//! [EvaluationElement] to be sent to the client along with a proof.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
//! # let mut client_rng = OsRng;
//! # let client_blind_result = VerifiableClient::<Default>::blind(
//! # let client_blind_result = VerifiableClient::<Group, Hash>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
//! # use voprf::VerifiableServer;
//! # let mut server_rng = OsRng;
//! # let server = VerifiableServer::<Default>::new(&mut server_rng)
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server");
//! use voprf::Metadata;
//! let server_evaluate_result = server.evaluate(
@@ -280,23 +248,19 @@
//! output for the protocol.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
//! # let mut client_rng = OsRng;
//! # let client_blind_result = VerifiableClient::<Default>::blind(
//! # let client_blind_result = VerifiableClient::<Group, Hash>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
//! # use voprf::VerifiableServer;
//! # let mut server_rng = OsRng;
//! # let server = VerifiableServer::<Default>::new(&mut server_rng)
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server");
//! # let server_evaluate_result = server.evaluate(
//! # &mut server_rng,
@@ -311,7 +275,7 @@
//! &Metadata::none(),
//! ).expect("Unable to perform client finalization");
//!
//! println!("VOPRF output: {:?}", client_finalize_result.output.to_vec());
//! println!("VOPRF output: {:?}", client_finalize_result.to_vec());
//! ```
//!
//! # Advanced Usage
@@ -333,12 +297,8 @@
//! states and messages:
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -346,7 +306,7 @@
//! let mut client_states = vec![];
//! let mut client_messages = vec![];
//! for _ in 0..10 {
//! let client_blind_result = VerifiableClient::<Default>::blind(
//! let client_blind_result = VerifiableClient::<Group, Hash>::blind(
//! b"input",
//! &mut client_rng,
//! ).expect("Unable to construct client");
@@ -361,12 +321,8 @@
//! along with a single proof:
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -374,7 +330,7 @@
//! # let mut client_states = vec![];
//! # let mut client_messages = vec![];
//! # for _ in 0..10 {
//! # let client_blind_result = VerifiableClient::<Default>::blind(
//! # let client_blind_result = VerifiableClient::<Group, Hash>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
@@ -384,7 +340,7 @@
//! # use voprf::Metadata;
//! # use voprf::VerifiableServer;
//! let mut server_rng = OsRng;
//! # let server = VerifiableServer::<Default>::new(&mut server_rng)
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server");
//! let server_batch_evaluate_result = server.batch_evaluate(
//! &mut server_rng,
@@ -400,12 +356,8 @@
//! verifies correctly.
//!
//! ```
//! # use voprf::CipherSuite;
//! # struct Default;
//! # impl CipherSuite for Default {
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # type Hash = sha2::Sha512;
//! # }
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -413,7 +365,7 @@
//! # let mut client_states = vec![];
//! # let mut client_messages = vec![];
//! # for _ in 0..10 {
//! # let client_blind_result = VerifiableClient::<Default>::blind(
//! # let client_blind_result = VerifiableClient::<Group, Hash>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
@@ -424,7 +376,7 @@
//! # use voprf::VerifiableServer;
//! use voprf::BatchFinalizeInput;
//! let mut server_rng = OsRng;
//! # let server = VerifiableServer::<Default>::new(&mut server_rng)
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server");
//! # let server_batch_evaluate_result = server.batch_evaluate(
//! # &mut server_rng,
@@ -442,7 +394,7 @@
//! &Metadata::none(),
//! ).expect("Unable to perform client batch finalization");
//!
//! println!("VOPRF batch outputs: {:?}", client_batch_finalize_result.outputs);
//! println!("VOPRF batch outputs: {:?}", client_batch_finalize_result);
//! ```
//!
//! ## Metadata
@@ -459,7 +411,7 @@
//!
//! # Features
//!
//! - The `p256` feature enables using p256 as the underlying group for the [CipherSuite] choice.
//! - The `p256` feature enables using p256 as the underlying group for the [Group](group::Group) choice.
//! Note that this is currently an experimental feature ⚠️, and is not yet ready for production use.
//!
//! - The `serialize` feature, enabled by default, provides convenience functions for serializing and deserializing with
@@ -484,10 +436,8 @@ extern crate alloc;
mod impls;
#[macro_use]
mod serialization;
mod ciphersuite;
pub mod errors;
pub mod group;
pub mod hash;
mod voprf;
#[cfg(test)]
@@ -497,10 +447,9 @@ mod tests;
pub use rand;
pub use crate::ciphersuite::CipherSuite;
pub use crate::voprf::{
BatchFinalizeInput, BlindedElement, EvaluationElement, Metadata, NonVerifiableClient,
NonVerifiableClientBlindResult, NonVerifiableClientFinalizeResult, NonVerifiableServer,
NonVerifiableServerEvaluateResult, VerifiableClient, VerifiableClientBlindResult,
VerifiableClientFinalizeResult, VerifiableServer, VerifiableServerEvaluateResult,
NonVerifiableClientBlindResult, NonVerifiableServer, NonVerifiableServerEvaluateResult,
VerifiableClient, VerifiableClientBlindResult, VerifiableServer,
VerifiableServerEvaluateResult,
};
+50 -38
View File
@@ -9,7 +9,6 @@
//! in the VOPRF protocol
use crate::{
ciphersuite::CipherSuite,
errors::InternalError,
group::Group,
voprf::{
@@ -18,6 +17,8 @@ use crate::{
},
};
use alloc::vec::Vec;
use core::marker::PhantomData;
use digest::{BlockInput, Digest};
use generic_array::{typenum::Unsigned, GenericArray};
//////////////////////////////////////////////////////////
@@ -25,35 +26,35 @@ use generic_array::{typenum::Unsigned, GenericArray};
// ==================================================== //
//////////////////////////////////////////////////////////
impl<CS: CipherSuite> NonVerifiableClient<CS> {
impl<G: Group, H: BlockInput + Digest> NonVerifiableClient<G, H> {
/// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> {
[
CS::Group::scalar_as_bytes(self.blind).to_vec(),
self.data.clone(),
]
.concat()
[G::scalar_as_bytes(self.blind).to_vec(), self.data.clone()].concat()
}
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, InternalError> {
let scalar_len = <CS::Group as Group>::ScalarLen::USIZE;
let scalar_len = <G as Group>::ScalarLen::USIZE;
if input.len() < scalar_len {
return Err(InternalError::SizeError);
}
let blind = CS::Group::from_scalar_slice(GenericArray::from_slice(&input[..scalar_len]))?;
let blind = G::from_scalar_slice(GenericArray::from_slice(&input[..scalar_len]))?;
let data = input[scalar_len..].to_vec();
Ok(Self { blind, data })
Ok(Self {
blind,
data,
hash: PhantomData,
})
}
}
impl<CS: CipherSuite> VerifiableClient<CS> {
impl<G: Group, H: BlockInput + Digest> VerifiableClient<G, H> {
/// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> {
[
CS::Group::scalar_as_bytes(self.blind).to_vec(),
G::scalar_as_bytes(self.blind).to_vec(),
self.blinded_element.to_arr().to_vec(),
self.data.clone(),
]
@@ -62,14 +63,14 @@ impl<CS: CipherSuite> VerifiableClient<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, InternalError> {
let scalar_len = <CS::Group as Group>::ScalarLen::USIZE;
let elem_len = <CS::Group as Group>::ElemLen::USIZE;
let scalar_len = <G as Group>::ScalarLen::USIZE;
let elem_len = <G as Group>::ElemLen::USIZE;
if input.len() < scalar_len + elem_len {
return Err(InternalError::SizeError);
}
let blind = CS::Group::from_scalar_slice(GenericArray::from_slice(&input[..scalar_len]))?;
let blinded_element = CS::Group::from_element_slice(GenericArray::from_slice(
let blind = G::from_scalar_slice(GenericArray::from_slice(&input[..scalar_len]))?;
let blinded_element = G::from_element_slice(GenericArray::from_slice(
&input[scalar_len..scalar_len + elem_len],
))?;
let data = input[scalar_len + elem_len..].to_vec();
@@ -78,34 +79,38 @@ impl<CS: CipherSuite> VerifiableClient<CS> {
blind,
blinded_element,
data,
hash: PhantomData,
})
}
}
impl<CS: CipherSuite> NonVerifiableServer<CS> {
impl<G: Group, H: BlockInput + Digest> NonVerifiableServer<G, H> {
/// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> {
CS::Group::scalar_as_bytes(self.sk).to_vec()
G::scalar_as_bytes(self.sk).to_vec()
}
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, InternalError> {
let scalar_len = <CS::Group as Group>::ScalarLen::USIZE;
let scalar_len = <G as Group>::ScalarLen::USIZE;
if input.len() != scalar_len {
return Err(InternalError::SizeError);
}
let sk = CS::Group::from_scalar_slice(GenericArray::from_slice(input))?;
let sk = G::from_scalar_slice(GenericArray::from_slice(input))?;
Ok(Self { sk })
Ok(Self {
sk,
hash: PhantomData,
})
}
}
impl<CS: CipherSuite> VerifiableServer<CS> {
impl<G: Group, H: BlockInput + Digest> VerifiableServer<G, H> {
/// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> {
[
CS::Group::scalar_as_bytes(self.sk).to_vec(),
G::scalar_as_bytes(self.sk).to_vec(),
self.pk.to_arr().to_vec(),
]
.concat()
@@ -113,43 +118,48 @@ impl<CS: CipherSuite> VerifiableServer<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, InternalError> {
let scalar_len = <CS::Group as Group>::ScalarLen::USIZE;
let elem_len = <CS::Group as Group>::ElemLen::USIZE;
let scalar_len = <G as Group>::ScalarLen::USIZE;
let elem_len = <G as Group>::ElemLen::USIZE;
if input.len() != scalar_len + elem_len {
return Err(InternalError::SizeError);
}
let sk = CS::Group::from_scalar_slice(GenericArray::from_slice(&input[..scalar_len]))?;
let pk = CS::Group::from_element_slice(GenericArray::from_slice(&input[scalar_len..]))?;
let sk = G::from_scalar_slice(GenericArray::from_slice(&input[..scalar_len]))?;
let pk = G::from_element_slice(GenericArray::from_slice(&input[scalar_len..]))?;
Ok(Self { sk, pk })
Ok(Self {
sk,
pk,
hash: PhantomData,
})
}
}
impl<CS: CipherSuite> Proof<CS> {
impl<G: Group, H: BlockInput + Digest> Proof<G, H> {
/// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> {
[
CS::Group::scalar_as_bytes(self.c_scalar),
CS::Group::scalar_as_bytes(self.s_scalar),
G::scalar_as_bytes(self.c_scalar),
G::scalar_as_bytes(self.s_scalar),
]
.concat()
}
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, InternalError> {
let scalar_len = <CS::Group as Group>::ScalarLen::USIZE;
let scalar_len = <G as Group>::ScalarLen::USIZE;
if input.len() < scalar_len + scalar_len {
return Err(InternalError::SizeError);
}
Ok(Proof {
c_scalar: CS::Group::from_scalar_slice(GenericArray::from_slice(&input[..scalar_len]))?,
s_scalar: CS::Group::from_scalar_slice(GenericArray::from_slice(&input[scalar_len..]))?,
c_scalar: G::from_scalar_slice(GenericArray::from_slice(&input[..scalar_len]))?,
s_scalar: G::from_scalar_slice(GenericArray::from_slice(&input[scalar_len..]))?,
hash: PhantomData,
})
}
}
impl<CS: CipherSuite> BlindedElement<CS> {
impl<G: Group, H: BlockInput + Digest> BlindedElement<G, H> {
/// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> {
self.value.to_arr().to_vec()
@@ -158,12 +168,13 @@ impl<CS: CipherSuite> BlindedElement<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, InternalError> {
Ok(Self {
value: CS::Group::from_element_slice(GenericArray::from_slice(input))?,
value: G::from_element_slice(GenericArray::from_slice(input))?,
hash: PhantomData,
})
}
}
impl<CS: CipherSuite> EvaluationElement<CS> {
impl<G: Group, H: BlockInput + Digest> EvaluationElement<G, H> {
/// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> {
self.value.to_arr().to_vec()
@@ -172,7 +183,8 @@ impl<CS: CipherSuite> EvaluationElement<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, InternalError> {
Ok(Self {
value: CS::Group::from_element_slice(GenericArray::from_slice(input))?,
value: G::from_element_slice(GenericArray::from_slice(input))?,
hash: PhantomData,
})
}
}
-15
View File
@@ -9,18 +9,3 @@ mod mock_rng;
mod parser;
mod voprf_test_vectors;
mod voprf_vectors;
/// Ciphersuite definitions for tests
pub(crate) struct Ristretto255Sha512;
impl crate::CipherSuite for Ristretto255Sha512 {
type Group = curve25519_dalek::ristretto::RistrettoPoint;
type Hash = sha2::Sha512;
}
#[cfg(feature = "p256")]
pub(crate) struct P256Sha256;
#[cfg(feature = "p256")]
impl crate::CipherSuite for P256Sha256 {
type Group = p256_::ProjectivePoint;
type Hash = sha2::Sha256;
}
+46 -48
View File
@@ -6,7 +6,6 @@
// of this source tree.
use crate::{
ciphersuite::CipherSuite,
errors::InternalError,
group::Group,
tests::{mock_rng::CycleRng, parser::*},
@@ -17,6 +16,7 @@ use crate::{
};
use alloc::string::ToString;
use alloc::vec::Vec;
use digest::{BlockInput, Digest};
use generic_array::GenericArray;
use json::JsonValue;
@@ -85,7 +85,8 @@ fn test_vectors() -> Result<(), InternalError> {
let rfc = json::parse(rfc_to_json(super::voprf_vectors::VECTORS).as_str())
.expect("Could not parse json");
use crate::tests::Ristretto255Sha512;
use curve25519_dalek::ristretto::RistrettoPoint;
use sha2::Sha512;
let ristretto_base_tvs = json_to_test_vectors!(
rfc,
@@ -99,19 +100,20 @@ fn test_vectors() -> Result<(), InternalError> {
String::from("Verifiable")
);
test_base_seed_to_key::<Ristretto255Sha512>(&ristretto_base_tvs)?;
test_base_blind::<Ristretto255Sha512>(&ristretto_base_tvs)?;
test_base_evaluate::<Ristretto255Sha512>(&ristretto_base_tvs)?;
test_base_finalize::<Ristretto255Sha512>(&ristretto_base_tvs)?;
test_base_seed_to_key::<RistrettoPoint, Sha512>(&ristretto_base_tvs)?;
test_base_blind::<RistrettoPoint, Sha512>(&ristretto_base_tvs)?;
test_base_evaluate::<RistrettoPoint, Sha512>(&ristretto_base_tvs)?;
test_base_finalize::<RistrettoPoint, Sha512>(&ristretto_base_tvs)?;
test_verifiable_seed_to_key::<Ristretto255Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_blind::<Ristretto255Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_evaluate::<Ristretto255Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_finalize::<Ristretto255Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_seed_to_key::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_blind::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_evaluate::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_finalize::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
#[cfg(feature = "p256")]
{
use crate::tests::P256Sha256;
use p256_::ProjectivePoint;
use sha2::Sha256;
let p256_base_tvs =
json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("Base"));
@@ -122,43 +124,43 @@ fn test_vectors() -> Result<(), InternalError> {
String::from("Verifiable")
);
test_base_seed_to_key::<P256Sha256>(&p256_base_tvs)?;
test_base_blind::<P256Sha256>(&p256_base_tvs)?;
test_base_evaluate::<P256Sha256>(&p256_base_tvs)?;
test_base_finalize::<P256Sha256>(&p256_base_tvs)?;
test_base_seed_to_key::<ProjectivePoint, Sha256>(&p256_base_tvs)?;
test_base_blind::<ProjectivePoint, Sha256>(&p256_base_tvs)?;
test_base_evaluate::<ProjectivePoint, Sha256>(&p256_base_tvs)?;
test_base_finalize::<ProjectivePoint, Sha256>(&p256_base_tvs)?;
test_verifiable_seed_to_key::<P256Sha256>(&p256_verifiable_tvs)?;
test_verifiable_blind::<P256Sha256>(&p256_verifiable_tvs)?;
test_verifiable_evaluate::<P256Sha256>(&p256_verifiable_tvs)?;
test_verifiable_finalize::<P256Sha256>(&p256_verifiable_tvs)?;
test_verifiable_seed_to_key::<ProjectivePoint, Sha256>(&p256_verifiable_tvs)?;
test_verifiable_blind::<ProjectivePoint, Sha256>(&p256_verifiable_tvs)?;
test_verifiable_evaluate::<ProjectivePoint, Sha256>(&p256_verifiable_tvs)?;
test_verifiable_finalize::<ProjectivePoint, Sha256>(&p256_verifiable_tvs)?;
}
Ok(())
}
fn test_base_seed_to_key<CS: CipherSuite>(
fn test_base_seed_to_key<G: Group, H: BlockInput + Digest>(
tvs: &[VOPRFTestVectorParameters],
) -> Result<(), InternalError> {
for parameters in tvs {
let server = NonVerifiableServer::<CS>::new_from_seed(&parameters.seed)?;
let server = NonVerifiableServer::<G, H>::new_from_seed(&parameters.seed)?;
assert_eq!(
&parameters.sksm,
&CS::Group::scalar_as_bytes(server.get_private_key()).to_vec()
&G::scalar_as_bytes(server.get_private_key()).to_vec()
);
}
Ok(())
}
fn test_verifiable_seed_to_key<CS: CipherSuite>(
fn test_verifiable_seed_to_key<G: Group, H: BlockInput + Digest>(
tvs: &[VOPRFTestVectorParameters],
) -> Result<(), InternalError> {
for parameters in tvs {
let server = VerifiableServer::<CS>::new_from_seed(&parameters.seed)?;
let server = VerifiableServer::<G, H>::new_from_seed(&parameters.seed)?;
assert_eq!(
&parameters.sksm,
&CS::Group::scalar_as_bytes(server.get_private_key()).to_vec()
&G::scalar_as_bytes(server.get_private_key()).to_vec()
);
assert_eq!(&parameters.pksm, &server.get_public_key().to_arr().to_vec());
}
@@ -166,17 +168,17 @@ fn test_verifiable_seed_to_key<CS: CipherSuite>(
}
// Tests input -> blind, blinded_element
fn test_base_blind<CS: CipherSuite>(
fn test_base_blind<G: Group, H: BlockInput + Digest>(
tvs: &[VOPRFTestVectorParameters],
) -> Result<(), InternalError> {
for parameters in tvs {
for i in 0..parameters.input.len() {
let mut rng = CycleRng::new(parameters.blind[i].to_vec());
let client_result = NonVerifiableClient::<CS>::blind(&parameters.input[i], &mut rng)?;
let client_result = NonVerifiableClient::<G, H>::blind(&parameters.input[i], &mut rng)?;
assert_eq!(
&parameters.blind[i],
&CS::Group::scalar_as_bytes(client_result.state.get_blind()).to_vec()
&G::scalar_as_bytes(client_result.state.get_blind()).to_vec()
);
assert_eq!(
&parameters.blinded_element[i],
@@ -188,18 +190,18 @@ fn test_base_blind<CS: CipherSuite>(
}
// Tests input -> blind, blinded_element
fn test_verifiable_blind<CS: CipherSuite>(
fn test_verifiable_blind<G: Group, H: BlockInput + Digest>(
tvs: &[VOPRFTestVectorParameters],
) -> Result<(), InternalError> {
for parameters in tvs {
for i in 0..parameters.input.len() {
let mut rng = CycleRng::new(parameters.blind[i].to_vec());
let client_blind_result =
VerifiableClient::<CS>::blind(&parameters.input[i], &mut rng)?;
VerifiableClient::<G, H>::blind(&parameters.input[i], &mut rng)?;
assert_eq!(
&parameters.blind[i],
&CS::Group::scalar_as_bytes(client_blind_result.state.get_blind()).to_vec()
&G::scalar_as_bytes(client_blind_result.state.get_blind()).to_vec()
);
assert_eq!(
&parameters.blinded_element[i],
@@ -211,12 +213,12 @@ fn test_verifiable_blind<CS: CipherSuite>(
}
// Tests sksm, blinded_element -> evaluation_element
fn test_base_evaluate<CS: CipherSuite>(
fn test_base_evaluate<G: Group, H: BlockInput + Digest>(
tvs: &[VOPRFTestVectorParameters],
) -> Result<(), InternalError> {
for parameters in tvs {
for i in 0..parameters.input.len() {
let server = NonVerifiableServer::<CS>::new_with_key(&parameters.sksm)?;
let server = NonVerifiableServer::<G, H>::new_with_key(&parameters.sksm)?;
let server_result = server.evaluate(
BlindedElement::deserialize(&parameters.blinded_element[i])?,
&Metadata(parameters.info.clone()),
@@ -231,12 +233,12 @@ fn test_base_evaluate<CS: CipherSuite>(
Ok(())
}
fn test_verifiable_evaluate<CS: CipherSuite>(
fn test_verifiable_evaluate<G: Group, H: BlockInput + Digest>(
tvs: &[VOPRFTestVectorParameters],
) -> Result<(), InternalError> {
for parameters in tvs {
let mut rng = CycleRng::new(parameters.proof_random_scalar.clone());
let server = VerifiableServer::<CS>::new_with_key(&parameters.sksm)?;
let server = VerifiableServer::<G, H>::new_with_key(&parameters.sksm)?;
let mut blinded_elements = vec![];
for blinded_element_bytes in &parameters.blinded_element {
@@ -262,14 +264,14 @@ fn test_verifiable_evaluate<CS: CipherSuite>(
}
// Tests input, blind, evaluation_element -> output
fn test_base_finalize<CS: CipherSuite>(
fn test_base_finalize<G: Group, H: BlockInput + Digest>(
tvs: &[VOPRFTestVectorParameters],
) -> Result<(), InternalError> {
for parameters in tvs {
for i in 0..parameters.input.len() {
let client = NonVerifiableClient::<CS>::from_data_and_blind(
let client = NonVerifiableClient::<G, H>::from_data_and_blind(
&parameters.input[i],
<CS::Group as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
<G as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
&parameters.blind[i],
))?,
);
@@ -279,27 +281,24 @@ fn test_base_finalize<CS: CipherSuite>(
&Metadata(parameters.info.clone()),
)?;
assert_eq!(
&parameters.output[i],
&client_finalize_result.output.to_vec()
);
assert_eq!(&parameters.output[i], &client_finalize_result.to_vec());
}
}
Ok(())
}
fn test_verifiable_finalize<CS: CipherSuite>(
fn test_verifiable_finalize<G: Group, H: BlockInput + Digest>(
tvs: &[VOPRFTestVectorParameters],
) -> Result<(), InternalError> {
for parameters in tvs {
let mut clients = vec![];
for i in 0..parameters.input.len() {
let client = VerifiableClient::<CS>::from_data_and_blind(
let client = VerifiableClient::<G, H>::from_data_and_blind(
&parameters.input[i],
<CS::Group as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
<G as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
&parameters.blind[i],
))?,
<CS::Group as Group>::from_element_slice(&GenericArray::clone_from_slice(
<G as Group>::from_element_slice(&GenericArray::clone_from_slice(
&parameters.blinded_element[i],
))?,
);
@@ -318,14 +317,13 @@ fn test_verifiable_finalize<CS: CipherSuite>(
let batch_result = VerifiableClient::batch_finalize(
batch_finalize_input,
Proof::deserialize(&parameters.proof)?,
CS::Group::from_element_slice(GenericArray::from_slice(&parameters.pksm))?,
G::from_element_slice(GenericArray::from_slice(&parameters.pksm))?,
&Metadata(parameters.info.clone()),
)?;
assert_eq!(
parameters.output,
batch_result
.outputs
.iter()
.map(|arr| arr.to_vec())
.collect::<Vec<Vec<u8>>>()
+284 -266
View File
File diff suppressed because it is too large Load Diff