Updating to draft 11 (#80)

* draft-11

* Fix CI complaints

* Address review comments, CHANGELOG entry, minor fixes
This commit is contained in:
raphaelrobert
2022-07-09 07:30:20 -04:00
committed by GitHub
parent 6e16a99a87
commit f670733165
9 changed files with 489 additions and 129 deletions
+8
View File
@@ -1,5 +1,13 @@
# Changelog # Changelog
## 0.4.0-pre.4 (July 9, 2022)
* Updated to be in sync with draft-irtf-cfrg-voprf-11
* Adds the evaluate() function to the servers to calculate the output of the OPRF
directly
* Renames the former evaluate() function to blind_evaluate to match the spec
* Fixes the order of parameters for PoprfClient::blind to align it with the
other clients
## 0.4.0-pre.3 (July 1, 2022) ## 0.4.0-pre.3 (July 1, 2022)
* Updated to be in sync with draft-irtf-cfrg-voprf-10, with * Updated to be in sync with draft-irtf-cfrg-voprf-10, with
the only difference from -09 being a constant string change the only difference from -09 being a constant string change
+1 -1
View File
@@ -9,7 +9,7 @@ name = "voprf"
readme = "README.md" readme = "README.md"
repository = "https://github.com/novifinancial/voprf/" repository = "https://github.com/novifinancial/voprf/"
rust-version = "1.57" rust-version = "1.57"
version = "0.4.0-pre.3" version = "0.4.0-pre.4"
[features] [features]
alloc = [] alloc = []
+1 -1
View File
@@ -16,7 +16,7 @@ Installation
Add the following line to the dependencies of your `Cargo.toml`: Add the following line to the dependencies of your `Cargo.toml`:
``` ```
voprf = "0.4.0-pre.3" voprf = "0.4.0-pre.4"
``` ```
### Minimum Supported Rust Version ### Minimum Supported Rust Version
+56 -7
View File
@@ -11,7 +11,7 @@ use core::convert::TryFrom;
use derive_where::derive_where; use derive_where::derive_where;
use digest::core_api::BlockSizeUser; use digest::core_api::BlockSizeUser;
use digest::{Digest, OutputSizeUser}; use digest::{Digest, Output, OutputSizeUser};
use generic_array::sequence::Concat; use generic_array::sequence::Concat;
use generic_array::typenum::{IsLess, IsLessOrEqual, Unsigned, U11, U2, U256}; use generic_array::typenum::{IsLess, IsLessOrEqual, Unsigned, U11, U2, U256};
use generic_array::{ArrayLength, GenericArray}; use generic_array::{ArrayLength, GenericArray};
@@ -153,7 +153,7 @@ where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>, IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{ {
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-10.html#section-2.2.1 // https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html#section-2.2.1
let (m, z) = compute_composites::<CS, _, _>(Some(k), b, cs, ds, mode)?; let (m, z) = compute_composites::<CS, _, _>(Some(k), b, cs, ds, mode)?;
@@ -216,7 +216,7 @@ where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>, IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{ {
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-10.html#section-2.2.2 // https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html#section-2.2.2
let (m, z) = compute_composites::<CS, _, _>(None, b, cs, ds, mode)?; let (m, z) = compute_composites::<CS, _, _>(None, b, cs, ds, mode)?;
let t2 = (a * &proof.s_scalar) + &(b * &proof.c_scalar); let t2 = (a * &proof.s_scalar) + &(b * &proof.c_scalar);
let t3 = (m * &proof.s_scalar) + &(z * &proof.c_scalar); let t3 = (m * &proof.s_scalar) + &(z * &proof.c_scalar);
@@ -285,7 +285,7 @@ where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>, IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{ {
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-10.html#section-2.2.1 // https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html#section-2.2.1
let elem_len = <CS::Group as Group>::ElemLen::U16.to_be_bytes(); let elem_len = <CS::Group as Group>::ElemLen::U16.to_be_bytes();
@@ -437,12 +437,61 @@ where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>, IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{ {
let dst = GenericArray::from(STR_HASH_TO_GROUP).concat(create_context_string::<CS>(mode)); let hashed_point = hash_to_group::<CS>(input, mode)?;
let hashed_point =
CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst).map_err(|_| Error::Input)?;
Ok(hashed_point * blind) Ok(hashed_point * blind)
} }
/// Hashes `input` to a point on the curve
pub(crate) fn hash_to_group<CS: CipherSuite>(
input: &[u8],
mode: Mode,
) -> Result<<CS::Group as Group>::Elem>
where
<CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{
let dst = GenericArray::from(STR_HASH_TO_GROUP).concat(create_context_string::<CS>(mode));
CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst).map_err(|_| Error::Input)
}
/// Internal function that finalizes the hash input for OPRF, VOPRF & POPRF.
/// Returned values can only fail with [`Error::Input`].
pub(crate) fn server_evaluate_hash_input<CS: CipherSuite>(
input: &[u8],
info: Option<&[u8]>,
issued_element: GenericArray<u8, <<CS as CipherSuite>::Group as Group>::ElemLen>,
) -> Result<Output<CS::Hash>>
where
<CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{
// OPRF & VOPRF
// hashInput = I2OSP(len(input), 2) || input ||
// I2OSP(len(issuedElement), 2) || issuedElement ||
// "Finalize"
// return Hash(hashInput)
//
// POPRF
// hashInput = I2OSP(len(input), 2) || input ||
// I2OSP(len(info), 2) || info ||
// I2OSP(len(issuedElement), 2) || issuedElement ||
// "Finalize"
let mut hash = CS::Hash::new()
.chain_update(i2osp_2(input.as_ref().len()).map_err(|_| Error::Input)?)
.chain_update(input.as_ref());
if let Some(info) = info {
hash = hash
.chain_update(i2osp_2(info.as_ref().len()).map_err(|_| Error::Input)?)
.chain_update(info.as_ref());
}
Ok(hash
.chain_update(i2osp_2(issued_element.as_ref().len()).map_err(|_| Error::Input)?)
.chain_update(issued_element)
.chain_update(STR_FINALIZE)
.finalize())
}
/// Generates the contextString parameter as defined in /// Generates the contextString parameter as defined in
/// <https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/> /// <https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/>
pub(crate) fn create_context_string<CS: CipherSuite>(mode: Mode) -> GenericArray<u8, U11> pub(crate) fn create_context_string<CS: CipherSuite>(mode: Mode) -> GenericArray<u8, U11>
+136 -54
View File
@@ -8,7 +8,7 @@
//! An implementation of a verifiable oblivious pseudorandom function (VOPRF) //! An implementation of a verifiable oblivious pseudorandom function (VOPRF)
//! //!
//! Note: This implementation is in sync with //! Note: This implementation is in sync with
//! [draft-irtf-cfrg-voprf-10](https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-10.html), //! [draft-irtf-cfrg-voprf-11](https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html),
//! but this specification is subject to change, until the final version //! but this specification is subject to change, until the final version
//! published by the IETF. //! published by the IETF.
//! //!
@@ -36,18 +36,19 @@
//! VOPRF, where a public input can be supplied to the PRF computation //! VOPRF, where a public input can be supplied to the PRF computation
//! //!
//! In all of these modes, the protocol begins with a client blinding, followed //! In all of these modes, the protocol begins with a client blinding, followed
//! by a server evaluation, and finishes with a client finalization. //! by a server evaluation, and finishes with a client finalization and server
//! evaluation.
//! //!
//! ## Base Mode //! ## Base Mode
//! //!
//! In base mode, an [OprfClient] interacts with an [OprfServer] //! In base mode, an [OprfClient] interacts with an [OprfServer] to compute the
//! to compute the output of the OPRF. //! output of the OPRF.
//! //!
//! ### Server Setup //! ### Server Setup
//! //!
//! The protocol begins with a setup phase, in which the server must run //! The protocol begins with a setup phase, in which the server must run
//! [OprfServer::new()] to produce an instance of itself. This instance //! [OprfServer::new()] to produce an instance of itself. This instance must be
//! must be persisted on the server and used for online client evaluations. //! persisted on the server and used for online client evaluations.
//! //!
//! ``` //! ```
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
@@ -64,11 +65,10 @@
//! //!
//! ### Client Blinding //! ### Client Blinding
//! //!
//! In the first step, the client chooses an input, and runs //! In the first step, the client chooses an input, and runs [OprfClient::blind]
//! [OprfClient::blind] to produce an [OprfClientBlindResult], //! to produce an [OprfClientBlindResult], which consists of a [BlindedElement]
//! which consists of a [BlindedElement] to be sent to the server and an //! to be sent to the server and an [OprfClient] which must be persisted on the
//! [OprfClient] which must be persisted on the client for the final //! client for the final step of the VOPRF protocol.
//! step of the VOPRF protocol.
//! //!
//! ``` //! ```
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
@@ -84,11 +84,11 @@
//! .expect("Unable to construct client"); //! .expect("Unable to construct client");
//! ``` //! ```
//! //!
//! ### Server Evaluation //! ### Server Blind Evaluation
//! //!
//! In the second step, the server takes as input the message from //! In the second step, the server takes as input the message from
//! [OprfClient::blind] (a [BlindedElement]), and runs //! [OprfClient::blind] (a [BlindedElement]), and runs
//! [OprfServer::evaluate] to produce [EvaluationElement] to be sent to //! [OprfServer::blind_evaluate] to produce [EvaluationElement] to be sent to
//! the client. //! the client.
//! //!
//! ``` //! ```
@@ -107,13 +107,13 @@
//! # use voprf::OprfServer; //! # use voprf::OprfServer;
//! # let mut server_rng = OsRng; //! # let mut server_rng = OsRng;
//! # let server = OprfServer::<CipherSuite>::new(&mut server_rng).unwrap(); //! # let server = OprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! let server_evaluate_result = server.evaluate(&client_blind_result.message); //! let server_evaluate_result = server.blind_evaluate(&client_blind_result.message);
//! ``` //! ```
//! //!
//! ### Client Finalization //! ### Client Finalization
//! //!
//! In the final step, the client takes as input the message from //! In the final step on the client side, the client takes as input the message
//! [OprfServer::evaluate] (an [EvaluationElement]), and runs //! from [OprfServer::evaluate] (an [EvaluationElement]), and runs
//! [OprfClient::finalize] to produce an output for the protocol. //! [OprfClient::finalize] to produce an output for the protocol.
//! //!
//! ``` //! ```
@@ -132,7 +132,7 @@
//! # use voprf::OprfServer; //! # use voprf::OprfServer;
//! # let mut server_rng = OsRng; //! # let mut server_rng = OsRng;
//! # let server = OprfServer::<CipherSuite>::new(&mut server_rng).unwrap(); //! # let server = OprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! # let message = server.evaluate(&client_blind_result.message); //! # let message = server.blind_evaluate(&client_blind_result.message);
//! let client_finalize_result = client_blind_result //! let client_finalize_result = client_blind_result
//! .state //! .state
//! .finalize(b"input", &message) //! .finalize(b"input", &message)
@@ -141,10 +141,47 @@
//! println!("VOPRF output: {:?}", client_finalize_result.to_vec()); //! println!("VOPRF output: {:?}", client_finalize_result.to_vec());
//! ``` //! ```
//! //!
//! ### Server Evaluation
//!
//! Optionally, if the server has direct access to the PRF input, then it need
//! not perform the oblivious computation and can simply run
//! [OprfServer::evaluate] to generate an output which matches the output
//! produced by an execution of the oblivious protocol on the same input and
//! key.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type CipherSuite = voprf::Ristretto255;
//! # #[cfg(not(feature = "ristretto255"))]
//! # type CipherSuite = p256::NistP256;
//! # use voprf::OprfClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
//! # let mut client_rng = OsRng;
//! # let client_blind_result = OprfClient::<CipherSuite>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
//! # use voprf::OprfServer;
//! # let mut server_rng = OsRng;
//! # let server = OprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! # let message = server.blind_evaluate(&client_blind_result.message);
//! let client_finalize_result = client_blind_result
//! .state
//! .finalize(b"input", &message)
//! .expect("Unable to perform client finalization");
//!
//! let server_evaluate_result = server
//! .evaluate(b"input")
//! .expect("Unable to perform the server evaluation");
//!
//! assert_eq!(client_finalize_result, server_evaluate_result);
//! ```
//!
//! ## Verifiable Mode //! ## Verifiable Mode
//! //!
//! In verifiable mode, a [VoprfClient] interacts with a [VoprfServer] //! In verifiable mode, a [VoprfClient] interacts with a [VoprfServer] to
//! to compute the output of the VOPRF. In order to verify the server's //! compute the output of the VOPRF. In order to verify the server's
//! computation, the client checks a server-generated proof against the server's //! computation, the client checks a server-generated proof against the server's
//! public key. If the proof fails to verify, then the client does not receive //! public key. If the proof fails to verify, then the client does not receive
//! an output. //! an output.
@@ -156,8 +193,8 @@
//! ### Server Setup //! ### Server Setup
//! //!
//! The protocol begins with a setup phase, in which the server must run //! The protocol begins with a setup phase, in which the server must run
//! [VoprfServer::new()] to produce an instance of itself. This instance //! [VoprfServer::new()] to produce an instance of itself. This instance must be
//! must be persisted on the server and used for online client evaluations. //! persisted on the server and used for online client evaluations.
//! //!
//! ``` //! ```
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
@@ -182,10 +219,9 @@
//! ### Client Blinding //! ### Client Blinding
//! //!
//! In the first step, the client chooses an input, and runs //! In the first step, the client chooses an input, and runs
//! [VoprfClient::blind] to produce a [VoprfClientBlindResult], which //! [VoprfClient::blind] to produce a [VoprfClientBlindResult], which consists
//! consists of a [BlindedElement] to be sent to the server and a //! of a [BlindedElement] to be sent to the server and a [VoprfClient] which
//! [VoprfClient] which must be persisted on the client for the final step //! must be persisted on the client for the final step of the VOPRF protocol.
//! of the VOPRF protocol.
//! //!
//! ``` //! ```
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
@@ -201,11 +237,11 @@
//! .expect("Unable to construct client"); //! .expect("Unable to construct client");
//! ``` //! ```
//! //!
//! ### Server Evaluation //! ### Server Blind Evaluation
//! //!
//! In the second step, the server takes as input the message from //! In the second step, the server takes as input the message from
//! [VoprfClient::blind] (a [BlindedElement]), and runs //! [VoprfClient::blind] (a [BlindedElement]), and runs
//! [VoprfServer::evaluate] to produce a [VoprfServerEvaluateResult], //! [VoprfServer::blind_evaluate] to produce a [VoprfServerEvaluateResult],
//! which consists of an [EvaluationElement] to be sent to the client along with //! which consists of an [EvaluationElement] to be sent to the client along with
//! a proof. //! a proof.
//! //!
@@ -226,15 +262,15 @@
//! # let mut server_rng = OsRng; //! # let mut server_rng = OsRng;
//! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap(); //! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! let VoprfServerEvaluateResult { message, proof } = //! let VoprfServerEvaluateResult { message, proof } =
//! server.evaluate(&mut server_rng, &client_blind_result.message); //! server.blind_evaluate(&mut server_rng, &client_blind_result.message);
//! ``` //! ```
//! //!
//! ### Client Finalization //! ### Client Finalization
//! //!
//! In the final step, the client takes as input the message from //! In the final step, the client takes as input the message from
//! [VoprfServer::evaluate] (an [EvaluationElement]), the proof, and the //! [VoprfServer::blind_evaluate] (an [EvaluationElement]), the proof, and the
//! server's public key, and runs [VoprfClient::finalize] to produce an //! server's public key, and runs [VoprfClient::finalize] to produce an output
//! output for the protocol. //! for the protocol.
//! //!
//! ``` //! ```
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
@@ -252,7 +288,7 @@
//! # use voprf::VoprfServer; //! # use voprf::VoprfServer;
//! # let mut server_rng = OsRng; //! # let mut server_rng = OsRng;
//! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap(); //! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! # let server_evaluate_result = server.evaluate( //! # let server_evaluate_result = server.blind_evaluate(
//! # &mut server_rng, //! # &mut server_rng,
//! # &client_blind_result.message, //! # &client_blind_result.message,
//! # ); //! # );
@@ -269,6 +305,51 @@
//! println!("VOPRF output: {:?}", client_finalize_result.to_vec()); //! println!("VOPRF output: {:?}", client_finalize_result.to_vec());
//! ``` //! ```
//! //!
//! ### Server Evaluation
//!
//! Optionally, if the server has direct access to the PRF input, then it need
//! not perform the oblivious computation and can simply run
//! [VoprfServer::evaluate] to generate an output which matches the output
//! produced by an execution of the oblivious protocol on the same input and
//! key.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type CipherSuite = voprf::Ristretto255;
//! # #[cfg(not(feature = "ristretto255"))]
//! # type CipherSuite = p256::NistP256;
//! # use voprf::VoprfClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
//! # let mut client_rng = OsRng;
//! # let client_blind_result = VoprfClient::<CipherSuite>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
//! # use voprf::VoprfServer;
//! # let mut server_rng = OsRng;
//! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! # let server_evaluate_result = server.blind_evaluate(
//! # &mut server_rng,
//! # &client_blind_result.message,
//! # );
//! let client_finalize_result = client_blind_result
//! .state
//! .finalize(
//! b"input",
//! &server_evaluate_result.message,
//! &server_evaluate_result.proof,
//! server.get_public_key(),
//! )
//! .expect("Unable to perform client finalization");
//!
//! let server_evaluate_result = server
//! .evaluate(b"input")
//! .expect("Unable to perform the server evaluation");
//!
//! assert_eq!(client_finalize_result, server_evaluate_result);
//! ```
//!
//! # Advanced Usage //! # Advanced Usage
//! //!
//! There are two additional (and optional) extensions to the core VOPRF //! There are two additional (and optional) extensions to the core VOPRF
@@ -279,9 +360,9 @@
//! //!
//! It is sometimes desirable to generate only a single, constant-size proof for //! It is sometimes desirable to generate only a single, constant-size proof for
//! an unbounded number of VOPRF evaluations (on arbitrary inputs). //! an unbounded number of VOPRF evaluations (on arbitrary inputs).
//! [VoprfClient] and [VoprfServer] support a batch API for handling //! [VoprfClient] and [VoprfServer] support a batch API for handling this case.
//! this case. In the following example, we show how to use the batch API to //! In the following example, we show how to use the batch API to produce a
//! produce a single proof for 10 parallel VOPRF evaluations. //! single proof for 10 parallel VOPRF evaluations.
//! //!
//! First, the client produces 10 blindings, storing their resulting states and //! First, the client produces 10 blindings, storing their resulting states and
//! messages: //! messages:
@@ -305,8 +386,8 @@
//! } //! }
//! ``` //! ```
//! //!
//! Next, the server calls the [VoprfServer::batch_evaluate_prepare] and //! Next, the server calls the [VoprfServer::batch_blind_evaluate_prepare] and
//! [VoprfServer::batch_evaluate_finish] function on a set of client //! [VoprfServer::batch_blind_evaluate_finish] function on a set of client
//! messages, to produce a corresponding set of messages to be returned to the //! messages, to produce a corresponding set of messages to be returned to the
//! client (returned in the same order), along with a single proof: //! client (returned in the same order), along with a single proof:
//! //!
@@ -332,15 +413,15 @@
//! # use voprf::VoprfServer; //! # use voprf::VoprfServer;
//! let mut server_rng = OsRng; //! let mut server_rng = OsRng;
//! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap(); //! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! let prepared_evaluation_elements = server.batch_evaluate_prepare(client_messages.iter()); //! let prepared_evaluation_elements = server.batch_blind_evaluate_prepare(client_messages.iter());
//! let prepared_elements: Vec<_> = prepared_evaluation_elements.collect(); //! let prepared_elements: Vec<_> = prepared_evaluation_elements.collect();
//! let VoprfServerBatchEvaluateFinishResult { messages, proof } = server //! let VoprfServerBatchEvaluateFinishResult { messages, proof } = server
//! .batch_evaluate_finish(&mut server_rng, client_messages.iter(), &prepared_elements) //! .batch_blind_evaluate_finish(&mut server_rng, client_messages.iter(), &prepared_elements)
//! .expect("Unable to perform server batch evaluate"); //! .expect("Unable to perform server batch evaluate");
//! let messages: Vec<_> = messages.collect(); //! let messages: Vec<_> = messages.collect();
//! ``` //! ```
//! //!
//! If `alloc` is available, `VoprfServer::batch_evaluate` can be called //! If `alloc` is available, `VoprfServer::batch_blind_evaluate` can be called
//! to avoid having to collect output manually: //! to avoid having to collect output manually:
//! //!
//! ``` //! ```
@@ -367,15 +448,15 @@
//! let mut server_rng = OsRng; //! let mut server_rng = OsRng;
//! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap(); //! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! let VoprfServerBatchEvaluateResult { messages, proof } = server //! let VoprfServerBatchEvaluateResult { messages, proof } = server
//! .batch_evaluate(&mut server_rng, &client_messages) //! .batch_blind_evaluate(&mut server_rng, &client_messages)
//! .expect("Unable to perform server batch evaluate"); //! .expect("Unable to perform server batch evaluate");
//! # } //! # }
//! ``` //! ```
//! //!
//! Then, the client calls [VoprfClient::batch_finalize] on the client //! Then, the client calls [VoprfClient::batch_finalize] on the client states
//! states saved from the first step, along with the messages returned by the //! saved from the first step, along with the messages returned by the server,
//! server, along with the server's proof, in order to produce a vector of //! along with the server's proof, in order to produce a vector of outputs if
//! outputs if the proof verifies correctly. //! the proof verifies correctly.
//! //!
//! ``` //! ```
//! # #[cfg(feature = "alloc")] { //! # #[cfg(feature = "alloc")] {
@@ -401,7 +482,7 @@
//! # let mut server_rng = OsRng; //! # let mut server_rng = OsRng;
//! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap(); //! # let server = VoprfServer::<CipherSuite>::new(&mut server_rng).unwrap();
//! # let VoprfServerBatchEvaluateResult { messages, proof } = server //! # let VoprfServerBatchEvaluateResult { messages, proof } = server
//! # .batch_evaluate(&mut server_rng, &client_messages) //! # .batch_blind_evaluate(&mut server_rng, &client_messages)
//! # .expect("Unable to perform server batch evaluate"); //! # .expect("Unable to perform server batch evaluate");
//! let client_batch_finalize_result = VoprfClient::batch_finalize( //! let client_batch_finalize_result = VoprfClient::batch_finalize(
//! &[b"input"; 10], //! &[b"input"; 10],
@@ -420,17 +501,17 @@
//! ## Metadata //! ## Metadata
//! //!
//! The optional metadata parameter included in the POPRF mode allows clients //! The optional metadata parameter included in the POPRF mode allows clients
//! and servers to cryptographically bind additional data to the //! and servers to cryptographically bind additional data to the VOPRF output.
//! VOPRF output. This metadata is known to both parties at the start of the //! This metadata is known to both parties at the start of the protocol, and is
//! protocol, and is inserted under the server's evaluate step and the client's //! inserted under the server's blind evaluate step and the client's finalize
//! finalize step. This metadata can be constructed with some type of //! step. This metadata can be constructed with some type of higher-level domain
//! higher-level domain separation to avoid cross-protocol attacks or related //! separation to avoid cross-protocol attacks or related issues.
//! issues.
//! //!
//! The API for POPRF mode is similar to VOPRF mode, except that a [PoprfServer] //! The API for POPRF mode is similar to VOPRF mode, except that a [PoprfServer]
//! and [PoprfClient] are used, and that each of the functions accept an //! and [PoprfClient] are used, and that each of the functions accept an
//! additional (and optional) info parameter which represents the public input. //! additional (and optional) info parameter which represents the public input.
//! See <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-10.html#name-poprf-public-input> //! See
//! <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html#name-poprf-public-input>
//! for more detailed information on how this public input should be used. //! for more detailed information on how this public input should be used.
//! //!
//! # Features //! # Features
@@ -464,7 +545,8 @@
//! automatically enable the `ristretto255-u64` feature and requires Rust //! automatically enable the `ristretto255-u64` feature and requires Rust
//! nightly. //! nightly.
//! //!
//! [curve25519-dalek]: (https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features) //! [curve25519-dalek]:
//! (https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features)
#![cfg_attr(not(test), deny(unsafe_code))] #![cfg_attr(not(test), deny(unsafe_code))]
#![no_std] #![no_std]
+51 -5
View File
@@ -17,8 +17,8 @@ use generic_array::GenericArray;
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use crate::common::{ use crate::common::{
derive_key_internal, deterministic_blind_unchecked, i2osp_2, BlindedElement, EvaluationElement, derive_key_internal, deterministic_blind_unchecked, hash_to_group, i2osp_2,
Mode, STR_FINALIZE, server_evaluate_hash_input, BlindedElement, EvaluationElement, Mode, STR_FINALIZE,
}; };
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use crate::serialization::serde::Scalar; use crate::serialization::serde::Scalar;
@@ -202,9 +202,25 @@ where
/// Computes the second step for the multiplicative blinding version of /// Computes the second step for the multiplicative blinding version of
/// DH-OPRF. This message is sent from the server (who holds the OPRF key) /// DH-OPRF. This message is sent from the server (who holds the OPRF key)
/// to the client. /// to the client.
pub fn evaluate(&self, blinded_element: &BlindedElement<CS>) -> EvaluationElement<CS> { pub fn blind_evaluate(&self, blinded_element: &BlindedElement<CS>) -> EvaluationElement<CS> {
EvaluationElement(blinded_element.0 * &self.sk) EvaluationElement(blinded_element.0 * &self.sk)
} }
/// Computes the output of the OPRF on the server side
///
/// # Errors
/// [`Error::Input`] if the `input` is longer then [`u16::MAX`].
pub fn evaluate(&self, input: &[u8]) -> Result<Output<<CS as CipherSuite>::Hash>> {
let input_element = hash_to_group::<CS>(input, Mode::Oprf)?;
if CS::Group::is_identity_elem(input_element).into() {
return Err(Error::Input);
};
let evaluated_element = input_element * &self.sk;
let issued_element = CS::Group::serialize_elem(evaluated_element);
server_evaluate_hash_input::<CS>(input, None, issued_element)
}
} }
///////////////////////// /////////////////////////
@@ -312,7 +328,7 @@ mod tests {
let mut rng = OsRng; let mut rng = OsRng;
let client_blind_result = OprfClient::<CS>::blind(input, &mut rng).unwrap(); let client_blind_result = OprfClient::<CS>::blind(input, &mut rng).unwrap();
let server = OprfServer::<CS>::new(&mut rng).unwrap(); let server = OprfServer::<CS>::new(&mut rng).unwrap();
let message = server.evaluate(&client_blind_result.message); let message = server.blind_evaluate(&client_blind_result.message);
let client_finalize_result = client_blind_result.state.finalize(input, &message).unwrap(); let client_finalize_result = client_blind_result.state.finalize(input, &message).unwrap();
let res2 = prf::<CS>(input, server.get_private_key(), &[], Mode::Oprf); let res2 = prf::<CS>(input, server.get_private_key(), &[], Mode::Oprf);
assert_eq!(client_finalize_result, res2); assert_eq!(client_finalize_result, res2);
@@ -343,6 +359,34 @@ mod tests {
assert_eq!(client_finalize_result, res2); assert_eq!(client_finalize_result, res2);
} }
fn server_evaluate<CS: CipherSuite>()
where
<CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{
let input = b"input";
let mut rng = OsRng;
let client_blind_result = OprfClient::<CS>::blind(input, &mut rng).unwrap();
let server = OprfServer::<CS>::new(&mut rng).unwrap();
let server_result = server.blind_evaluate(&client_blind_result.message);
let client_finalize = client_blind_result
.state
.finalize(input, &server_result)
.unwrap();
// We expect the outputs from client and server to be equal given an identical
// input
let server_evaluate = server.evaluate(input).unwrap();
assert_eq!(client_finalize, server_evaluate);
// We expect the outputs from client and server to be different given different
// inputs
let wrong_input = b"wrong input";
let server_evaluate = server.evaluate(wrong_input).unwrap();
assert!(client_finalize != server_evaluate);
}
fn zeroize_oprf_client<CS: CipherSuite>() fn zeroize_oprf_client<CS: CipherSuite>()
where where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
@@ -370,7 +414,7 @@ mod tests {
let mut rng = OsRng; let mut rng = OsRng;
let client_blind_result = OprfClient::<CS>::blind(input, &mut rng).unwrap(); let client_blind_result = OprfClient::<CS>::blind(input, &mut rng).unwrap();
let server = OprfServer::<CS>::new(&mut rng).unwrap(); let server = OprfServer::<CS>::new(&mut rng).unwrap();
let mut message = server.evaluate(&client_blind_result.message); let mut message = server.blind_evaluate(&client_blind_result.message);
let mut state = server; let mut state = server;
unsafe { ptr::drop_in_place(&mut state) }; unsafe { ptr::drop_in_place(&mut state) };
@@ -390,6 +434,7 @@ mod tests {
base_retrieval::<Ristretto255>(); base_retrieval::<Ristretto255>();
base_inversion_unsalted::<Ristretto255>(); base_inversion_unsalted::<Ristretto255>();
server_evaluate::<Ristretto255>();
zeroize_oprf_client::<Ristretto255>(); zeroize_oprf_client::<Ristretto255>();
zeroize_oprf_server::<Ristretto255>(); zeroize_oprf_server::<Ristretto255>();
@@ -397,6 +442,7 @@ mod tests {
base_retrieval::<NistP256>(); base_retrieval::<NistP256>();
base_inversion_unsalted::<NistP256>(); base_inversion_unsalted::<NistP256>();
server_evaluate::<NistP256>();
zeroize_oprf_client::<NistP256>(); zeroize_oprf_client::<NistP256>();
zeroize_oprf_server::<NistP256>(); zeroize_oprf_server::<NistP256>();
+86 -23
View File
@@ -20,9 +20,10 @@ use generic_array::GenericArray;
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use crate::common::{ use crate::common::{
create_context_string, derive_keypair, deterministic_blind_unchecked, generate_proof, i2osp_2, create_context_string, derive_keypair, deterministic_blind_unchecked, generate_proof,
verify_proof, BlindedElement, EvaluationElement, Mode, PreparedEvaluationElement, Proof, hash_to_group, i2osp_2, server_evaluate_hash_input, verify_proof, BlindedElement,
STR_FINALIZE, STR_HASH_TO_SCALAR, STR_INFO, EvaluationElement, Mode, PreparedEvaluationElement, Proof, STR_FINALIZE, STR_HASH_TO_SCALAR,
STR_INFO,
}; };
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use crate::serialization::serde::{Element, Scalar}; use crate::serialization::serde::{Element, Scalar};
@@ -89,8 +90,8 @@ where
/// # Errors /// # Errors
/// [`Error::Input`] if the `input` is empty or longer than [`u16::MAX`]. /// [`Error::Input`] if the `input` is empty or longer than [`u16::MAX`].
pub fn blind<R: RngCore + CryptoRng>( pub fn blind<R: RngCore + CryptoRng>(
blinding_factor_rng: &mut R,
input: &[u8], input: &[u8],
blinding_factor_rng: &mut R,
) -> Result<PoprfClientBlindResult<CS>> { ) -> Result<PoprfClientBlindResult<CS>> {
let blind = CS::Group::random_scalar(blinding_factor_rng); let blind = CS::Group::random_scalar(blinding_factor_rng);
Self::deterministic_blind_unchecked_inner(input, blind) Self::deterministic_blind_unchecked_inner(input, blind)
@@ -248,7 +249,7 @@ where
/// # Errors /// # Errors
/// - [`Error::Info`] if the `info` is longer than `u16::MAX`. /// - [`Error::Info`] if the `info` is longer than `u16::MAX`.
/// - [`Error::Protocol`] if the protocol fails and can't be completed. /// - [`Error::Protocol`] if the protocol fails and can't be completed.
pub fn evaluate<R: RngCore + CryptoRng>( pub fn blind_evaluate<R: RngCore + CryptoRng>(
&self, &self,
rng: &mut R, rng: &mut R,
blinded_element: &BlindedElement<CS>, blinded_element: &BlindedElement<CS>,
@@ -257,7 +258,7 @@ where
let PoprfServerBatchEvaluatePrepareResult { let PoprfServerBatchEvaluatePrepareResult {
mut prepared_evaluation_elements, mut prepared_evaluation_elements,
prepared_tweak, prepared_tweak,
} = self.batch_evaluate_prepare(iter::once(blinded_element), info)?; } = self.batch_blind_evaluate_prepare(iter::once(blinded_element), info)?;
let prepared_evaluation_element = prepared_evaluation_elements.next().unwrap(); let prepared_evaluation_element = prepared_evaluation_elements.next().unwrap();
let prepared_evaluation_elements = core::array::from_ref(&prepared_evaluation_element); let prepared_evaluation_elements = core::array::from_ref(&prepared_evaluation_element);
@@ -265,7 +266,7 @@ where
let PoprfServerBatchEvaluateFinishResult { let PoprfServerBatchEvaluateFinishResult {
mut messages, mut messages,
proof, proof,
} = Self::batch_evaluate_finish( } = Self::batch_blind_evaluate_finish(
rng, rng,
iter::once(blinded_element), iter::once(blinded_element),
prepared_evaluation_elements, prepared_evaluation_elements,
@@ -286,7 +287,7 @@ where
/// - [`Error::Info`] if the `info` is longer than `u16::MAX`. /// - [`Error::Info`] if the `info` is longer than `u16::MAX`.
/// - [`Error::Protocol`] if the protocol fails and can't be completed. /// - [`Error::Protocol`] if the protocol fails and can't be completed.
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub fn batch_evaluate<'a, R: RngCore + CryptoRng, IE>( pub fn batch_blind_evaluate<'a, R: RngCore + CryptoRng, IE>(
&self, &self,
rng: &mut R, rng: &mut R,
blinded_elements: &'a IE, blinded_elements: &'a IE,
@@ -300,13 +301,13 @@ where
let PoprfServerBatchEvaluatePrepareResult { let PoprfServerBatchEvaluatePrepareResult {
prepared_evaluation_elements, prepared_evaluation_elements,
prepared_tweak, prepared_tweak,
} = self.batch_evaluate_prepare(blinded_elements.into_iter(), info)?; } = self.batch_blind_evaluate_prepare(blinded_elements.into_iter(), info)?;
let prepared_evaluation_elements: Vec<_> = prepared_evaluation_elements.collect(); let prepared_evaluation_elements: Vec<_> = prepared_evaluation_elements.collect();
// This can't fail because we know the size of the inputs. // This can't fail because we know the size of the inputs.
let PoprfServerBatchEvaluateFinishResult { messages, proof } = let PoprfServerBatchEvaluateFinishResult { messages, proof } =
Self::batch_evaluate_finish::<_, _, Vec<_>>( Self::batch_blind_evaluate_finish::<_, _, Vec<_>>(
rng, rng,
blinded_elements.into_iter(), blinded_elements.into_iter(),
&prepared_evaluation_elements, &prepared_evaluation_elements,
@@ -319,15 +320,15 @@ where
Ok(PoprfServerBatchEvaluateResult { messages, proof }) Ok(PoprfServerBatchEvaluateResult { messages, proof })
} }
/// Alternative version of `batch_evaluate` without /// Alternative version of `batch_blind_evaluate` without
/// memory allocation. Returned [`PreparedEvaluationElement`] have to /// memory allocation. Returned [`PreparedEvaluationElement`] have to
/// be [`collect`](Iterator::collect)ed and passed into /// be [`collect`](Iterator::collect)ed and passed into
/// [`batch_evaluate_finish`](Self::batch_evaluate_finish). /// [`batch_blind_evaluate_finish`](Self::batch_blind_evaluate_finish).
/// ///
/// # Errors /// # Errors
/// - [`Error::Info`] if the `info` is longer than `u16::MAX`. /// - [`Error::Info`] if the `info` is longer than `u16::MAX`.
/// - [`Error::Protocol`] if the protocol fails and can't be completed. /// - [`Error::Protocol`] if the protocol fails and can't be completed.
pub fn batch_evaluate_prepare<'a, I: Iterator<Item = &'a BlindedElement<CS>>>( pub fn batch_blind_evaluate_prepare<'a, I: Iterator<Item = &'a BlindedElement<CS>>>(
&self, &self,
blinded_elements: I, blinded_elements: I,
info: Option<&[u8]>, info: Option<&[u8]>,
@@ -349,14 +350,14 @@ where
}) })
} }
/// See [`batch_evaluate_prepare`](Self::batch_evaluate_prepare) for more /// See [`batch_blind_evaluate_prepare`](Self::batch_blind_evaluate_prepare)
/// details. /// for more details.
/// ///
/// # Errors /// # Errors
/// [`Error::Batch`] if the number of `blinded_elements` and /// [`Error::Batch`] if the number of `blinded_elements` and
/// `prepared_evaluation_elements` don't match or is longer then /// `prepared_evaluation_elements` don't match or is longer then
/// [`u16::MAX`] /// [`u16::MAX`]
pub fn batch_evaluate_finish< pub fn batch_blind_evaluate_finish<
'a, 'a,
'b, 'b,
R: RngCore + CryptoRng, R: RngCore + CryptoRng,
@@ -398,6 +399,29 @@ where
Ok(PoprfServerBatchEvaluateFinishResult { messages, proof }) Ok(PoprfServerBatchEvaluateFinishResult { messages, proof })
} }
/// Computes the output of the VOPRF on the server side
///
/// # Errors
/// [`Error::Input`] if the `input` is longer then [`u16::MAX`].
pub fn evaluate(
&self,
input: &[u8],
info: Option<&[u8]>,
) -> Result<Output<<CS as CipherSuite>::Hash>> {
let input_element = hash_to_group::<CS>(input, Mode::Poprf)?;
if CS::Group::is_identity_elem(input_element).into() {
return Err(Error::Input);
};
let tweak = compute_tweak::<CS>(self.sk, info)?;
let evaluated_element = input_element * &CS::Group::invert_scalar(tweak);
let issued_element = CS::Group::serialize_elem(evaluated_element);
server_evaluate_hash_input::<CS>(input, info, issued_element)
}
/// Retrieves the server's public key /// Retrieves the server's public key
pub fn get_public_key(&self) -> <CS::Group as Group>::Elem { pub fn get_public_key(&self) -> <CS::Group as Group>::Elem {
self.pk self.pk
@@ -808,9 +832,9 @@ mod tests {
let info = b"info"; let info = b"info";
let mut rng = OsRng; let mut rng = OsRng;
let server = PoprfServer::<CS>::new(&mut rng).unwrap(); let server = PoprfServer::<CS>::new(&mut rng).unwrap();
let client_blind_result = PoprfClient::<CS>::blind(&mut rng, input).unwrap(); let client_blind_result = PoprfClient::<CS>::blind(input, &mut rng).unwrap();
let server_result = server let server_result = server
.evaluate(&mut rng, &client_blind_result.message, Some(info)) .blind_evaluate(&mut rng, &client_blind_result.message, Some(info))
.unwrap(); .unwrap();
let client_finalize_result = client_blind_result let client_finalize_result = client_blind_result
.state .state
@@ -835,9 +859,9 @@ mod tests {
let info = b"info"; let info = b"info";
let mut rng = OsRng; let mut rng = OsRng;
let server = PoprfServer::<CS>::new(&mut rng).unwrap(); let server = PoprfServer::<CS>::new(&mut rng).unwrap();
let client_blind_result = PoprfClient::<CS>::blind(&mut rng, input).unwrap(); let client_blind_result = PoprfClient::<CS>::blind(input, &mut rng).unwrap();
let server_result = server let server_result = server
.evaluate(&mut rng, &client_blind_result.message, Some(info)) .blind_evaluate(&mut rng, &client_blind_result.message, Some(info))
.unwrap(); .unwrap();
let wrong_pk = { let wrong_pk = {
let dst = GenericArray::from(STR_HASH_TO_GROUP) let dst = GenericArray::from(STR_HASH_TO_GROUP)
@@ -855,6 +879,43 @@ mod tests {
assert!(client_finalize_result.is_err()); assert!(client_finalize_result.is_err());
} }
fn verifiable_server_evaluate<CS: CipherSuite>()
where
<CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{
let input = b"input";
let info = Some(b"info".as_slice());
let mut rng = OsRng;
let client_blind_result = PoprfClient::<CS>::blind(input, &mut rng).unwrap();
let server = PoprfServer::<CS>::new(&mut rng).unwrap();
let server_result = server
.blind_evaluate(&mut rng, &client_blind_result.message, info)
.unwrap();
let client_finalize = client_blind_result
.state
.finalize(
input,
&server_result.message,
&server_result.proof,
server.get_public_key(),
info,
)
.unwrap();
// We expect the outputs from client and server to be equal given an identical
// input
let server_evaluate = server.evaluate(input, info).unwrap();
assert_eq!(client_finalize, server_evaluate);
// We expect the outputs from client and server to be different given different
// inputs
let wrong_input = b"wrong input";
let server_evaluate = server.evaluate(wrong_input, info).unwrap();
assert!(client_finalize != server_evaluate);
}
fn zeroize_verifiable_client<CS: CipherSuite>() fn zeroize_verifiable_client<CS: CipherSuite>()
where where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
@@ -864,7 +925,7 @@ mod tests {
{ {
let input = b"input"; let input = b"input";
let mut rng = OsRng; let mut rng = OsRng;
let client_blind_result = PoprfClient::<CS>::blind(&mut rng, input).unwrap(); let client_blind_result = PoprfClient::<CS>::blind(input, &mut rng).unwrap();
let mut state = client_blind_result.state; let mut state = client_blind_result.state;
unsafe { ptr::drop_in_place(&mut state) }; unsafe { ptr::drop_in_place(&mut state) };
@@ -888,9 +949,9 @@ mod tests {
let info = b"info"; let info = b"info";
let mut rng = OsRng; let mut rng = OsRng;
let server = PoprfServer::<CS>::new(&mut rng).unwrap(); let server = PoprfServer::<CS>::new(&mut rng).unwrap();
let client_blind_result = PoprfClient::<CS>::blind(&mut rng, input).unwrap(); let client_blind_result = PoprfClient::<CS>::blind(input, &mut rng).unwrap();
let server_result = server let server_result = server
.evaluate(&mut rng, &client_blind_result.message, Some(info)) .blind_evaluate(&mut rng, &client_blind_result.message, Some(info))
.unwrap(); .unwrap();
let mut state = server; let mut state = server;
@@ -916,6 +977,7 @@ mod tests {
verifiable_retrieval::<Ristretto255>(); verifiable_retrieval::<Ristretto255>();
verifiable_bad_public_key::<Ristretto255>(); verifiable_bad_public_key::<Ristretto255>();
verifiable_server_evaluate::<Ristretto255>();
zeroize_verifiable_client::<Ristretto255>(); zeroize_verifiable_client::<Ristretto255>();
zeroize_verifiable_server::<Ristretto255>(); zeroize_verifiable_server::<Ristretto255>();
@@ -923,6 +985,7 @@ mod tests {
verifiable_retrieval::<NistP256>(); verifiable_retrieval::<NistP256>();
verifiable_bad_public_key::<NistP256>(); verifiable_bad_public_key::<NistP256>();
verifiable_server_evaluate::<NistP256>();
zeroize_verifiable_client::<NistP256>(); zeroize_verifiable_client::<NistP256>();
zeroize_verifiable_server::<NistP256>(); zeroize_verifiable_server::<NistP256>();
+75 -15
View File
@@ -101,8 +101,9 @@ fn test_vectors() -> Result<()> {
assert_ne!(ristretto_oprf_tvs.len(), 0); assert_ne!(ristretto_oprf_tvs.len(), 0);
test_oprf_seed_to_key::<Ristretto255>(&ristretto_oprf_tvs)?; test_oprf_seed_to_key::<Ristretto255>(&ristretto_oprf_tvs)?;
test_oprf_blind::<Ristretto255>(&ristretto_oprf_tvs)?; test_oprf_blind::<Ristretto255>(&ristretto_oprf_tvs)?;
test_oprf_evaluate::<Ristretto255>(&ristretto_oprf_tvs)?; test_oprf_blind_evaluate::<Ristretto255>(&ristretto_oprf_tvs)?;
test_oprf_finalize::<Ristretto255>(&ristretto_oprf_tvs)?; test_oprf_finalize::<Ristretto255>(&ristretto_oprf_tvs)?;
test_oprf_evaluate::<Ristretto255>(&ristretto_oprf_tvs)?;
let ristretto_voprf_tvs = json_to_test_vectors!( let ristretto_voprf_tvs = json_to_test_vectors!(
rfc, rfc,
@@ -112,8 +113,9 @@ fn test_vectors() -> Result<()> {
assert_ne!(ristretto_voprf_tvs.len(), 0); assert_ne!(ristretto_voprf_tvs.len(), 0);
test_voprf_seed_to_key::<Ristretto255>(&ristretto_voprf_tvs)?; test_voprf_seed_to_key::<Ristretto255>(&ristretto_voprf_tvs)?;
test_voprf_blind::<Ristretto255>(&ristretto_voprf_tvs)?; test_voprf_blind::<Ristretto255>(&ristretto_voprf_tvs)?;
test_voprf_evaluate::<Ristretto255>(&ristretto_voprf_tvs)?; test_voprf_blind_evaluate::<Ristretto255>(&ristretto_voprf_tvs)?;
test_voprf_finalize::<Ristretto255>(&ristretto_voprf_tvs)?; test_voprf_finalize::<Ristretto255>(&ristretto_voprf_tvs)?;
test_voprf_evaluate::<Ristretto255>(&ristretto_voprf_tvs)?;
let ristretto_poprf_tvs = json_to_test_vectors!( let ristretto_poprf_tvs = json_to_test_vectors!(
rfc, rfc,
@@ -123,8 +125,9 @@ fn test_vectors() -> Result<()> {
assert_ne!(ristretto_poprf_tvs.len(), 0); assert_ne!(ristretto_poprf_tvs.len(), 0);
test_poprf_seed_to_key::<Ristretto255>(&ristretto_poprf_tvs)?; test_poprf_seed_to_key::<Ristretto255>(&ristretto_poprf_tvs)?;
test_poprf_blind::<Ristretto255>(&ristretto_poprf_tvs)?; test_poprf_blind::<Ristretto255>(&ristretto_poprf_tvs)?;
test_poprf_evaluate::<Ristretto255>(&ristretto_poprf_tvs)?; test_poprf_blind_evaluate::<Ristretto255>(&ristretto_poprf_tvs)?;
test_poprf_finalize::<Ristretto255>(&ristretto_poprf_tvs)?; test_poprf_finalize::<Ristretto255>(&ristretto_poprf_tvs)?;
test_poprf_evaluate::<Ristretto255>(&ristretto_poprf_tvs)?;
} }
let p256_oprf_tvs = let p256_oprf_tvs =
@@ -132,24 +135,27 @@ fn test_vectors() -> Result<()> {
assert_ne!(p256_oprf_tvs.len(), 0); assert_ne!(p256_oprf_tvs.len(), 0);
test_oprf_seed_to_key::<NistP256>(&p256_oprf_tvs)?; test_oprf_seed_to_key::<NistP256>(&p256_oprf_tvs)?;
test_oprf_blind::<NistP256>(&p256_oprf_tvs)?; test_oprf_blind::<NistP256>(&p256_oprf_tvs)?;
test_oprf_evaluate::<NistP256>(&p256_oprf_tvs)?; test_oprf_blind_evaluate::<NistP256>(&p256_oprf_tvs)?;
test_oprf_finalize::<NistP256>(&p256_oprf_tvs)?; test_oprf_finalize::<NistP256>(&p256_oprf_tvs)?;
test_oprf_evaluate::<NistP256>(&p256_oprf_tvs)?;
let p256_voprf_tvs = let p256_voprf_tvs =
json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("VOPRF")); json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("VOPRF"));
assert_ne!(p256_voprf_tvs.len(), 0); assert_ne!(p256_voprf_tvs.len(), 0);
test_voprf_seed_to_key::<NistP256>(&p256_voprf_tvs)?; test_voprf_seed_to_key::<NistP256>(&p256_voprf_tvs)?;
test_voprf_blind::<NistP256>(&p256_voprf_tvs)?; test_voprf_blind::<NistP256>(&p256_voprf_tvs)?;
test_voprf_evaluate::<NistP256>(&p256_voprf_tvs)?; test_voprf_blind_evaluate::<NistP256>(&p256_voprf_tvs)?;
test_voprf_finalize::<NistP256>(&p256_voprf_tvs)?; test_voprf_finalize::<NistP256>(&p256_voprf_tvs)?;
test_voprf_evaluate::<NistP256>(&p256_voprf_tvs)?;
let p256_poprf_tvs = let p256_poprf_tvs =
json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("POPRF")); json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("POPRF"));
assert_ne!(p256_poprf_tvs.len(), 0); assert_ne!(p256_poprf_tvs.len(), 0);
test_poprf_seed_to_key::<NistP256>(&p256_poprf_tvs)?; test_poprf_seed_to_key::<NistP256>(&p256_poprf_tvs)?;
test_poprf_blind::<NistP256>(&p256_poprf_tvs)?; test_poprf_blind::<NistP256>(&p256_poprf_tvs)?;
test_poprf_evaluate::<NistP256>(&p256_poprf_tvs)?; test_poprf_blind_evaluate::<NistP256>(&p256_poprf_tvs)?;
test_poprf_finalize::<NistP256>(&p256_poprf_tvs)?; test_poprf_finalize::<NistP256>(&p256_poprf_tvs)?;
test_poprf_evaluate::<NistP256>(&p256_poprf_tvs)?;
Ok(()) Ok(())
} }
@@ -286,7 +292,7 @@ where
} }
// Tests sksm, blinded_element -> evaluation_element // Tests sksm, blinded_element -> evaluation_element
fn test_oprf_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()> fn test_oprf_blind_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()>
where where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>, IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
@@ -294,7 +300,7 @@ where
for parameters in tvs { for parameters in tvs {
for i in 0..parameters.input.len() { for i in 0..parameters.input.len() {
let server = OprfServer::<CS>::new_with_key(&parameters.sksm)?; let server = OprfServer::<CS>::new_with_key(&parameters.sksm)?;
let message = server.evaluate(&BlindedElement::deserialize( let message = server.blind_evaluate(&BlindedElement::deserialize(
&parameters.blinded_element[i], &parameters.blinded_element[i],
)?); )?);
@@ -307,7 +313,7 @@ where
Ok(()) Ok(())
} }
fn test_voprf_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()> fn test_voprf_blind_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()>
where where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>, IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
@@ -323,10 +329,11 @@ where
blinded_elements.push(BlindedElement::deserialize(blinded_element_bytes)?); blinded_elements.push(BlindedElement::deserialize(blinded_element_bytes)?);
} }
let prepared_evaluation_elements = server.batch_evaluate_prepare(blinded_elements.iter()); let prepared_evaluation_elements =
server.batch_blind_evaluate_prepare(blinded_elements.iter());
let prepared_elements: Vec<_> = prepared_evaluation_elements.collect(); let prepared_elements: Vec<_> = prepared_evaluation_elements.collect();
let VoprfServerBatchEvaluateFinishResult { messages, proof } = let VoprfServerBatchEvaluateFinishResult { messages, proof } = server
server.batch_evaluate_finish(&mut rng, blinded_elements.iter(), &prepared_elements)?; .batch_blind_evaluate_finish(&mut rng, blinded_elements.iter(), &prepared_elements)?;
let messages: Vec<_> = messages.collect(); let messages: Vec<_> = messages.collect();
for (parameter, message) in parameters.evaluation_element.iter().zip(messages) { for (parameter, message) in parameters.evaluation_element.iter().zip(messages) {
@@ -338,7 +345,7 @@ where
Ok(()) Ok(())
} }
fn test_poprf_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()> fn test_poprf_blind_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()>
where where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>, IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
@@ -357,10 +364,10 @@ where
let PoprfServerBatchEvaluatePrepareResult { let PoprfServerBatchEvaluatePrepareResult {
prepared_evaluation_elements, prepared_evaluation_elements,
prepared_tweak, prepared_tweak,
} = server.batch_evaluate_prepare(blinded_elements.iter(), Some(&parameters.info))?; } = server.batch_blind_evaluate_prepare(blinded_elements.iter(), Some(&parameters.info))?;
let prepared_evaluation_elements: Vec<_> = prepared_evaluation_elements.collect(); let prepared_evaluation_elements: Vec<_> = prepared_evaluation_elements.collect();
let PoprfServerBatchEvaluateFinishResult { messages, proof } = let PoprfServerBatchEvaluateFinishResult { messages, proof } =
PoprfServer::batch_evaluate_finish::<_, _, Vec<_>>( PoprfServer::batch_blind_evaluate_finish::<_, _, Vec<_>>(
&mut rng, &mut rng,
blinded_elements.iter(), blinded_elements.iter(),
&prepared_evaluation_elements, &prepared_evaluation_elements,
@@ -476,3 +483,56 @@ where
} }
Ok(()) Ok(())
} }
// Tests input, sksm -> output
fn test_oprf_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()>
where
<CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{
for parameters in tvs {
for i in 0..parameters.input.len() {
let server = OprfServer::<CS>::new_with_key(&parameters.sksm)?;
let server_evaluate_result = server.evaluate(&parameters.input[i])?;
assert_eq!(&parameters.output[i], &server_evaluate_result.to_vec());
}
}
Ok(())
}
fn test_voprf_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()>
where
<CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{
for parameters in tvs {
for i in 0..parameters.input.len() {
let server = VoprfServer::<CS>::new_with_key(&parameters.sksm)?;
let server_evaluate_result = server.evaluate(&parameters.input[i])?;
assert_eq!(&parameters.output[i], &server_evaluate_result.to_vec());
}
}
Ok(())
}
fn test_poprf_evaluate<CS: CipherSuite>(tvs: &[VOPRFTestVectorParameters]) -> Result<()>
where
<CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{
for parameters in tvs {
for i in 0..parameters.input.len() {
let server = PoprfServer::<CS>::new_with_key(&parameters.sksm)?;
let server_evaluate_result =
server.evaluate(&parameters.input[i], Some(&parameters.info))?;
assert_eq!(&parameters.output[i], &server_evaluate_result.to_vec());
}
}
Ok(())
}
+75 -23
View File
@@ -19,8 +19,9 @@ use generic_array::GenericArray;
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use crate::common::{ use crate::common::{
derive_keypair, deterministic_blind_unchecked, generate_proof, i2osp_2, verify_proof, derive_keypair, deterministic_blind_unchecked, generate_proof, hash_to_group, i2osp_2,
BlindedElement, EvaluationElement, Mode, PreparedEvaluationElement, Proof, STR_FINALIZE, server_evaluate_hash_input, verify_proof, BlindedElement, EvaluationElement, Mode,
PreparedEvaluationElement, Proof, STR_FINALIZE,
}; };
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use crate::serialization::serde::{Element, Scalar}; use crate::serialization::serde::{Element, Scalar};
@@ -253,13 +254,13 @@ where
/// Computes the second step for the multiplicative blinding version of /// Computes the second step for the multiplicative blinding version of
/// DH-OPRF. This message is sent from the server (who holds the OPRF key) /// DH-OPRF. This message is sent from the server (who holds the OPRF key)
/// to the client. /// to the client.
pub fn evaluate<R: RngCore + CryptoRng>( pub fn blind_evaluate<R: RngCore + CryptoRng>(
&self, &self,
rng: &mut R, rng: &mut R,
blinded_element: &BlindedElement<CS>, blinded_element: &BlindedElement<CS>,
) -> VoprfServerEvaluateResult<CS> { ) -> VoprfServerEvaluateResult<CS> {
let mut prepared_evaluation_elements = let mut prepared_evaluation_elements =
self.batch_evaluate_prepare(iter::once(blinded_element)); self.batch_blind_evaluate_prepare(iter::once(blinded_element));
let prepared_evaluation_element = [prepared_evaluation_elements.next().unwrap()]; let prepared_evaluation_element = [prepared_evaluation_elements.next().unwrap()];
// This can't fail because we know the size of the inputs. // This can't fail because we know the size of the inputs.
@@ -267,7 +268,7 @@ where
mut messages, mut messages,
proof, proof,
} = self } = self
.batch_evaluate_finish( .batch_blind_evaluate_finish(
rng, rng,
iter::once(blinded_element), iter::once(blinded_element),
&prepared_evaluation_element, &prepared_evaluation_element,
@@ -286,7 +287,7 @@ where
/// [`Error::Batch`] if the number of `blinded_elements` and /// [`Error::Batch`] if the number of `blinded_elements` and
/// `evaluation_elements` don't match or is longer then [`u16::MAX`] /// `evaluation_elements` don't match or is longer then [`u16::MAX`]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub fn batch_evaluate<'a, R: RngCore + CryptoRng, I>( pub fn batch_blind_evaluate<'a, R: RngCore + CryptoRng, I>(
&self, &self,
rng: &mut R, rng: &mut R,
blinded_elements: &'a I, blinded_elements: &'a I,
@@ -297,10 +298,10 @@ where
<&'a I as IntoIterator>::IntoIter: ExactSizeIterator, <&'a I as IntoIterator>::IntoIter: ExactSizeIterator,
{ {
let prepared_evaluation_elements = self let prepared_evaluation_elements = self
.batch_evaluate_prepare(blinded_elements.into_iter()) .batch_blind_evaluate_prepare(blinded_elements.into_iter())
.collect(); .collect();
let VoprfServerBatchEvaluateFinishResult { messages, proof } = self let VoprfServerBatchEvaluateFinishResult { messages, proof } = self
.batch_evaluate_finish::<_, _, Vec<_>>( .batch_blind_evaluate_finish::<_, _, Vec<_>>(
rng, rng,
blinded_elements.into_iter(), blinded_elements.into_iter(),
&prepared_evaluation_elements, &prepared_evaluation_elements,
@@ -310,11 +311,11 @@ where
Ok(VoprfServerBatchEvaluateResult { messages, proof }) Ok(VoprfServerBatchEvaluateResult { messages, proof })
} }
/// Alternative version of `batch_evaluate` without /// Alternative version of `batch_blind_evaluate` without memory allocation.
/// memory allocation. Returned [`PreparedEvaluationElement`] have to be /// Returned [`PreparedEvaluationElement`] have to be
/// [`collect`](Iterator::collect)ed and passed into /// [`collect`](Iterator::collect)ed and passed into
/// [`batch_evaluate_finish`](Self::batch_evaluate_finish). /// [`batch_blind_evaluate_finish`](Self::batch_blind_evaluate_finish).
pub fn batch_evaluate_prepare<'a, I: Iterator<Item = &'a BlindedElement<CS>>>( pub fn batch_blind_evaluate_prepare<'a, I: Iterator<Item = &'a BlindedElement<CS>>>(
&self, &self,
blinded_elements: I, blinded_elements: I,
) -> VoprfServerBatchEvaluatePreparedEvaluationElements<CS, I> ) -> VoprfServerBatchEvaluatePreparedEvaluationElements<CS, I>
@@ -328,13 +329,13 @@ where
}) })
} }
/// See [`batch_evaluate_prepare`](Self::batch_evaluate_prepare) for more /// See [`batch_blind_evaluate_prepare`](Self::batch_blind_evaluate_prepare)
/// details. /// for more details.
/// ///
/// # Errors /// # Errors
/// [`Error::Batch`] if the number of `blinded_elements` and /// [`Error::Batch`] if the number of `blinded_elements` and
/// `evaluation_elements` don't match or is longer then [`u16::MAX`] /// `evaluation_elements` don't match or is longer then [`u16::MAX`]
pub fn batch_evaluate_finish< pub fn batch_blind_evaluate_finish<
'a, 'a,
'b, 'b,
R: RngCore + CryptoRng, R: RngCore + CryptoRng,
@@ -371,6 +372,22 @@ where
Ok(VoprfServerBatchEvaluateFinishResult { messages, proof }) Ok(VoprfServerBatchEvaluateFinishResult { messages, proof })
} }
/// Computes the output of the POPRF on the server side
///
/// # Errors
/// [`Error::Input`] if the `input` is longer then [`u16::MAX`].
pub fn evaluate(&self, input: &[u8]) -> Result<Output<<CS as CipherSuite>::Hash>> {
let input_element = hash_to_group::<CS>(input, Mode::Voprf)?;
if CS::Group::is_identity_elem(input_element).into() {
return Err(Error::Input);
};
let evaluated_element = input_element * &self.sk;
let issued_element = CS::Group::serialize_elem(evaluated_element);
server_evaluate_hash_input::<CS>(input, None, issued_element)
}
/// Retrieves the server's public key /// Retrieves the server's public key
pub fn get_public_key(&self) -> <CS::Group as Group>::Elem { pub fn get_public_key(&self) -> <CS::Group as Group>::Elem {
self.pk self.pk
@@ -431,7 +448,7 @@ where
} }
/// Concrete type of [`EvaluationElement`]s returned by /// Concrete type of [`EvaluationElement`]s returned by
/// [`VoprfServer::batch_evaluate_prepare`]. /// [`VoprfServer::batch_blind_evaluate_prepare`].
pub type VoprfServerBatchEvaluatePreparedEvaluationElements<CS, I> = Map< pub type VoprfServerBatchEvaluatePreparedEvaluationElements<CS, I> = Map<
Zip<I, Repeat<<<CS as CipherSuite>::Group as Group>::Scalar>>, Zip<I, Repeat<<<CS as CipherSuite>::Group as Group>::Scalar>>,
fn( fn(
@@ -608,7 +625,7 @@ mod tests {
let mut rng = OsRng; let mut rng = OsRng;
let client_blind_result = VoprfClient::<CS>::blind(input, &mut rng).unwrap(); let client_blind_result = VoprfClient::<CS>::blind(input, &mut rng).unwrap();
let server = VoprfServer::<CS>::new(&mut rng).unwrap(); let server = VoprfServer::<CS>::new(&mut rng).unwrap();
let server_result = server.evaluate(&mut rng, &client_blind_result.message); let server_result = server.blind_evaluate(&mut rng, &client_blind_result.message);
let client_finalize_result = client_blind_result let client_finalize_result = client_blind_result
.state .state
.finalize( .finalize(
@@ -642,10 +659,10 @@ mod tests {
} }
let server = VoprfServer::<CS>::new(&mut rng).unwrap(); let server = VoprfServer::<CS>::new(&mut rng).unwrap();
let prepared_evaluation_elements: Vec<_> = server let prepared_evaluation_elements: Vec<_> = server
.batch_evaluate_prepare(client_messages.iter()) .batch_blind_evaluate_prepare(client_messages.iter())
.collect(); .collect();
let VoprfServerBatchEvaluateFinishResult { messages, proof } = server let VoprfServerBatchEvaluateFinishResult { messages, proof } = server
.batch_evaluate_finish( .batch_blind_evaluate_finish(
&mut rng, &mut rng,
client_messages.iter(), client_messages.iter(),
&prepared_evaluation_elements, &prepared_evaluation_elements,
@@ -690,10 +707,10 @@ mod tests {
} }
let server = VoprfServer::<CS>::new(&mut rng).unwrap(); let server = VoprfServer::<CS>::new(&mut rng).unwrap();
let prepared_evaluation_elements: Vec<_> = server let prepared_evaluation_elements: Vec<_> = server
.batch_evaluate_prepare(client_messages.iter()) .batch_blind_evaluate_prepare(client_messages.iter())
.collect(); .collect();
let VoprfServerBatchEvaluateFinishResult { messages, proof } = server let VoprfServerBatchEvaluateFinishResult { messages, proof } = server
.batch_evaluate_finish( .batch_blind_evaluate_finish(
&mut rng, &mut rng,
client_messages.iter(), client_messages.iter(),
&prepared_evaluation_elements, &prepared_evaluation_elements,
@@ -720,7 +737,7 @@ mod tests {
let mut rng = OsRng; let mut rng = OsRng;
let client_blind_result = VoprfClient::<CS>::blind(input, &mut rng).unwrap(); let client_blind_result = VoprfClient::<CS>::blind(input, &mut rng).unwrap();
let server = VoprfServer::<CS>::new(&mut rng).unwrap(); let server = VoprfServer::<CS>::new(&mut rng).unwrap();
let server_result = server.evaluate(&mut rng, &client_blind_result.message); let server_result = server.blind_evaluate(&mut rng, &client_blind_result.message);
let wrong_pk = { let wrong_pk = {
let dst = GenericArray::from(STR_HASH_TO_GROUP) let dst = GenericArray::from(STR_HASH_TO_GROUP)
.concat(create_context_string::<CS>(Mode::Oprf)); .concat(create_context_string::<CS>(Mode::Oprf));
@@ -736,6 +753,39 @@ mod tests {
assert!(client_finalize_result.is_err()); assert!(client_finalize_result.is_err());
} }
fn verifiable_server_evaluate<CS: CipherSuite>()
where
<CS::Hash as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
{
let input = b"input";
let mut rng = OsRng;
let client_blind_result = VoprfClient::<CS>::blind(input, &mut rng).unwrap();
let server = VoprfServer::<CS>::new(&mut rng).unwrap();
let server_result = server.blind_evaluate(&mut rng, &client_blind_result.message);
let client_finalize = client_blind_result
.state
.finalize(
input,
&server_result.message,
&server_result.proof,
server.get_public_key(),
)
.unwrap();
// We expect the outputs from client and server to be equal given an identical
// input
let server_evaluate = server.evaluate(input).unwrap();
assert_eq!(client_finalize, server_evaluate);
// We expect the outputs from client and server to be different given different
// inputs
let wrong_input = b"wrong input";
let server_evaluate = server.evaluate(wrong_input).unwrap();
assert!(client_finalize != server_evaluate);
}
fn zeroize_voprf_client<CS: CipherSuite>() fn zeroize_voprf_client<CS: CipherSuite>()
where where
<CS::Hash as OutputSizeUser>::OutputSize: <CS::Hash as OutputSizeUser>::OutputSize:
@@ -769,7 +819,7 @@ mod tests {
let mut rng = OsRng; let mut rng = OsRng;
let client_blind_result = VoprfClient::<CS>::blind(input, &mut rng).unwrap(); let client_blind_result = VoprfClient::<CS>::blind(input, &mut rng).unwrap();
let server = VoprfServer::<CS>::new(&mut rng).unwrap(); let server = VoprfServer::<CS>::new(&mut rng).unwrap();
let server_result = server.evaluate(&mut rng, &client_blind_result.message); let server_result = server.blind_evaluate(&mut rng, &client_blind_result.message);
let mut state = server; let mut state = server;
unsafe { ptr::drop_in_place(&mut state) }; unsafe { ptr::drop_in_place(&mut state) };
@@ -796,6 +846,7 @@ mod tests {
verifiable_batch_retrieval::<Ristretto255>(); verifiable_batch_retrieval::<Ristretto255>();
verifiable_bad_public_key::<Ristretto255>(); verifiable_bad_public_key::<Ristretto255>();
verifiable_batch_bad_public_key::<Ristretto255>(); verifiable_batch_bad_public_key::<Ristretto255>();
verifiable_server_evaluate::<Ristretto255>();
zeroize_voprf_client::<Ristretto255>(); zeroize_voprf_client::<Ristretto255>();
zeroize_voprf_server::<Ristretto255>(); zeroize_voprf_server::<Ristretto255>();
@@ -805,6 +856,7 @@ mod tests {
verifiable_batch_retrieval::<NistP256>(); verifiable_batch_retrieval::<NistP256>();
verifiable_bad_public_key::<NistP256>(); verifiable_bad_public_key::<NistP256>();
verifiable_batch_bad_public_key::<NistP256>(); verifiable_batch_bad_public_key::<NistP256>();
verifiable_server_evaluate::<NistP256>();
zeroize_voprf_client::<NistP256>(); zeroize_voprf_client::<NistP256>();
zeroize_voprf_server::<NistP256>(); zeroize_voprf_server::<NistP256>();