Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ elliptic-curve = { version = "0.13", features = [
"voprf",
] }
generic-array = "1"
rand_core = { version = "0.6", default-features = false }
rand_core = { version = "0.9", default-features = false }
serde = { version = "1", default-features = false, features = [
"derive",
], optional = true }
sha2 = { version = "0.10", default-features = false, optional = true }
subtle = { version = "2.3", default-features = false }
subtle = { version = "2.6", default-features = false }
zeroize = { version = "1.5", default-features = false }

[dev-dependencies]
Expand All @@ -58,7 +58,7 @@ p521 = { version = "0.13.3", default-features = false, features = [
"voprf",
] }
proptest = "1"
rand = "0.8"
rand = "0.9"
regex = "1"
serde_json = "1"
sha2 = "0.10"
Expand Down
4 changes: 2 additions & 2 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use digest::{Digest, Output, OutputSizeUser};
use generic_array::sequence::Concat;
use generic_array::typenum::{IsLess, Unsigned, U2, U256, U9};
use generic_array::{ArrayLength, GenericArray};
use rand_core::{CryptoRng, RngCore};
use rand_core::{TryCryptoRng, TryRngCore};
use subtle::ConstantTimeEq;

#[cfg(feature = "serde")]
Expand Down Expand Up @@ -128,7 +128,7 @@ pub struct Proof<CS: CipherSuite> {

/// Can only fail with [`Error::Batch`].
#[allow(clippy::many_single_char_names)]
pub(crate) fn generate_proof<CS: CipherSuite, R: RngCore + CryptoRng>(
pub(crate) fn generate_proof<CS: CipherSuite, R: TryRngCore + TryCryptoRng>(
rng: &mut R,
k: <CS::Group as Group>::Scalar,
a: <CS::Group as Group>::Elem,
Expand Down
43 changes: 40 additions & 3 deletions src/group/elliptic_curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// of this source tree. You may select, at your option, one of the above-listed
// licenses.

use core::num::NonZeroU32;
use core::ops::Add;

use digest::core_api::BlockSizeUser;
Expand All @@ -19,7 +20,7 @@ use elliptic_curve::{
};
use generic_array::typenum::{IsLess, IsLessOrEqual, Sum, U256};
use generic_array::{ArrayLength, GenericArray};
use rand_core::{CryptoRng, RngCore};
use rand_core::{TryCryptoRng, TryRngCore};

use super::Group;
use crate::{Error, InternalError, Result};
Expand Down Expand Up @@ -93,8 +94,8 @@ where
.map_err(|_| Error::Deserialization)
}

fn random_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
*SecretKey::<Self>::random(rng).to_nonzero_scalar()
fn random_scalar<R: TryRngCore + TryCryptoRng>(rng: &mut R) -> Self::Scalar {
*SecretKey::<Self>::random(&mut CompatRng(rng)).to_nonzero_scalar()
}

fn invert_scalar(scalar: Self::Scalar) -> Self::Scalar {
Expand Down Expand Up @@ -123,3 +124,39 @@ where
.map_err(|_| Error::Deserialization)
}
}

/// Adapter allowing `rand_core 0.9` RNGs to satisfy the `elliptic_curve` 0.13
/// requirement for `rand_core 0.6` traits.
struct CompatRng<'a, R>(&'a mut R);

impl<'a, R> elliptic_curve::rand_core::RngCore for CompatRng<'a, R>
where
R: TryRngCore,
{
fn next_u32(&mut self) -> u32 {
self.0.try_next_u32().expect("RNG failure")
}

fn next_u64(&mut self) -> u64 {
self.0.try_next_u64().expect("RNG failure")
}

fn fill_bytes(&mut self, dest: &mut [u8]) {
self.0
.try_fill_bytes(dest)
.expect("RNG failure while filling bytes");
}

fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), elliptic_curve::rand_core::Error> {
self.0.try_fill_bytes(dest).map_err(|_| compat_error())?;
Ok(())
}
}

impl<'a, R> elliptic_curve::rand_core::CryptoRng for CompatRng<'a, R> where R: TryCryptoRng {}

fn compat_error() -> elliptic_curve::rand_core::Error {
let code = NonZeroU32::new(elliptic_curve::rand_core::Error::CUSTOM_START)
.expect("CUSTOM_START must be non-zero");
elliptic_curve::rand_core::Error::from(code)
}
4 changes: 2 additions & 2 deletions src/group/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use digest::core_api::BlockSizeUser;
use digest::{FixedOutput, HashMarker};
use generic_array::typenum::{IsLess, IsLessOrEqual, Sum, U256};
use generic_array::{ArrayLength, GenericArray};
use rand_core::{CryptoRng, RngCore};
use rand_core::{TryCryptoRng, TryRngCore};
#[cfg(feature = "ristretto255")]
pub use ristretto::Ristretto255;
use subtle::{Choice, ConstantTimeEq};
Expand Down Expand Up @@ -101,7 +101,7 @@ where
fn deserialize_elem(element_bits: &[u8]) -> Result<Self::Elem>;

/// picks a scalar at random
fn random_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar;
fn random_scalar<R: TryRngCore + TryCryptoRng>(rng: &mut R) -> Self::Scalar;

/// The multiplicative inverse of this scalar
fn invert_scalar(scalar: Self::Scalar) -> Self::Scalar;
Expand Down
7 changes: 4 additions & 3 deletions src/group/ristretto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use digest::{FixedOutput, HashMarker};
use elliptic_curve::hash2curve::{ExpandMsg, ExpandMsgXmd, Expander};
use generic_array::typenum::{IsLess, IsLessOrEqual, U256, U32, U64};
use generic_array::GenericArray;
use rand_core::{CryptoRng, RngCore};
use rand_core::{TryCryptoRng, TryRngCore};
use subtle::ConstantTimeEq;

use super::Group;
Expand Down Expand Up @@ -94,10 +94,11 @@ impl Group for Ristretto255 {
.ok_or(Error::Deserialization)
}

fn random_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
fn random_scalar<R: TryRngCore + TryCryptoRng>(rng: &mut R) -> Self::Scalar {
loop {
let mut scalar_bytes = [0u8; 32];
rng.fill_bytes(&mut scalar_bytes);
rng.try_fill_bytes(&mut scalar_bytes)
.expect("RNG failure while filling scalar bytes");

if let Ok(scalar) = Self::deserialize_scalar(&scalar_bytes) {
break scalar;
Expand Down
11 changes: 6 additions & 5 deletions src/oprf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use derive_where::derive_where;
use digest::{Digest, Output};
use generic_array::typenum::Unsigned;
use generic_array::GenericArray;
use rand_core::{CryptoRng, RngCore};
use rand_core::{TryCryptoRng, TryRngCore};

use crate::common::{
derive_key_internal, deterministic_blind_unchecked, hash_to_group, i2osp_2,
Expand Down Expand Up @@ -73,7 +73,7 @@ impl<CS: CipherSuite> OprfClient<CS> {
///
/// # Errors
/// [`Error::Input`] if the `input` is empty or longer then [`u16::MAX`].
pub fn blind<R: RngCore + CryptoRng>(
pub fn blind<R: TryRngCore + TryCryptoRng>(
input: &[u8],
blinding_factor_rng: &mut R,
) -> Result<OprfClientBlindResult<CS>> {
Expand Down Expand Up @@ -146,9 +146,9 @@ impl<CS: CipherSuite> OprfServer<CS> {
///
/// # Errors
/// [`Error::Protocol`] if the protocol fails and can't be completed.
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self> {
pub fn new<R: TryRngCore + TryCryptoRng>(rng: &mut R) -> Result<Self> {
let mut seed = GenericArray::<_, <CS::Group as Group>::ScalarLen>::default();
rng.fill_bytes(&mut seed);
rng.try_fill_bytes(&mut seed).map_err(|_| Error::Protocol)?;
Self::new_from_seed(&seed, &[])
}

Expand Down Expand Up @@ -268,6 +268,7 @@ mod tests {
use core::ptr;

use rand::rngs::OsRng;
use rand::TryRngCore;

use super::*;
use crate::common::{Dst, STR_HASH_TO_GROUP};
Expand Down Expand Up @@ -304,7 +305,7 @@ mod tests {
fn base_inversion_unsalted<CS: CipherSuite>() {
let mut rng = OsRng;
let mut input = [0u8; 64];
rng.fill_bytes(&mut input);
rng.try_fill_bytes(&mut input).unwrap();
let client_blind_result = OprfClient::<CS>::blind(&input, &mut rng).unwrap();
let client_finalize_result = client_blind_result
.state
Expand Down
14 changes: 7 additions & 7 deletions src/poprf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use derive_where::derive_where;
use digest::{Digest, Output, OutputSizeUser};
use generic_array::typenum::Unsigned;
use generic_array::{ArrayLength, GenericArray};
use rand_core::{CryptoRng, RngCore};
use rand_core::{TryCryptoRng, TryRngCore};

use crate::common::{
derive_keypair, deterministic_blind_unchecked, generate_proof, hash_to_group, i2osp_2,
Expand Down Expand Up @@ -75,7 +75,7 @@ impl<CS: CipherSuite> PoprfClient<CS> {
///
/// # Errors
/// [`Error::Input`] if the `input` is empty or longer than [`u16::MAX`].
pub fn blind<R: RngCore + CryptoRng>(
pub fn blind<R: TryRngCore + TryCryptoRng>(
input: &[u8],
blinding_factor_rng: &mut R,
) -> Result<PoprfClientBlindResult<CS>> {
Expand Down Expand Up @@ -189,9 +189,9 @@ impl<CS: CipherSuite> PoprfServer<CS> {
///
/// # Errors
/// [`Error::Protocol`] if the protocol fails and can't be completed.
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self> {
pub fn new<R: TryRngCore + TryCryptoRng>(rng: &mut R) -> Result<Self> {
let mut seed = GenericArray::<_, <CS::Group as Group>::ScalarLen>::default();
rng.fill_bytes(&mut seed);
rng.try_fill_bytes(&mut seed).map_err(|_| Error::Protocol)?;

Self::new_from_seed(&seed, &[])
}
Expand Down Expand Up @@ -235,7 +235,7 @@ impl<CS: CipherSuite> PoprfServer<CS> {
/// # Errors
/// - [`Error::Info`] if the `info` is longer than `u16::MAX`.
/// - [`Error::Protocol`] if the protocol fails and can't be completed.
pub fn blind_evaluate<R: RngCore + CryptoRng>(
pub fn blind_evaluate<R: TryRngCore + TryCryptoRng>(
&self,
rng: &mut R,
blinded_element: &BlindedElement<CS>,
Expand Down Expand Up @@ -273,7 +273,7 @@ impl<CS: CipherSuite> PoprfServer<CS> {
/// - [`Error::Info`] if the `info` is longer than `u16::MAX`.
/// - [`Error::Protocol`] if the protocol fails and can't be completed.
#[cfg(feature = "alloc")]
pub fn batch_blind_evaluate<'a, R: RngCore + CryptoRng, IE>(
pub fn batch_blind_evaluate<'a, R: TryRngCore + TryCryptoRng, IE>(
&self,
rng: &mut R,
blinded_elements: &'a IE,
Expand Down Expand Up @@ -346,7 +346,7 @@ impl<CS: CipherSuite> PoprfServer<CS> {
pub fn batch_blind_evaluate_finish<
'a,
'b,
R: RngCore + CryptoRng,
R: TryRngCore + TryCryptoRng,
IB: Iterator<Item = &'a BlindedElement<CS>> + ExactSizeIterator,
IE,
>(
Expand Down
8 changes: 1 addition & 7 deletions src/tests/mock_rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use alloc::vec::Vec;
use core::cmp::min;

use rand_core::{CryptoRng, Error, RngCore};
use rand_core::{CryptoRng, RngCore};

/// A simple implementation of `RngCore` for testing purposes.
///
Expand Down Expand Up @@ -54,12 +54,6 @@ impl RngCore for CycleRng {
dest[..len].copy_from_slice(&self.v[..len]);
rotate_left(&mut self.v, len);
}

#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
self.fill_bytes(dest);
Ok(())
}
}

// This is meant for testing only
Expand Down
18 changes: 9 additions & 9 deletions src/voprf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use derive_where::derive_where;
use digest::{Digest, Output};
use generic_array::typenum::Unsigned;
use generic_array::GenericArray;
use rand_core::{CryptoRng, RngCore};
use rand_core::{TryCryptoRng, TryRngCore};

use crate::common::{
derive_keypair, deterministic_blind_unchecked, generate_proof, hash_to_group, i2osp_2,
Expand Down Expand Up @@ -75,7 +75,7 @@ impl<CS: CipherSuite> VoprfClient<CS> {
///
/// # Errors
/// [`Error::Input`] if the `input` is empty or longer then [`u16::MAX`].
pub fn blind<R: RngCore + CryptoRng>(
pub fn blind<R: TryRngCore + TryCryptoRng>(
input: &[u8],
blinding_factor_rng: &mut R,
) -> Result<VoprfClientBlindResult<CS>> {
Expand Down Expand Up @@ -196,9 +196,9 @@ impl<CS: CipherSuite> VoprfServer<CS> {
///
/// # Errors
/// [`Error::Protocol`] if the protocol fails and can't be completed.
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self> {
pub fn new<R: TryRngCore + TryCryptoRng>(rng: &mut R) -> Result<Self> {
let mut seed = GenericArray::<_, <CS::Group as Group>::ScalarLen>::default();
rng.fill_bytes(&mut seed);
rng.try_fill_bytes(&mut seed).map_err(|_| Error::Protocol)?;
// This can't fail as the hash output is type constrained.
Self::new_from_seed(&seed, &[])
}
Expand Down Expand Up @@ -238,7 +238,7 @@ impl<CS: CipherSuite> VoprfServer<CS> {
/// 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 blind_evaluate<R: RngCore + CryptoRng>(
pub fn blind_evaluate<R: TryRngCore + TryCryptoRng>(
&self,
rng: &mut R,
blinded_element: &BlindedElement<CS>,
Expand Down Expand Up @@ -271,7 +271,7 @@ impl<CS: CipherSuite> VoprfServer<CS> {
/// [`Error::Batch`] if the number of `blinded_elements` and
/// `evaluation_elements` don't match or is longer then [`u16::MAX`]
#[cfg(feature = "alloc")]
pub fn batch_blind_evaluate<'a, R: RngCore + CryptoRng, I>(
pub fn batch_blind_evaluate<'a, R: TryRngCore + TryCryptoRng, I>(
&self,
rng: &mut R,
blinded_elements: &'a I,
Expand Down Expand Up @@ -322,7 +322,7 @@ impl<CS: CipherSuite> VoprfServer<CS> {
pub fn batch_blind_evaluate_finish<
'a,
'b,
R: RngCore + CryptoRng,
R: TryRngCore + TryCryptoRng,
IB: Iterator<Item = &'a BlindedElement<CS>> + ExactSizeIterator,
IE,
>(
Expand Down Expand Up @@ -599,7 +599,7 @@ mod tests {
let num_iterations = 10;
for _ in 0..num_iterations {
let mut input = [0u8; 32];
rng.fill_bytes(&mut input);
rng.try_fill_bytes(&mut input).unwrap();
let client_blind_result = VoprfClient::<CS>::blind(&input, &mut rng).unwrap();
inputs.push(input);
client_states.push(client_blind_result.state);
Expand Down Expand Up @@ -643,7 +643,7 @@ mod tests {
let num_iterations = 10;
for _ in 0..num_iterations {
let mut input = [0u8; 32];
rng.fill_bytes(&mut input);
rng.try_fill_bytes(&mut input).unwrap();
let client_blind_result = VoprfClient::<CS>::blind(&input, &mut rng).unwrap();
inputs.push(input);
client_states.push(client_blind_result.state);
Expand Down
Loading