Adding deterministic_blind_unchecked functionality under danger feature (#30)

This commit is contained in:
Kevin Lewi
2021-10-18 13:24:15 -07:00
committed by GitHub
parent 14830f1436
commit 093a15f597
3 changed files with 83 additions and 24 deletions
+3 -14
View File
@@ -87,20 +87,9 @@ impl Group for RistrettoPoint {
fn random_nonzero_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
loop {
let scalar = {
#[cfg(not(test))]
{
let mut scalar_bytes = [0u8; 64];
rng.fill_bytes(&mut scalar_bytes);
Scalar::from_bytes_mod_order_wide(&scalar_bytes)
}
// Tests need an exact conversion from bytes to scalar, sampling only 32 bytes from rng
#[cfg(test)]
{
let mut scalar_bytes = [0u8; 32];
rng.fill_bytes(&mut scalar_bytes);
Scalar::from_bytes_mod_order(scalar_bytes)
}
let mut scalar_bytes = [0u8; 64];
rng.fill_bytes(&mut scalar_bytes);
Scalar::from_bytes_mod_order_wide(&scalar_bytes)
};
if scalar != Scalar::zero() {
+13 -7
View File
@@ -173,9 +173,12 @@ fn test_base_blind<G: Group, H: BlockInput + Digest>(
) -> Result<(), InternalError> {
for parameters in tvs {
for i in 0..parameters.input.len() {
let mut rng = CycleRng::new(parameters.blind[i].to_vec());
let client_result =
NonVerifiableClient::<G, H>::blind(parameters.input[i].clone(), &mut rng)?;
let blind =
G::from_scalar_slice(&GenericArray::clone_from_slice(&parameters.blind[i]))?;
let client_result = NonVerifiableClient::<G, H>::deterministic_blind_unchecked(
parameters.input[i].clone(),
blind,
)?;
assert_eq!(
&parameters.blind[i],
@@ -196,9 +199,12 @@ fn test_verifiable_blind<G: Group, H: BlockInput + Digest>(
) -> Result<(), InternalError> {
for parameters in tvs {
for i in 0..parameters.input.len() {
let mut rng = CycleRng::new(parameters.blind[i].to_vec());
let client_blind_result =
VerifiableClient::<G, H>::blind(parameters.input[i].clone(), &mut rng)?;
let blind =
G::from_scalar_slice(&GenericArray::clone_from_slice(&parameters.blind[i]))?;
let client_blind_result = VerifiableClient::<G, H>::deterministic_blind_unchecked(
parameters.input[i].clone(),
blind,
)?;
assert_eq!(
&parameters.blind[i],
@@ -291,7 +297,7 @@ fn test_verifiable_finalize<G: Group, H: BlockInput + Digest>(
for parameters in tvs {
let mut clients = vec![];
for i in 0..parameters.input.len() {
let client = VerifiableClient::<G, H>::from_data_and_blind(
let client = VerifiableClient::<G, H>::from_data_and_blind_and_element(
&parameters.input[i],
<G as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
&parameters.blind[i],
+67 -3
View File
@@ -165,6 +165,32 @@ impl<G: Group, H: BlockInput + Digest> NonVerifiableClient<G, H> {
})
}
#[cfg(feature = "danger")]
/// 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!
pub fn deterministic_blind_unchecked(
input: Vec<u8>,
blind: <G as Group>::Scalar,
) -> Result<NonVerifiableClientBlindResult<G, H>, InternalError> {
let blinded_element = deterministic_blind_unchecked::<G, H>(&input, &blind, Mode::Base)?;
Ok(NonVerifiableClientBlindResult {
state: Self {
data: input,
blind,
hash: PhantomData,
},
message: BlindedElement {
value: blinded_element,
hash: PhantomData,
},
})
}
/// Computes the third step for the multiplicative blinding version of DH-OPRF, in which
/// the client unblinds the server's message.
pub fn finalize(
@@ -221,6 +247,34 @@ impl<G: Group, H: BlockInput + Digest> VerifiableClient<G, H> {
})
}
#[cfg(feature = "danger")]
/// 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!
pub fn deterministic_blind_unchecked(
input: Vec<u8>,
blind: <G as Group>::Scalar,
) -> Result<VerifiableClientBlindResult<G, H>, InternalError> {
let blinded_element =
deterministic_blind_unchecked::<G, H>(&input, &blind, Mode::Verifiable)?;
Ok(VerifiableClientBlindResult {
state: Self {
data: input,
blind,
blinded_element,
hash: PhantomData,
},
message: BlindedElement {
value: blinded_element,
hash: PhantomData,
},
})
}
/// Computes the third step for the multiplicative blinding version of DH-OPRF, in which
/// the client unblinds the server's message.
pub fn finalize(
@@ -303,7 +357,7 @@ impl<G: Group, H: BlockInput + Digest> VerifiableClient<G, H> {
#[cfg(test)]
/// Only used for test functions
pub fn from_data_and_blind(
pub fn from_data_and_blind_and_element(
data: &[u8],
blind: <G as Group>::Scalar,
blinded_element: G,
@@ -622,10 +676,20 @@ fn blind<G: Group, H: BlockInput + Digest, R: RngCore + CryptoRng>(
) -> Result<(<G as Group>::Scalar, G), InternalError> {
// Choose a random scalar that must be non-zero
let blind = <G as Group>::random_nonzero_scalar(blinding_factor_rng);
let blinded_element = deterministic_blind_unchecked::<G, H>(input, &blind, mode)?;
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.
fn deterministic_blind_unchecked<G: Group, H: BlockInput + Digest>(
input: &[u8],
blind: &<G as Group>::Scalar,
mode: Mode,
) -> Result<G, InternalError> {
let dst = GenericArray::from(*STR_HASH_TO_GROUP).concat(get_context_string::<G>(mode)?);
let hashed_point = <G as Group>::hash_to_curve::<H, _>(input, dst)?;
let blinded_element = hashed_point * &blind;
Ok((blind, blinded_element))
Ok(hashed_point * blind)
}
fn verifiable_unblind<'a, G: 'a + Group, H: 'a + BlockInput + Digest, I>(