Configure Rustfmt and Taplo (#38)
* Configure rustfmt * Add Taplo configuration and run in CI
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
// 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.
|
||||
@@ -128,18 +128,18 @@ jobs:
|
||||
args: --no-deps --document-private-items --features std,p256
|
||||
|
||||
|
||||
format:
|
||||
rustfmt:
|
||||
name: cargo fmt
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install stable toolchain
|
||||
- name: Install nightly toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
toolchain: nightly
|
||||
override: true
|
||||
components: rustfmt
|
||||
|
||||
@@ -148,3 +148,25 @@ jobs:
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
||||
|
||||
taplo:
|
||||
name: Taplo
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/.crates.toml
|
||||
~/.cargo/.crates2.json
|
||||
~/.cargo/bin/taplo
|
||||
key: taplo
|
||||
|
||||
- name: Install Taplo
|
||||
run: cargo install taplo-cli
|
||||
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Run Taplo
|
||||
run: taplo fmt --check
|
||||
|
||||
+15
-12
@@ -1,26 +1,26 @@
|
||||
[package]
|
||||
name = "voprf"
|
||||
version = "0.3.0"
|
||||
description = "An implementation of a verifiable oblivious pseudorandom function (VOPRF)"
|
||||
authors = ["Kevin Lewi <[email protected]>"]
|
||||
repository = "https://github.com/novifinancial/voprf/"
|
||||
categories = ["no-std", "algorithms", "cryptography"]
|
||||
description = "An implementation of a verifiable oblivious pseudorandom function (VOPRF)"
|
||||
edition = "2018"
|
||||
keywords = ["oprf"]
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
name = "voprf"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/novifinancial/voprf/"
|
||||
resolver = "2"
|
||||
rust-version = "1.51.0"
|
||||
version = "0.3.0"
|
||||
|
||||
[features]
|
||||
default = ["ristretto255_u64", "serde"]
|
||||
danger = []
|
||||
ristretto255_u64 = ["curve25519-dalek/u64_backend"]
|
||||
ristretto255_u32 = ["curve25519-dalek/u32_backend"]
|
||||
ristretto255_fiat_u64 = ["curve25519-dalek/fiat_u64_backend"]
|
||||
ristretto255_fiat_u32 = ["curve25519-dalek/fiat_u32_backend"]
|
||||
ristretto255_simd = ["curve25519-dalek/simd_backend"]
|
||||
default = ["ristretto255_u64", "serde"]
|
||||
p256 = ["num-bigint", "num-integer", "num-traits", "once_cell", "p256_"]
|
||||
ristretto255_fiat_u32 = ["curve25519-dalek/fiat_u32_backend"]
|
||||
ristretto255_fiat_u64 = ["curve25519-dalek/fiat_u64_backend"]
|
||||
ristretto255_simd = ["curve25519-dalek/simd_backend"]
|
||||
ristretto255_u32 = ["curve25519-dalek/u32_backend"]
|
||||
ristretto255_u64 = ["curve25519-dalek/u64_backend"]
|
||||
std = []
|
||||
|
||||
[dependencies]
|
||||
@@ -33,7 +33,10 @@ num-bigint = { version = "0.4", default-features = false, optional = true }
|
||||
num-integer = { version = "0.1", default-features = false, optional = true }
|
||||
num-traits = { version = "0.2", default-features = false, optional = true }
|
||||
once_cell = { version = "1", default-features = false, optional = true }
|
||||
p256_ = { package = "p256", version = "0.9", default-features = false, features = ["arithmetic", "zeroize"], optional = true }
|
||||
p256_ = { package = "p256", version = "0.9", default-features = false, features = [
|
||||
"arithmetic",
|
||||
"zeroize",
|
||||
], optional = true }
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
serde = { version = "1", default-features = false, optional = true }
|
||||
subtle = { version = "2.3", default-features = false }
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
format_code_in_doc_comments = true
|
||||
format_strings = true
|
||||
group_imports = "StdExternalCrate"
|
||||
imports_granularity = "Module"
|
||||
license_template_path = ".cargo/license.rs"
|
||||
newline_style = "Unix"
|
||||
unstable_features = true
|
||||
wrap_comments = true
|
||||
+9
-11
@@ -5,15 +5,15 @@
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
|
||||
use core::ops::Add;
|
||||
|
||||
use digest::{BlockInput, Digest};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{Unsigned, U1, U2};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
use crate::errors::InternalError;
|
||||
use crate::util::i2osp;
|
||||
use core::ops::Add;
|
||||
use digest::{BlockInput, Digest};
|
||||
use generic_array::{
|
||||
sequence::Concat,
|
||||
typenum::{Unsigned, U1, U2},
|
||||
ArrayLength, GenericArray,
|
||||
};
|
||||
|
||||
// Computes ceil(x / y)
|
||||
fn div_ceil(x: usize, y: usize) -> usize {
|
||||
@@ -79,10 +79,8 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use generic_array::{
|
||||
typenum::{U128, U32},
|
||||
GenericArray,
|
||||
};
|
||||
use generic_array::typenum::{U128, U32};
|
||||
use generic_array::GenericArray;
|
||||
|
||||
struct Params {
|
||||
msg: &'static str,
|
||||
|
||||
+11
-8
@@ -22,14 +22,17 @@ cfg_ristretto! {
|
||||
mod ristretto;
|
||||
}
|
||||
|
||||
use crate::errors::InternalError;
|
||||
use core::ops::{Add, Mul, Sub};
|
||||
|
||||
use digest::{BlockInput, Digest};
|
||||
use generic_array::{typenum::U1, ArrayLength, GenericArray};
|
||||
use generic_array::typenum::U1;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use subtle::ConstantTimeEq;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::errors::InternalError;
|
||||
|
||||
/// A prime-order subgroup of a base field (EC, prime-order field ...). This
|
||||
/// subgroup is noted additively — as in the draft RFC — in this trait.
|
||||
pub trait Group:
|
||||
@@ -80,8 +83,8 @@ pub trait Group:
|
||||
scalar_bits: &GenericArray<u8, Self::ScalarLen>,
|
||||
) -> Result<Self::Scalar, InternalError>;
|
||||
|
||||
/// Return a scalar from its fixed-length bytes representation. If the scalar
|
||||
/// is zero, then return an error.
|
||||
/// Return a scalar from its fixed-length bytes representation. If the
|
||||
/// scalar is zero, then return an error.
|
||||
fn from_scalar_slice<'a>(
|
||||
scalar_bits: impl Into<&'a GenericArray<u8, Self::ScalarLen>>,
|
||||
) -> Result<Self::Scalar, InternalError> {
|
||||
@@ -103,14 +106,14 @@ pub trait Group:
|
||||
type ElemLen: ArrayLength<u8> + 'static;
|
||||
|
||||
/// Return an element from its fixed-length bytes representation. This is
|
||||
/// the unchecked version, which does not check for deserializing the identity
|
||||
/// element
|
||||
/// the unchecked version, which does not check for deserializing the
|
||||
/// identity element
|
||||
fn from_element_slice_unchecked(
|
||||
element_bits: &GenericArray<u8, Self::ElemLen>,
|
||||
) -> Result<Self, InternalError>;
|
||||
|
||||
/// Return an element from its fixed-length bytes representation. If the element
|
||||
/// is the identity element, return an error.
|
||||
/// Return an element from its fixed-length bytes representation. If the
|
||||
/// element is the identity element, return an error.
|
||||
fn from_element_slice<'a>(
|
||||
element_bits: impl Into<&'a GenericArray<u8, Self::ElemLen>>,
|
||||
) -> Result<Self, InternalError> {
|
||||
|
||||
+13
-8
@@ -5,18 +5,17 @@
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
|
||||
// Note: This group implementation of p256 is experimental for now,
|
||||
// until hash-to-curve or crypto-bigint are fully supported.
|
||||
// Note: This group implementation of p256 is experimental for now, until
|
||||
// hash-to-curve or crypto-bigint are fully supported.
|
||||
|
||||
#![allow(
|
||||
clippy::borrow_interior_mutable_const,
|
||||
clippy::declare_interior_mutable_const
|
||||
)]
|
||||
|
||||
use super::Group;
|
||||
use crate::errors::InternalError;
|
||||
use core::ops::{Add, Div, Mul, Neg};
|
||||
use core::str::FromStr;
|
||||
|
||||
use digest::{BlockInput, Digest};
|
||||
use generic_array::typenum::{Unsigned, U1, U2, U32, U33, U48};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
@@ -32,6 +31,9 @@ use p256_::{AffinePoint, EncodedPoint, ProjectivePoint};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use subtle::{Choice, ConditionallySelectable};
|
||||
|
||||
use super::Group;
|
||||
use crate::errors::InternalError;
|
||||
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2
|
||||
// `L: 48`
|
||||
pub type L = U48;
|
||||
@@ -109,7 +111,9 @@ impl Group for ProjectivePoint {
|
||||
<D as Add<U1>>::Output: ArrayLength<u8>,
|
||||
{
|
||||
// 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`
|
||||
// P-256 `n` is defined as
|
||||
// `115792089210356248762697446949407573529996955224135760342
|
||||
// 422259061068512044369`
|
||||
const N: Lazy<BigInt> = Lazy::new(|| {
|
||||
BigInt::from_str(
|
||||
"115792089210356248762697446949407573529996955224135760342422259061068512044369",
|
||||
@@ -182,8 +186,8 @@ impl Group for ProjectivePoint {
|
||||
/// Corresponds to the hash_to_curve_simple_swu() function defined in
|
||||
/// <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-F.2>
|
||||
///
|
||||
/// `cmov`, `mod_floor` and `modpow` needs to be made constant-time, which
|
||||
/// will be supported after crypto-bigint is no longer experimental. See
|
||||
/// `cmov`, `mod_floor` and `modpow` needs to be made constant-time, which will
|
||||
/// be supported after crypto-bigint is no longer experimental. See
|
||||
/// <https://github.com/novifinancial/voprf/issues/13> for more context.
|
||||
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
@@ -435,9 +439,10 @@ fn hash_to_curve_simple_swu<N: ArrayLength<u8>>(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use generic_array::typenum::U96;
|
||||
|
||||
use super::*;
|
||||
|
||||
struct Params {
|
||||
msg: &'static str,
|
||||
px: &'static str,
|
||||
|
||||
@@ -22,8 +22,8 @@ use generic_array::{
|
||||
};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
// `cfg` here is only needed because of a bug in Rust's crate feature documentation.
|
||||
// See: https://github.com/rust-lang/rust/issues/83428
|
||||
// `cfg` here is only needed because of a bug in Rust's crate feature documentation. See:
|
||||
// https://github.com/rust-lang/rust/issues/83428
|
||||
cfg_ristretto! {
|
||||
/// The implementation of such a subgroup for Ristretto
|
||||
impl Group for RistrettoPoint {
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@
|
||||
use crate::errors::InternalError;
|
||||
use crate::group::Group;
|
||||
|
||||
// Test that the deserialization of a group element should throw an error
|
||||
// if the identity element can be deserialized properly
|
||||
// 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> {
|
||||
|
||||
+121
-118
@@ -14,10 +14,10 @@
|
||||
//!
|
||||
//! # Overview
|
||||
//!
|
||||
//! A verifiable oblivious pseudorandom function is a protocol that is
|
||||
//! evaluated between a client and a server. They must first agree on a
|
||||
//! collection of primitives to be kept consistent throughout protocol
|
||||
//! execution. These include:
|
||||
//! A verifiable oblivious pseudorandom function is a protocol that is evaluated
|
||||
//! between a client and a server. They must first agree on a collection of
|
||||
//! primitives to be kept consistent throughout protocol execution. These
|
||||
//! include:
|
||||
//! - a finite cyclic group along with a point representation, and
|
||||
//! - a hashing function.
|
||||
//!
|
||||
@@ -31,35 +31,35 @@
|
||||
//! ## Modes of Operation
|
||||
//!
|
||||
//! VOPRF can be used in two modes:
|
||||
//! - [Base Mode](#base-mode), which corresponds to a normal OPRF evaluation with no
|
||||
//! support for the verification of the OPRF outputs
|
||||
//! - [Verifiable Mode](#verifiable-mode), which corresponds to an OPRF evaluation where
|
||||
//! the outputs can be verified against a server public key
|
||||
//! - [Base Mode](#base-mode), which corresponds to a normal OPRF evaluation
|
||||
//! with no support for the verification of the OPRF outputs
|
||||
//! - [Verifiable Mode](#verifiable-mode), which corresponds to an OPRF
|
||||
//! evaluation where the outputs can be verified against a server public key
|
||||
//!
|
||||
//! In either mode, the protocol begins with a client blinding, followed by
|
||||
//! a server evaluation, and finishes with a client finalization.
|
||||
//! In either mode, the protocol begins with a client blinding, followed by a
|
||||
//! server evaluation, and finishes with a client finalization.
|
||||
//!
|
||||
//! ## Base Mode
|
||||
//!
|
||||
//! In base mode, a [NonVerifiableClient] interacts with a
|
||||
//! [NonVerifiableServer] to compute the output of the VOPRF.
|
||||
//! In base mode, a [NonVerifiableClient] interacts with a [NonVerifiableServer]
|
||||
//! to compute the output of the VOPRF.
|
||||
//!
|
||||
//! ### Server Setup
|
||||
//!
|
||||
//! The protocol begins with a setup phase, in which the server must run
|
||||
//! [NonVerifiableServer::new()] to produce an instance of itself. This
|
||||
//! instance must be persisted on the server and used for online
|
||||
//! client evaluations.
|
||||
//! [NonVerifiableServer::new()] to produce an instance of itself. This instance
|
||||
//! must be persisted on the server and used for online client evaluations.
|
||||
//!
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! use rand::rngs::OsRng;
|
||||
//! use rand::RngCore;
|
||||
//! use voprf::NonVerifiableServer;
|
||||
//! use rand::{rngs::OsRng, RngCore};
|
||||
//!
|
||||
//! let mut server_rng = OsRng;
|
||||
//! let server = NonVerifiableServer::<Group, Hash>::new(&mut server_rng)
|
||||
//! .expect("Unable to construct server");
|
||||
//! .expect("Unable to construct server");
|
||||
//! ```
|
||||
//!
|
||||
//! ### Client Blinding
|
||||
@@ -73,14 +73,14 @@
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! use rand::rngs::OsRng;
|
||||
//! use rand::RngCore;
|
||||
//! use voprf::NonVerifiableClient;
|
||||
//! use rand::{rngs::OsRng, RngCore};
|
||||
//!
|
||||
//! let mut client_rng = OsRng;
|
||||
//! let client_blind_result = NonVerifiableClient::<Group, Hash>::blind(
|
||||
//! b"input".to_vec(),
|
||||
//! &mut client_rng,
|
||||
//! ).expect("Unable to construct client");
|
||||
//! let client_blind_result =
|
||||
//! NonVerifiableClient::<Group, Hash>::blind(b"input".to_vec(), &mut client_rng)
|
||||
//! .expect("Unable to construct client");
|
||||
//! ```
|
||||
//!
|
||||
//! ### Server Evaluation
|
||||
@@ -106,10 +106,9 @@
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! # let server = NonVerifiableServer::<Group, Hash>::new(&mut server_rng)
|
||||
//! # .expect("Unable to construct server");
|
||||
//! let server_evaluate_result = server.evaluate(
|
||||
//! &client_blind_result.message,
|
||||
//! None,
|
||||
//! ).expect("Unable to perform server evaluate");
|
||||
//! let server_evaluate_result = server
|
||||
//! .evaluate(&client_blind_result.message, None)
|
||||
//! .expect("Unable to perform server evaluate");
|
||||
//! ```
|
||||
//!
|
||||
//! ### Client Finalization
|
||||
@@ -137,79 +136,79 @@
|
||||
//! # &client_blind_result.message,
|
||||
//! # None,
|
||||
//! # ).expect("Unable to perform server evaluate");
|
||||
//! let client_finalize_result = client_blind_result.state.finalize(
|
||||
//! &server_evaluate_result.message,
|
||||
//! None,
|
||||
//! ).expect("Unable to perform client finalization");
|
||||
//! let client_finalize_result = client_blind_result
|
||||
//! .state
|
||||
//! .finalize(&server_evaluate_result.message, None)
|
||||
//! .expect("Unable to perform client finalization");
|
||||
//!
|
||||
//! println!("VOPRF output: {:?}", client_finalize_result.to_vec());
|
||||
//! ```
|
||||
//!
|
||||
//! ## Verifiable Mode
|
||||
//!
|
||||
//! In verifiable mode, a [VerifiableClient] interacts with a
|
||||
//! [VerifiableServer] to 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 public key. If the proof fails to verify,
|
||||
//! then the client does not receive an output.
|
||||
//! In verifiable mode, a [VerifiableClient] interacts with a [VerifiableServer]
|
||||
//! to 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
|
||||
//! public key. If the proof fails to verify, then the client does not receive
|
||||
//! an output.
|
||||
//!
|
||||
//! In batch mode, a single proof can be used for multiple VOPRF evaluations.
|
||||
//! See [the batching section](#batching)
|
||||
//! for more details on how to perform batch evaluations.
|
||||
//! See [the batching section](#batching) for more details on how to perform
|
||||
//! batch evaluations.
|
||||
//!
|
||||
//! ### Server Setup
|
||||
//!
|
||||
//! The protocol begins with a setup phase, in which the server must run
|
||||
//! [VerifiableServer::new()] to produce an instance of itself. This
|
||||
//! instance must be persisted on the server and used for online
|
||||
//! client evaluations.
|
||||
//! [VerifiableServer::new()] to produce an instance of itself. This instance
|
||||
//! must be persisted on the server and used for online client evaluations.
|
||||
//!
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! use rand::rngs::OsRng;
|
||||
//! use rand::RngCore;
|
||||
//! use voprf::VerifiableServer;
|
||||
//! use rand::{rngs::OsRng, RngCore};
|
||||
//!
|
||||
//! let mut server_rng = OsRng;
|
||||
//! let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
|
||||
//! .expect("Unable to construct server");
|
||||
//! let server =
|
||||
//! VerifiableServer::<Group, Hash>::new(&mut server_rng).expect("Unable to construct server");
|
||||
//!
|
||||
//! // To be sent to the client
|
||||
//! println!("Server public key: {:?}", server.get_public_key());
|
||||
//! ```
|
||||
//!
|
||||
//! The public key should be sent to the client, since the client will
|
||||
//! need it in the final step of the protocol in order to complete
|
||||
//! the evaluation of the VOPRF.
|
||||
//! The public key should be sent to the client, since the client will need it
|
||||
//! in the final step of the protocol in order to complete the evaluation of the
|
||||
//! VOPRF.
|
||||
//!
|
||||
//! ### Client Blinding
|
||||
//!
|
||||
//! In the first step, the client chooses an input, and runs
|
||||
//! [VerifiableClient::blind] to produce a [VerifiableClientBlindResult],
|
||||
//! which consists of a [BlindedElement] to be sent to the server and a
|
||||
//! [VerifiableClient] which must be persisted on the client for the final
|
||||
//! step of the VOPRF protocol.
|
||||
//! [VerifiableClient::blind] to produce a [VerifiableClientBlindResult], which
|
||||
//! consists of a [BlindedElement] to be sent to the server and a
|
||||
//! [VerifiableClient] which must be persisted on the client for the final step
|
||||
//! of the VOPRF protocol.
|
||||
//!
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! use rand::rngs::OsRng;
|
||||
//! use rand::RngCore;
|
||||
//! use voprf::VerifiableClient;
|
||||
//! use rand::{rngs::OsRng, RngCore};
|
||||
//!
|
||||
//! let mut client_rng = OsRng;
|
||||
//! let client_blind_result = VerifiableClient::<Group, Hash>::blind(
|
||||
//! b"input".to_vec(),
|
||||
//! &mut client_rng,
|
||||
//! ).expect("Unable to construct client");
|
||||
//! let client_blind_result =
|
||||
//! VerifiableClient::<Group, Hash>::blind(b"input".to_vec(), &mut client_rng)
|
||||
//! .expect("Unable to construct client");
|
||||
//! ```
|
||||
//!
|
||||
//! ### Server Evaluation
|
||||
//!
|
||||
//! In the second step, the server takes as input the message from
|
||||
//! [VerifiableClient::blind] (a [BlindedElement]), and runs
|
||||
//! [VerifiableServer::evaluate] to produce a
|
||||
//! [VerifiableServerEvaluateResult], which consists of an
|
||||
//! [EvaluationElement] to be sent to the client along with a proof.
|
||||
//! [VerifiableServer::evaluate] to produce a [VerifiableServerEvaluateResult],
|
||||
//! which consists of an [EvaluationElement] to be sent to the client along with
|
||||
//! a proof.
|
||||
//!
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
@@ -226,19 +225,17 @@
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
|
||||
//! # .expect("Unable to construct server");
|
||||
//! let server_evaluate_result = server.evaluate(
|
||||
//! &mut server_rng,
|
||||
//! &client_blind_result.message,
|
||||
//! None,
|
||||
//! ).expect("Unable to perform server evaluate");
|
||||
//! let server_evaluate_result = server
|
||||
//! .evaluate(&mut server_rng, &client_blind_result.message, None)
|
||||
//! .expect("Unable to perform server evaluate");
|
||||
//! ```
|
||||
//!
|
||||
//! ### Client Finalization
|
||||
//!
|
||||
//! In the final step, the client takes as input the message from
|
||||
//! [VerifiableServer::evaluate] (an [EvaluationElement]),
|
||||
//! the proof, and the server's public key, and runs
|
||||
//! [VerifiableClient::finalize] to produce an output for the protocol.
|
||||
//! [VerifiableServer::evaluate] (an [EvaluationElement]), the proof, and the
|
||||
//! server's public key, and runs [VerifiableClient::finalize] to produce an
|
||||
//! output for the protocol.
|
||||
//!
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
@@ -260,12 +257,15 @@
|
||||
//! # &client_blind_result.message,
|
||||
//! # None,
|
||||
//! # ).expect("Unable to perform server evaluate");
|
||||
//! let client_finalize_result = client_blind_result.state.finalize(
|
||||
//! &server_evaluate_result.message,
|
||||
//! &server_evaluate_result.proof,
|
||||
//! server.get_public_key(),
|
||||
//! None,
|
||||
//! ).expect("Unable to perform client finalization");
|
||||
//! let client_finalize_result = client_blind_result
|
||||
//! .state
|
||||
//! .finalize(
|
||||
//! &server_evaluate_result.message,
|
||||
//! &server_evaluate_result.proof,
|
||||
//! server.get_public_key(),
|
||||
//! None,
|
||||
//! )
|
||||
//! .expect("Unable to perform client finalization");
|
||||
//!
|
||||
//! println!("VOPRF output: {:?}", client_finalize_result.to_vec());
|
||||
//! ```
|
||||
@@ -278,15 +278,14 @@
|
||||
//!
|
||||
//! ## Batching
|
||||
//!
|
||||
//! It is sometimes desirable to generate only a single, constant-size
|
||||
//! proof for an unbounded number of VOPRF evaluations (on arbitrary inputs).
|
||||
//! [VerifiableClient] and [VerifiableServer] support a batch API for
|
||||
//! handling this case. In the following example, we show how to use
|
||||
//! the batch API to produce a single proof for 10 parallel
|
||||
//! VOPRF evaluations.
|
||||
//! It is sometimes desirable to generate only a single, constant-size proof for
|
||||
//! an unbounded number of VOPRF evaluations (on arbitrary inputs).
|
||||
//! [VerifiableClient] and [VerifiableServer] support a batch API for handling
|
||||
//! this case. In the following example, we show how to use the batch API to
|
||||
//! produce a single proof for 10 parallel VOPRF evaluations.
|
||||
//!
|
||||
//! First, the client produces 10 blindings, storing their resulting
|
||||
//! states and messages:
|
||||
//! First, the client produces 10 blindings, storing their resulting states and
|
||||
//! messages:
|
||||
//!
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
@@ -298,19 +297,18 @@
|
||||
//! let mut client_states = vec![];
|
||||
//! let mut client_messages = vec![];
|
||||
//! for _ in 0..10 {
|
||||
//! let client_blind_result = VerifiableClient::<Group, Hash>::blind(
|
||||
//! b"input".to_vec(),
|
||||
//! &mut client_rng,
|
||||
//! ).expect("Unable to construct client");
|
||||
//! let client_blind_result =
|
||||
//! VerifiableClient::<Group, Hash>::blind(b"input".to_vec(), &mut client_rng)
|
||||
//! .expect("Unable to construct client");
|
||||
//! client_states.push(client_blind_result.state);
|
||||
//! client_messages.push(client_blind_result.message);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Next, the server calls the [VerifiableServer::batch_evaluate]
|
||||
//! function on a set of client messages, to produce a corresponding
|
||||
//! set of messages to be returned to the client (returned in the same order),
|
||||
//! along with a single proof:
|
||||
//! Next, the server calls the [VerifiableServer::batch_evaluate] function on a
|
||||
//! set of client messages, to produce a corresponding set of messages to be
|
||||
//! returned to the client (returned in the same order), along with a single
|
||||
//! proof:
|
||||
//!
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
@@ -333,17 +331,15 @@
|
||||
//! let mut server_rng = OsRng;
|
||||
//! # 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,
|
||||
//! &client_messages,
|
||||
//! None,
|
||||
//! ).expect("Unable to perform server batch evaluate");
|
||||
//! let server_batch_evaluate_result = server
|
||||
//! .batch_evaluate(&mut server_rng, &client_messages, None)
|
||||
//! .expect("Unable to perform server batch evaluate");
|
||||
//! ```
|
||||
//!
|
||||
//! Then, the client calls [VerifiableClient::batch_finalize] on
|
||||
//! the client states saved from the first step, along with the messages
|
||||
//! returned by the server, along with the server's proof, in order to produce
|
||||
//! a vector of outputs if the proof verifies correctly.
|
||||
//! Then, the client calls [VerifiableClient::batch_finalize] on the client
|
||||
//! states saved from the first step, along with the messages returned by the
|
||||
//! server, along with the server's proof, in order to produce a vector of
|
||||
//! outputs if the proof verifies correctly.
|
||||
//!
|
||||
//! ```
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
@@ -377,7 +373,8 @@
|
||||
//! &server_batch_evaluate_result.proof,
|
||||
//! server.get_public_key(),
|
||||
//! None,
|
||||
//! ).expect("Unable to perform client batch finalization");
|
||||
//! )
|
||||
//! .expect("Unable to perform client batch finalization");
|
||||
//!
|
||||
//! println!("VOPRF batch outputs: {:?}", client_batch_finalize_result);
|
||||
//! ```
|
||||
@@ -386,34 +383,40 @@
|
||||
//!
|
||||
//! The optional metadata parameter included in the protocol allows clients and
|
||||
//! servers (of either mode) to cryptographically bind additional data to the
|
||||
//! VOPRF output. This metadata is known to both parties at the start of the protocol,
|
||||
//! and is inserted under the server's evaluate step and the client's finalize step.
|
||||
//! This metadata can be constructed with some type of higher-level domain separation
|
||||
//! to avoid cross-protocol attacks or related issues.
|
||||
//! VOPRF output. This metadata is known to both parties at the start of the
|
||||
//! protocol, and is inserted under the server's evaluate step and the client's
|
||||
//! finalize step. This metadata can be constructed with some type of
|
||||
//! higher-level domain separation to avoid cross-protocol attacks or related
|
||||
//! issues.
|
||||
//!
|
||||
//! A custom metadata can be specified, for example, by: `Some(b"custom metadata")`.
|
||||
//! A custom metadata can be specified, for example, by:
|
||||
//! `Some(b"custom metadata")`.
|
||||
//!
|
||||
//! # Features
|
||||
//!
|
||||
//! - 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 `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 `serde` feature, enabled by default, provides convenience functions for serializing and deserializing with
|
||||
//! [serde](https://serde.rs/).
|
||||
//! - The `serde` feature, enabled by default, provides convenience functions
|
||||
//! for serializing and deserializing with [serde](https://serde.rs/).
|
||||
//!
|
||||
//! - The `danger` feature, disabled by default, exposes functions for setting and getting
|
||||
//! internal values not available in the default API. These functions are intended for use in
|
||||
//! by higher-level cryptographic protocols that need access to these raw values and are able to
|
||||
//! perform the necessary validations on them (such as being valid group elements).
|
||||
//! - The `danger` feature, disabled by default, exposes functions for setting
|
||||
//! and getting internal values not available in the default API. These
|
||||
//! functions are intended for use in by higher-level cryptographic protocols
|
||||
//! that need access to these raw values and are able to perform the necessary
|
||||
//! validations on them (such as being valid group elements).
|
||||
//!
|
||||
//! - The backend features are re-exported from
|
||||
//! [curve25519-dalek](https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features) and allow for selecting
|
||||
//! the corresponding backend for the curve arithmetic used. The `ristretto255_u64` feature is included as the default.
|
||||
//! Other features are mapped as `ristretto255_u32`, `ristretto255_fiat_u64` and `ristretto255_fiat_u32`.
|
||||
//! - The backend features are re-exported from [curve25519-dalek](https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features)
|
||||
//! and allow for selecting the corresponding backend for the curve arithmetic
|
||||
//! used. The `ristretto255_u64` feature is included as the default. Other
|
||||
//! features are mapped as `ristretto255_u32`, `ristretto255_fiat_u64` and
|
||||
//! `ristretto255_fiat_u32`.
|
||||
//!
|
||||
//! - The `ristretto255_simd` feature is re-exported from
|
||||
//! [curve25519-dalek](https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features) and enables parallel formulas,
|
||||
//! using either AVX2 or AVX512-IFMA. This will automatically enable the `ristretto255_u64` feature and requires Rust nightly.
|
||||
//! - The `ristretto255_simd` feature is re-exported from [curve25519-dalek](https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features)
|
||||
//! and enables parallel formulas, using either AVX2 or AVX512-IFMA. This will
|
||||
//! automatically enable the `ristretto255_u64` feature and requires Rust
|
||||
//! nightly.
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![no_std]
|
||||
|
||||
+10
-10
@@ -5,22 +5,22 @@
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
|
||||
//! Handles the serialization of each of the components used
|
||||
//! in the VOPRF protocol
|
||||
//! Handles the serialization of each of the components used in the VOPRF
|
||||
//! protocol
|
||||
|
||||
use crate::{
|
||||
errors::InternalError,
|
||||
group::Group,
|
||||
voprf::{
|
||||
BlindedElement, EvaluationElement, NonVerifiableClient, NonVerifiableServer, Proof,
|
||||
VerifiableClient, VerifiableServer,
|
||||
},
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use digest::{BlockInput, Digest};
|
||||
use generic_array::typenum::Unsigned;
|
||||
|
||||
use crate::errors::InternalError;
|
||||
use crate::group::Group;
|
||||
use crate::voprf::{
|
||||
BlindedElement, EvaluationElement, NonVerifiableClient, NonVerifiableServer, Proof,
|
||||
VerifiableClient, VerifiableServer,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Serialization and Deserialization for High-Level API //
|
||||
// ==================================================== //
|
||||
|
||||
@@ -7,21 +7,20 @@
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::cmp::min;
|
||||
|
||||
use rand_core::{CryptoRng, Error, RngCore};
|
||||
|
||||
/// A simple implementation of `RngCore` for testing purposes.
|
||||
///
|
||||
/// This generates a cyclic sequence (i.e. cycles over an initial buffer)
|
||||
///
|
||||
///
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CycleRng {
|
||||
v: Vec<u8>,
|
||||
}
|
||||
|
||||
impl CycleRng {
|
||||
/// Create a `CycleRng`, yielding a sequence starting with
|
||||
/// `initial` and looping thereafter
|
||||
/// Create a `CycleRng`, yielding a sequence starting with `initial` and
|
||||
/// looping thereafter
|
||||
pub fn new(initial: Vec<u8>) -> Self {
|
||||
CycleRng { v: initial }
|
||||
}
|
||||
|
||||
@@ -5,22 +5,23 @@
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
|
||||
use crate::{
|
||||
errors::InternalError,
|
||||
group::Group,
|
||||
tests::{mock_rng::CycleRng, parser::*},
|
||||
voprf::{
|
||||
BlindedElement, EvaluationElement, NonVerifiableClient, NonVerifiableServer, Proof,
|
||||
VerifiableClient, VerifiableServer,
|
||||
},
|
||||
};
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use digest::{BlockInput, Digest};
|
||||
use generic_array::GenericArray;
|
||||
use json::JsonValue;
|
||||
|
||||
use crate::errors::InternalError;
|
||||
use crate::group::Group;
|
||||
use crate::tests::mock_rng::CycleRng;
|
||||
use crate::tests::parser::*;
|
||||
use crate::voprf::{
|
||||
BlindedElement, EvaluationElement, NonVerifiableClient, NonVerifiableServer, Proof,
|
||||
VerifiableClient, VerifiableServer,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VOPRFTestVectorParameters {
|
||||
seed: Vec<u8>,
|
||||
|
||||
+12
-6
@@ -7,9 +7,12 @@
|
||||
|
||||
//! Helper functions
|
||||
|
||||
use crate::errors::InternalError;
|
||||
use core::array::IntoIter;
|
||||
use generic_array::{typenum::U0, ArrayLength, GenericArray};
|
||||
|
||||
use generic_array::typenum::U0;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
use crate::errors::InternalError;
|
||||
|
||||
// Corresponds to the I2OSP() function from RFC8017
|
||||
pub(crate) fn i2osp<L: ArrayLength<u8>>(
|
||||
@@ -100,8 +103,9 @@ macro_rules! chain_skip {
|
||||
};
|
||||
}
|
||||
|
||||
/// The purpose of this macro is to simplify [`concat`](alloc::slice::Concat::concat)ing
|
||||
/// slices into an [`Iterator`] to avoid allocation
|
||||
/// The purpose of this macro is to simplify
|
||||
/// [`concat`](alloc::slice::Concat::concat)ing slices into an [`Iterator`] to
|
||||
/// avoid allocation
|
||||
macro_rules! chain {
|
||||
(
|
||||
$var:ident,
|
||||
@@ -142,13 +146,15 @@ macro_rules! cfg_ristretto {
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use generic_array::typenum::{U1, U2};
|
||||
use proptest::collection::vec;
|
||||
use proptest::prelude::*;
|
||||
|
||||
use super::*;
|
||||
use crate::voprf::{
|
||||
BlindedElement, EvaluationElement, NonVerifiableClient, NonVerifiableServer, Proof,
|
||||
VerifiableClient, VerifiableServer,
|
||||
};
|
||||
use generic_array::typenum::{U1, U2};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
// Test the error condition for I2OSP
|
||||
#[test]
|
||||
|
||||
+69
-66
@@ -7,24 +7,22 @@
|
||||
|
||||
//! Contains the main VOPRF API
|
||||
|
||||
use crate::{
|
||||
errors::InternalError,
|
||||
group::Group,
|
||||
util::{i2osp, serialize, serialize_owned},
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
use core::convert::TryInto;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use derive_where::DeriveWhere;
|
||||
use digest::{BlockInput, Digest};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::{
|
||||
typenum::{U1, U11, U2},
|
||||
GenericArray,
|
||||
};
|
||||
use generic_array::typenum::{U1, U11, U2};
|
||||
use generic_array::GenericArray;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
use crate::errors::InternalError;
|
||||
use crate::group::Group;
|
||||
use crate::util::{i2osp, serialize, serialize_owned};
|
||||
|
||||
///////////////
|
||||
// Constants //
|
||||
// ========= //
|
||||
@@ -39,8 +37,7 @@ static STR_COMPOSITE: [u8; 10] = *b"Composite-";
|
||||
static STR_CHALLENGE: [u8; 10] = *b"Challenge-";
|
||||
static STR_VOPRF: [u8; 8] = *b"VOPRF08-";
|
||||
|
||||
/// Determines the mode of operation (either base mode or
|
||||
/// verifiable mode)
|
||||
/// Determines the mode of operation (either base mode or verifiable mode)
|
||||
#[derive(Clone, Copy)]
|
||||
enum Mode {
|
||||
Base = 0,
|
||||
@@ -52,9 +49,8 @@ enum Mode {
|
||||
// ====================== //
|
||||
////////////////////////////
|
||||
|
||||
/// A client which engages with a [NonVerifiableServer]
|
||||
/// in base mode, meaning that the OPRF outputs are not
|
||||
/// verifiable.
|
||||
/// A client which engages with a [NonVerifiableServer] in base mode, meaning
|
||||
/// that the OPRF outputs are not verifiable.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; G::Scalar)]
|
||||
@@ -67,9 +63,8 @@ pub struct NonVerifiableClient<G: Group, H: BlockInput + Digest> {
|
||||
|
||||
impl_serialize_and_deserialize_for!(NonVerifiableClient);
|
||||
|
||||
/// A client which engages with a [VerifiableServer]
|
||||
/// in verifiable mode, meaning that the OPRF outputs
|
||||
/// can be checked against a server public key.
|
||||
/// A client which engages with a [VerifiableServer] in verifiable mode, meaning
|
||||
/// that the OPRF outputs can be checked against a server public key.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; G, G::Scalar)]
|
||||
@@ -83,9 +78,8 @@ pub struct VerifiableClient<G: Group, H: BlockInput + Digest> {
|
||||
|
||||
impl_serialize_and_deserialize_for!(VerifiableClient);
|
||||
|
||||
/// A server which engages with a [NonVerifiableClient]
|
||||
/// in base mode, meaning that the OPRF outputs are not
|
||||
/// verifiable.
|
||||
/// A server which engages with a [NonVerifiableClient] in base mode, meaning
|
||||
/// that the OPRF outputs are not verifiable.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; G::Scalar)]
|
||||
@@ -97,9 +91,8 @@ pub struct NonVerifiableServer<G: Group, H: BlockInput + Digest> {
|
||||
|
||||
impl_serialize_and_deserialize_for!(NonVerifiableServer);
|
||||
|
||||
/// A server which engages with a [VerifiableClient]
|
||||
/// in verifiable mode, meaning that the OPRF outputs
|
||||
/// can be checked against a server public key.
|
||||
/// A server which engages with a [VerifiableClient] in verifiable mode, meaning
|
||||
/// that the OPRF outputs can be checked against a server public key.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; G, G::Scalar)]
|
||||
@@ -112,8 +105,8 @@ pub struct VerifiableServer<G: Group, H: BlockInput + Digest> {
|
||||
|
||||
impl_serialize_and_deserialize_for!(VerifiableServer);
|
||||
|
||||
/// A proof produced by a [VerifiableServer] that
|
||||
/// the OPRF output matches against a server public key.
|
||||
/// A proof produced by a [VerifiableServer] that the OPRF output matches
|
||||
/// against a server public key.
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; G::Scalar)]
|
||||
@@ -126,8 +119,8 @@ pub struct Proof<G: Group, H: BlockInput + Digest> {
|
||||
|
||||
impl_serialize_and_deserialize_for!(Proof);
|
||||
|
||||
/// The first client message sent from a client (either verifiable or not)
|
||||
/// to a server (either verifiable or not).
|
||||
/// The first client message sent from a client (either verifiable or not) to a
|
||||
/// server (either verifiable or not).
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; G)]
|
||||
@@ -139,9 +132,8 @@ pub struct BlindedElement<G: Group, H: BlockInput + Digest> {
|
||||
|
||||
impl_serialize_and_deserialize_for!(BlindedElement);
|
||||
|
||||
/// The server's response to the [BlindedElement] message from
|
||||
/// a client (either verifiable or not)
|
||||
/// to a server (either verifiable or not).
|
||||
/// The server's response to the [BlindedElement] message from a client (either
|
||||
/// verifiable or not) to a server (either verifiable or not).
|
||||
#[derive(DeriveWhere)]
|
||||
#[derive_where(Clone, Zeroize(drop))]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; G)]
|
||||
@@ -159,7 +151,8 @@ impl_serialize_and_deserialize_for!(EvaluationElement);
|
||||
/////////////////////////
|
||||
|
||||
impl<G: Group, H: BlockInput + Digest> NonVerifiableClient<G, H> {
|
||||
/// Computes the first step for the multiplicative blinding version of DH-OPRF.
|
||||
/// Computes the first step for the multiplicative blinding version of
|
||||
/// DH-OPRF.
|
||||
pub fn blind<R: RngCore + CryptoRng>(
|
||||
input: Vec<u8>,
|
||||
blinding_factor_rng: &mut R,
|
||||
@@ -179,13 +172,14 @@ impl<G: Group, H: BlockInput + Digest> NonVerifiableClient<G, H> {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "danger", test))]
|
||||
/// Computes the first step for the multiplicative blinding version of DH-OPRF,
|
||||
/// taking a blinding factor scalar as input instead of sampling from an RNG.
|
||||
/// Computes the first step for the multiplicative blinding version of
|
||||
/// DH-OPRF, taking a blinding factor scalar as input instead of sampling
|
||||
/// from an RNG.
|
||||
///
|
||||
/// # Caution
|
||||
///
|
||||
/// This should be used with caution, since
|
||||
/// it does not perform any checks on the validity of the blinding factor!
|
||||
/// This should be used with caution, since it does not perform any checks
|
||||
/// on the validity of the blinding factor!
|
||||
pub fn deterministic_blind_unchecked(
|
||||
input: Vec<u8>,
|
||||
blind: G::Scalar,
|
||||
@@ -204,8 +198,8 @@ impl<G: Group, H: BlockInput + Digest> NonVerifiableClient<G, H> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Computes the third step for the multiplicative blinding version of DH-OPRF, in which
|
||||
/// the client unblinds the server's message.
|
||||
/// Computes the third step for the multiplicative blinding version of
|
||||
/// DH-OPRF, in which the client unblinds the server's message.
|
||||
pub fn finalize(
|
||||
&self,
|
||||
evaluation_element: &EvaluationElement<G, H>,
|
||||
@@ -238,7 +232,8 @@ impl<G: Group, H: BlockInput + Digest> NonVerifiableClient<G, H> {
|
||||
}
|
||||
|
||||
impl<G: Group, H: BlockInput + Digest> VerifiableClient<G, H> {
|
||||
/// Computes the first step for the multiplicative blinding version of DH-OPRF.
|
||||
/// Computes the first step for the multiplicative blinding version of
|
||||
/// DH-OPRF.
|
||||
pub fn blind<R: RngCore + CryptoRng>(
|
||||
input: Vec<u8>,
|
||||
blinding_factor_rng: &mut R,
|
||||
@@ -260,13 +255,14 @@ impl<G: Group, H: BlockInput + Digest> VerifiableClient<G, H> {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "danger", test))]
|
||||
/// Computes the first step for the multiplicative blinding version of DH-OPRF,
|
||||
/// taking a blinding factor scalar as input instead of sampling from an RNG.
|
||||
/// Computes the first step for the multiplicative blinding version of
|
||||
/// DH-OPRF, taking a blinding factor scalar as input instead of sampling
|
||||
/// from an RNG.
|
||||
///
|
||||
/// # Caution
|
||||
///
|
||||
/// This should be used with caution, since
|
||||
/// it does not perform any checks on the validity of the blinding factor!
|
||||
/// This should be used with caution, since it does not perform any checks
|
||||
/// on the validity of the blinding factor!
|
||||
pub fn deterministic_blind_unchecked(
|
||||
input: Vec<u8>,
|
||||
blind: G::Scalar,
|
||||
@@ -287,8 +283,8 @@ impl<G: Group, H: BlockInput + Digest> VerifiableClient<G, H> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Computes the third step for the multiplicative blinding version of DH-OPRF, in which
|
||||
/// the client unblinds the server's message.
|
||||
/// Computes the third step for the multiplicative blinding version of
|
||||
/// DH-OPRF, in which the client unblinds the server's message.
|
||||
pub fn finalize(
|
||||
&self,
|
||||
evaluation_element: &EvaluationElement<G, H>,
|
||||
@@ -306,7 +302,8 @@ impl<G: Group, H: BlockInput + Digest> VerifiableClient<G, H> {
|
||||
Ok(batch_result[0].clone())
|
||||
}
|
||||
|
||||
/// Allows for batching of the finalization of multiple [VerifiableClient] and [EvaluationElement] pairs
|
||||
/// Allows for batching of the finalization of multiple [VerifiableClient]
|
||||
/// and [EvaluationElement] pairs
|
||||
pub fn batch_finalize<'a, IC, IM>(
|
||||
clients: &'a IC,
|
||||
messages: &'a IM,
|
||||
@@ -400,8 +397,8 @@ impl<G: Group, H: BlockInput + Digest> NonVerifiableServer<G, H> {
|
||||
Self::new_from_seed(&seed)
|
||||
}
|
||||
|
||||
/// Produces a new instance of a [NonVerifiableServer] using a supplied set of bytes to
|
||||
/// represent the server's private key
|
||||
/// Produces a new instance of a [NonVerifiableServer] using a supplied set
|
||||
/// of bytes to represent the server's private key
|
||||
pub fn new_with_key(private_key_bytes: &[u8]) -> Result<Self, InternalError> {
|
||||
let sk = G::from_scalar_slice(private_key_bytes)?;
|
||||
Ok(Self {
|
||||
@@ -410,8 +407,8 @@ impl<G: Group, H: BlockInput + Digest> NonVerifiableServer<G, H> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Produces a new instance of a [NonVerifiableServer] using a supplied set of bytes which
|
||||
/// are used as a seed to derive the server's private key.
|
||||
/// Produces a new instance of a [NonVerifiableServer] using a supplied set
|
||||
/// of bytes which are used as a seed to derive the server's private key.
|
||||
///
|
||||
/// Corresponds to DeriveKeyPair() function from the VOPRF specification.
|
||||
pub fn new_from_seed(seed: &[u8]) -> Result<Self, InternalError> {
|
||||
@@ -430,8 +427,9 @@ impl<G: Group, H: BlockInput + Digest> NonVerifiableServer<G, H> {
|
||||
self.sk
|
||||
}
|
||||
|
||||
/// Computes the second step for the multiplicative blinding version of DH-OPRF. This
|
||||
/// message is sent from the server (who holds the OPRF key) to the client.
|
||||
/// Computes the second step for the multiplicative blinding version of
|
||||
/// DH-OPRF. This message is sent from the server (who holds the OPRF key)
|
||||
/// to the client.
|
||||
pub fn evaluate(
|
||||
&self,
|
||||
blinded_element: &BlindedElement<G, H>,
|
||||
@@ -465,8 +463,8 @@ impl<G: Group, H: BlockInput + Digest> VerifiableServer<G, H> {
|
||||
Self::new_from_seed(&seed)
|
||||
}
|
||||
|
||||
/// Produces a new instance of a [VerifiableServer] using a supplied set of bytes to
|
||||
/// represent the server's private key
|
||||
/// Produces a new instance of a [VerifiableServer] using a supplied set of
|
||||
/// bytes to represent the server's private key
|
||||
pub fn new_with_key(key: &[u8]) -> Result<Self, InternalError> {
|
||||
let sk = G::from_scalar_slice(key)?;
|
||||
let pk = G::base_point() * &sk;
|
||||
@@ -477,8 +475,8 @@ impl<G: Group, H: BlockInput + Digest> VerifiableServer<G, H> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Produces a new instance of a [VerifiableServer] using a supplied set of bytes which
|
||||
/// are used as a seed to derive the server's private key.
|
||||
/// Produces a new instance of a [VerifiableServer] using a supplied set of
|
||||
/// bytes which are used as a seed to derive the server's private key.
|
||||
///
|
||||
/// Corresponds to DeriveKeyPair() function from the VOPRF specification.
|
||||
pub fn new_from_seed(seed: &[u8]) -> Result<Self, InternalError> {
|
||||
@@ -499,8 +497,9 @@ impl<G: Group, H: BlockInput + Digest> VerifiableServer<G, H> {
|
||||
self.sk
|
||||
}
|
||||
|
||||
/// Computes the second step for the multiplicative blinding version of DH-OPRF. This
|
||||
/// message is sent from the server (who holds the OPRF key) to the client.
|
||||
/// Computes the second step for the multiplicative blinding version of
|
||||
/// DH-OPRF. This message is sent from the server (who holds the OPRF key)
|
||||
/// to the client.
|
||||
pub fn evaluate<R: RngCore + CryptoRng>(
|
||||
&self,
|
||||
rng: &mut R,
|
||||
@@ -518,7 +517,8 @@ impl<G: Group, H: BlockInput + Digest> VerifiableServer<G, H> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Allows for batching of the evaluation of multiple [BlindedElement] messages from a [VerifiableClient]
|
||||
/// Allows for batching of the evaluation of multiple [BlindedElement]
|
||||
/// messages from a [VerifiableClient]
|
||||
pub fn batch_evaluate<'a, R: RngCore + CryptoRng, I>(
|
||||
&self,
|
||||
rng: &mut R,
|
||||
@@ -641,8 +641,8 @@ impl<G: Group, H: BlockInput + Digest> BlindedElement<G, H> {
|
||||
///
|
||||
/// # Caution
|
||||
///
|
||||
/// This should be used with caution, since
|
||||
/// it does not perform any checks on the validity of the value itself!
|
||||
/// This should be used with caution, since it does not perform any checks
|
||||
/// on the validity of the value itself!
|
||||
pub fn from_value_unchecked(value: G) -> Self {
|
||||
Self {
|
||||
value,
|
||||
@@ -671,8 +671,8 @@ impl<G: Group, H: BlockInput + Digest> EvaluationElement<G, H> {
|
||||
///
|
||||
/// # Caution
|
||||
///
|
||||
/// This should be used with caution, since
|
||||
/// it does not perform any checks on the validity of the value itself!
|
||||
/// This should be used with caution, since it does not perform any checks
|
||||
/// on the validity of the value itself!
|
||||
pub fn from_value_unchecked(value: G) -> Self {
|
||||
Self {
|
||||
value,
|
||||
@@ -699,8 +699,9 @@ fn blind<G: Group, H: BlockInput + Digest, R: RngCore + CryptoRng>(
|
||||
Ok((blind, blinded_element))
|
||||
}
|
||||
|
||||
// Inner function for blind that assumes that the blinding factor has already been chosen,
|
||||
// and therefore takes it as input. Does not check if the blinding factor is non-zero.
|
||||
// Inner function for blind that assumes that the blinding factor has already
|
||||
// been chosen, and therefore takes it as input. Does not check if the blinding
|
||||
// factor is non-zero.
|
||||
fn deterministic_blind_unchecked<G: Group, H: BlockInput + Digest>(
|
||||
input: &[u8],
|
||||
blind: &G::Scalar,
|
||||
@@ -918,13 +919,15 @@ fn get_context_string<G: Group>(mode: Mode) -> Result<GenericArray<u8, U11>, Int
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::group::Group;
|
||||
use alloc::vec;
|
||||
|
||||
use generic_array::GenericArray;
|
||||
use rand::rngs::OsRng;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use super::*;
|
||||
use crate::group::Group;
|
||||
|
||||
fn prf<G: Group, H: BlockInput + Digest>(
|
||||
input: &[u8],
|
||||
key: G::Scalar,
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[formatting]
|
||||
reorder_keys = true
|
||||
allowed_blank_lines = 1
|
||||
Reference in New Issue
Block a user