Introduce ristretto255 crate feature (#35)

This commit is contained in:
daxpedda
2021-12-23 01:50:48 -05:00
committed by GitHub
parent 140f9e063d
commit 6669a0c4e6
9 changed files with 194 additions and 154 deletions
+1 -2
View File
@@ -37,8 +37,7 @@ jobs:
backend_feature:
- ristretto255_u64
- ristretto255_u32
# skip doc tests
- p256 --lib
- p256
- ristretto255_u64,p256
frontend_feature:
-
+6 -5
View File
@@ -16,11 +16,12 @@ version = "0.3.0"
danger = []
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"]
ristretto255 = []
ristretto255_fiat_u32 = ["curve25519-dalek/fiat_u32_backend", "ristretto255"]
ristretto255_fiat_u64 = ["curve25519-dalek/fiat_u64_backend", "ristretto255"]
ristretto255_simd = ["curve25519-dalek/simd_backend", "ristretto255"]
ristretto255_u32 = ["curve25519-dalek/u32_backend", "ristretto255"]
ristretto255_u64 = ["curve25519-dalek/u64_backend", "ristretto255"]
std = []
[dependencies]
+3 -11
View File
@@ -7,20 +7,12 @@
//! Defines the Group trait to specify the underlying prime order group
#[cfg(any(
feature = "ristretto255_u64",
feature = "ristretto255_u32",
feature = "ristretto255_fiat_u64",
feature = "ristretto255_fiat_u32",
feature = "ristretto255_simd",
feature = "p256",
))]
#[cfg(any(feature = "ristretto255", feature = "p256",))]
mod expand;
#[cfg(feature = "p256")]
mod p256;
cfg_ristretto! {
mod ristretto;
}
#[cfg(feature = "ristretto255")]
mod ristretto;
use core::ops::{Add, Mul, Sub};
+98 -102
View File
@@ -5,127 +5,123 @@
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
// of this source tree.
use super::Group;
use crate::errors::InternalError;
use core::convert::TryInto;
use core::ops::Add;
use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_POINT,
ristretto::{CompressedRistretto, RistrettoPoint},
scalar::Scalar,
traits::Identity,
};
use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::Identity;
use digest::{BlockInput, Digest};
use generic_array::{
typenum::{U1, U32, U64},
ArrayLength, GenericArray,
};
use generic_array::typenum::{U1, U32, U64};
use generic_array::{ArrayLength, GenericArray};
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_ristretto! {
/// The implementation of such a subgroup for Ristretto
impl Group for RistrettoPoint {
const SUITE_ID: usize = 0x0001;
use super::Group;
use crate::errors::InternalError;
// Implements the `hash_to_ristretto255()` function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt
fn hash_to_curve<H: BlockInput + Digest, D: ArrayLength<u8> + Add<U1>>(
msg: &[u8],
dst: GenericArray<u8, D>,
) -> Result<Self, InternalError>
where
<D as Add<U1>>::Output: ArrayLength<u8>,
{
let uniform_bytes = super::expand::expand_message_xmd::<H, U64, _, _>(Some(msg), dst)?;
// `cfg` here is only needed because of a bug in Rust's crate feature documentation. See: https://github.com/rust-lang/rust/issues/83428
#[cfg(feature = "ristretto255")]
/// The implementation of such a subgroup for Ristretto
impl Group for RistrettoPoint {
const SUITE_ID: usize = 0x0001;
Ok(RistrettoPoint::from_uniform_bytes(
uniform_bytes
.as_slice()
.try_into()
.map_err(|_| InternalError::HashToCurveError)?,
))
}
// Implements the `hash_to_ristretto255()` function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt
fn hash_to_curve<H: BlockInput + Digest, D: ArrayLength<u8> + Add<U1>>(
msg: &[u8],
dst: GenericArray<u8, D>,
) -> Result<Self, InternalError>
where
<D as Add<U1>>::Output: ArrayLength<u8>,
{
let uniform_bytes = super::expand::expand_message_xmd::<H, U64, _, _>(Some(msg), dst)?;
// Implements the `HashToScalar()` function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.1
fn hash_to_scalar<
'a,
H: BlockInput + Digest,
D: ArrayLength<u8> + Add<U1>,
I: IntoIterator<Item = &'a [u8]>,
>(
input: I,
dst: GenericArray<u8, D>,
) -> Result<Self::Scalar, InternalError>
where
<D as Add<U1>>::Output: ArrayLength<u8>,
{
let uniform_bytes = super::expand::expand_message_xmd::<H, U64, _, _>(input, dst)?;
Ok(RistrettoPoint::from_uniform_bytes(
uniform_bytes
.as_slice()
.try_into()
.map_err(|_| InternalError::HashToCurveError)?,
))
}
Ok(Scalar::from_bytes_mod_order_wide(
uniform_bytes
.as_slice()
.try_into()
.map_err(|_| InternalError::HashToCurveError)?,
))
}
// Implements the `HashToScalar()` function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.1
fn hash_to_scalar<
'a,
H: BlockInput + Digest,
D: ArrayLength<u8> + Add<U1>,
I: IntoIterator<Item = &'a [u8]>,
>(
input: I,
dst: GenericArray<u8, D>,
) -> Result<Self::Scalar, InternalError>
where
<D as Add<U1>>::Output: ArrayLength<u8>,
{
let uniform_bytes = super::expand::expand_message_xmd::<H, U64, _, _>(input, dst)?;
type Scalar = Scalar;
type ScalarLen = U32;
fn from_scalar_slice_unchecked(
scalar_bits: &GenericArray<u8, Self::ScalarLen>,
) -> Result<Self::Scalar, InternalError> {
Ok(Scalar::from_bytes_mod_order(*scalar_bits.as_ref()))
}
Ok(Scalar::from_bytes_mod_order_wide(
uniform_bytes
.as_slice()
.try_into()
.map_err(|_| InternalError::HashToCurveError)?,
))
}
fn random_nonzero_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
loop {
let scalar = {
let mut scalar_bytes = [0u8; 64];
rng.fill_bytes(&mut scalar_bytes);
Scalar::from_bytes_mod_order_wide(&scalar_bytes)
};
type Scalar = Scalar;
type ScalarLen = U32;
fn from_scalar_slice_unchecked(
scalar_bits: &GenericArray<u8, Self::ScalarLen>,
) -> Result<Self::Scalar, InternalError> {
Ok(Scalar::from_bytes_mod_order(*scalar_bits.as_ref()))
}
if scalar != Scalar::zero() {
break scalar;
}
fn random_nonzero_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
loop {
let scalar = {
let mut scalar_bytes = [0u8; 64];
rng.fill_bytes(&mut scalar_bytes);
Scalar::from_bytes_mod_order_wide(&scalar_bytes)
};
if scalar != Scalar::zero() {
break scalar;
}
}
}
fn scalar_as_bytes(scalar: Self::Scalar) -> GenericArray<u8, Self::ScalarLen> {
scalar.to_bytes().into()
}
fn scalar_as_bytes(scalar: Self::Scalar) -> GenericArray<u8, Self::ScalarLen> {
scalar.to_bytes().into()
}
fn scalar_invert(scalar: &Self::Scalar) -> Self::Scalar {
scalar.invert()
}
fn scalar_invert(scalar: &Self::Scalar) -> Self::Scalar {
scalar.invert()
}
// The byte length necessary to represent group elements
type ElemLen = U32;
fn from_element_slice_unchecked(
element_bits: &GenericArray<u8, Self::ElemLen>,
) -> Result<Self, InternalError> {
CompressedRistretto::from_slice(element_bits)
.decompress()
.ok_or(InternalError::PointError)
}
// serialization of a group element
fn to_arr(&self) -> GenericArray<u8, Self::ElemLen> {
self.compress().to_bytes().into()
}
// The byte length necessary to represent group elements
type ElemLen = U32;
fn from_element_slice_unchecked(
element_bits: &GenericArray<u8, Self::ElemLen>,
) -> Result<Self, InternalError> {
CompressedRistretto::from_slice(element_bits)
.decompress()
.ok_or(InternalError::PointError)
}
// serialization of a group element
fn to_arr(&self) -> GenericArray<u8, Self::ElemLen> {
self.compress().to_bytes().into()
}
fn base_point() -> Self {
RISTRETTO_BASEPOINT_POINT
}
fn base_point() -> Self {
RISTRETTO_BASEPOINT_POINT
}
fn identity() -> Self {
<Self as Identity>::identity()
}
fn identity() -> Self {
<Self as Identity>::identity()
}
fn scalar_zero() -> Self::Scalar {
Self::Scalar::zero()
}
fn scalar_zero() -> Self::Scalar {
Self::Scalar::zero()
}
}
+3 -2
View File
@@ -15,12 +15,13 @@ use crate::group::Group;
#[test]
fn test_group_properties() -> Result<(), InternalError> {
cfg_ristretto! { {
#[cfg(feature = "ristretto255")]
{
use curve25519_dalek::ristretto::RistrettoPoint;
test_identity_element_error::<RistrettoPoint>()?;
test_zero_scalar_error::<RistrettoPoint>()?;
} }
}
#[cfg(feature = "p256")]
{
+70 -2
View File
@@ -23,7 +23,7 @@
//!
//! We will use the following choices in this example:
//!
//! ```
//! ```ignore
//! type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! type Hash = sha2::Sha512;
//! ```
@@ -51,8 +51,14 @@
//! must be persisted on the server and used for online client evaluations.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! use rand::rngs::OsRng;
//! use rand::RngCore;
//! use voprf::NonVerifiableServer;
@@ -71,8 +77,14 @@
//! step of the VOPRF protocol.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! use rand::rngs::OsRng;
//! use rand::RngCore;
//! use voprf::NonVerifiableClient;
@@ -92,8 +104,14 @@
//! [EvaluationElement] to be sent to the client.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! # use voprf::NonVerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -118,8 +136,14 @@
//! [NonVerifiableClient::finalize] to produce an output for the protocol.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! # use voprf::NonVerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -163,8 +187,14 @@
//! must be persisted on the server and used for online client evaluations.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! use rand::rngs::OsRng;
//! use rand::RngCore;
//! use voprf::VerifiableServer;
@@ -190,8 +220,14 @@
//! of the VOPRF protocol.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! use rand::rngs::OsRng;
//! use rand::RngCore;
//! use voprf::VerifiableClient;
@@ -211,8 +247,14 @@
//! a proof.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -238,8 +280,14 @@
//! output for the protocol.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -288,8 +336,14 @@
//! messages:
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -311,8 +365,14 @@
//! proof:
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -342,8 +402,14 @@
//! outputs if the proof verifies correctly.
//!
//! ```
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! # use voprf::VerifiableClient;
//! # use rand::{rngs::OsRng, RngCore};
//! #
@@ -411,7 +477,9 @@
//! 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`.
//! `ristretto255_fiat_u32`. Any `ristretto255_*` backend feature will enable
//! the `ristretto255` feature, which can be used too, but keep in mind that
//! `curve25519-dalek` will fail to compile without a selected backend.
//!
//! - 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
+3 -2
View File
@@ -87,7 +87,8 @@ fn test_vectors() -> Result<(), InternalError> {
let rfc = json::parse(rfc_to_json(super::voprf_vectors::VECTORS).as_str())
.expect("Could not parse json");
cfg_ristretto! { {
#[cfg(feature = "ristretto255")]
{
use curve25519_dalek::ristretto::RistrettoPoint;
use sha2::Sha512;
@@ -112,7 +113,7 @@ fn test_vectors() -> Result<(), InternalError> {
test_verifiable_blind::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_evaluate::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_finalize::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
} }
}
#[cfg(feature = "p256")]
{
+7 -26
View File
@@ -121,29 +121,6 @@ macro_rules! chain {
};
}
macro_rules! cfg_ristretto {
($tree:tt) => {
#[cfg(any(
feature = "ristretto255_u64",
feature = "ristretto255_u32",
feature = "ristretto255_fiat_u64",
feature = "ristretto255_fiat_u32",
feature = "ristretto255_simd",
))]
$tree
};
($($item:item)+) => {
$(#[cfg(any(
feature = "ristretto255_u64",
feature = "ristretto255_u32",
feature = "ristretto255_fiat_u64",
feature = "ristretto255_fiat_u32",
feature = "ristretto255_simd",
))]
$item)+
};
}
#[cfg(test)]
mod unit_tests {
use generic_array::typenum::{U1, U2};
@@ -172,9 +149,13 @@ mod unit_tests {
macro_rules! test_deserialize {
($item:ident, $bytes:ident) => {
cfg_ristretto! { {
let _ = $item::<curve25519_dalek::ristretto::RistrettoPoint, sha2::Sha512>::deserialize(&$bytes[..]);
} }
#[cfg(feature = "ristretto255")]
{
let _ =
$item::<curve25519_dalek::ristretto::RistrettoPoint, sha2::Sha512>::deserialize(
&$bytes[..],
);
}
#[cfg(feature = "p256")]
{
let _ = $item::<p256_::ProjectivePoint, sha2::Sha256>::deserialize(&$bytes[..]);
+3 -2
View File
@@ -1196,7 +1196,8 @@ mod tests {
#[test]
fn test_functionality() -> Result<(), InternalError> {
cfg_ristretto! { {
#[cfg(feature = "ristretto255")]
{
use curve25519_dalek::ristretto::RistrettoPoint;
use sha2::Sha512;
@@ -1211,7 +1212,7 @@ mod tests {
zeroize_base_server::<RistrettoPoint, Sha512>();
zeroize_verifiable_client::<RistrettoPoint, Sha512>();
zeroize_verifiable_server::<RistrettoPoint, Sha512>();
} }
}
#[cfg(feature = "p256")]
{