Adding deterministic_blind_unchecked functionality under danger feature (#30)
This commit is contained in:
+3
-14
@@ -87,20 +87,9 @@ impl Group for RistrettoPoint {
|
|||||||
fn random_nonzero_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
|
fn random_nonzero_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
|
||||||
loop {
|
loop {
|
||||||
let scalar = {
|
let scalar = {
|
||||||
#[cfg(not(test))]
|
let mut scalar_bytes = [0u8; 64];
|
||||||
{
|
rng.fill_bytes(&mut scalar_bytes);
|
||||||
let mut scalar_bytes = [0u8; 64];
|
Scalar::from_bytes_mod_order_wide(&scalar_bytes)
|
||||||
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)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if scalar != Scalar::zero() {
|
if scalar != Scalar::zero() {
|
||||||
|
|||||||
@@ -173,9 +173,12 @@ fn test_base_blind<G: Group, H: BlockInput + Digest>(
|
|||||||
) -> Result<(), InternalError> {
|
) -> Result<(), InternalError> {
|
||||||
for parameters in tvs {
|
for parameters in tvs {
|
||||||
for i in 0..parameters.input.len() {
|
for i in 0..parameters.input.len() {
|
||||||
let mut rng = CycleRng::new(parameters.blind[i].to_vec());
|
let blind =
|
||||||
let client_result =
|
G::from_scalar_slice(&GenericArray::clone_from_slice(¶meters.blind[i]))?;
|
||||||
NonVerifiableClient::<G, H>::blind(parameters.input[i].clone(), &mut rng)?;
|
let client_result = NonVerifiableClient::<G, H>::deterministic_blind_unchecked(
|
||||||
|
parameters.input[i].clone(),
|
||||||
|
blind,
|
||||||
|
)?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
¶meters.blind[i],
|
¶meters.blind[i],
|
||||||
@@ -196,9 +199,12 @@ fn test_verifiable_blind<G: Group, H: BlockInput + Digest>(
|
|||||||
) -> Result<(), InternalError> {
|
) -> Result<(), InternalError> {
|
||||||
for parameters in tvs {
|
for parameters in tvs {
|
||||||
for i in 0..parameters.input.len() {
|
for i in 0..parameters.input.len() {
|
||||||
let mut rng = CycleRng::new(parameters.blind[i].to_vec());
|
let blind =
|
||||||
let client_blind_result =
|
G::from_scalar_slice(&GenericArray::clone_from_slice(¶meters.blind[i]))?;
|
||||||
VerifiableClient::<G, H>::blind(parameters.input[i].clone(), &mut rng)?;
|
let client_blind_result = VerifiableClient::<G, H>::deterministic_blind_unchecked(
|
||||||
|
parameters.input[i].clone(),
|
||||||
|
blind,
|
||||||
|
)?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
¶meters.blind[i],
|
¶meters.blind[i],
|
||||||
@@ -291,7 +297,7 @@ fn test_verifiable_finalize<G: Group, H: BlockInput + Digest>(
|
|||||||
for parameters in tvs {
|
for parameters in tvs {
|
||||||
let mut clients = vec![];
|
let mut clients = vec![];
|
||||||
for i in 0..parameters.input.len() {
|
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(
|
||||||
¶meters.input[i],
|
¶meters.input[i],
|
||||||
<G as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
|
<G as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
|
||||||
¶meters.blind[i],
|
¶meters.blind[i],
|
||||||
|
|||||||
+67
-3
@@ -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
|
/// Computes the third step for the multiplicative blinding version of DH-OPRF, in which
|
||||||
/// the client unblinds the server's message.
|
/// the client unblinds the server's message.
|
||||||
pub fn finalize(
|
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
|
/// Computes the third step for the multiplicative blinding version of DH-OPRF, in which
|
||||||
/// the client unblinds the server's message.
|
/// the client unblinds the server's message.
|
||||||
pub fn finalize(
|
pub fn finalize(
|
||||||
@@ -303,7 +357,7 @@ impl<G: Group, H: BlockInput + Digest> VerifiableClient<G, H> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
/// Only used for test functions
|
/// Only used for test functions
|
||||||
pub fn from_data_and_blind(
|
pub fn from_data_and_blind_and_element(
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
blind: <G as Group>::Scalar,
|
blind: <G as Group>::Scalar,
|
||||||
blinded_element: G,
|
blinded_element: G,
|
||||||
@@ -622,10 +676,20 @@ fn blind<G: Group, H: BlockInput + Digest, R: RngCore + CryptoRng>(
|
|||||||
) -> Result<(<G as Group>::Scalar, G), InternalError> {
|
) -> Result<(<G as Group>::Scalar, G), InternalError> {
|
||||||
// Choose a random scalar that must be non-zero
|
// Choose a random scalar that must be non-zero
|
||||||
let blind = <G as Group>::random_nonzero_scalar(blinding_factor_rng);
|
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 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 hashed_point = <G as Group>::hash_to_curve::<H, _>(input, dst)?;
|
||||||
let blinded_element = hashed_point * &blind;
|
Ok(hashed_point * blind)
|
||||||
Ok((blind, blinded_element))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verifiable_unblind<'a, G: 'a + Group, H: 'a + BlockInput + Digest, I>(
|
fn verifiable_unblind<'a, G: 'a + Group, H: 'a + BlockInput + Digest, I>(
|
||||||
|
|||||||
Reference in New Issue
Block a user