diff --git a/Cargo.toml b/Cargo.toml index 4e240ba..3a10e4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ std = ["alloc"] [dependencies] curve25519-dalek = { version = "3", default-features = false, optional = true } derive-where = { version = "1.0.0-rc.1", features = ["zeroize"] } -digest = "0.9" +digest = "0.10" displaydoc = { version = "0.2", default-features = false } generic-array = "0.14" num-bigint = { version = "0.4", default-features = false, optional = true } @@ -60,7 +60,7 @@ json = "0.12" proptest = "1" rand = "0.8" regex = "1" -sha2 = "0.9" +sha2 = "0.10" [package.metadata.docs.rs] features = ["danger", "p256", "std"] diff --git a/src/group/expand.rs b/src/group/expand.rs index ce7c4f0..a5dac54 100644 --- a/src/group/expand.rs +++ b/src/group/expand.rs @@ -7,7 +7,8 @@ use core::ops::Add; -use digest::{BlockInput, Digest}; +use digest::core_api::BlockSizeUser; +use digest::{Digest, FixedOutputReset}; use generic_array::sequence::Concat; use generic_array::typenum::{Unsigned, U1, U2}; use generic_array::{ArrayLength, GenericArray}; @@ -29,7 +30,7 @@ fn xor>(x: GenericArray, y: GenericArray) -> Ge /// pub fn expand_message_xmd< 'a, - H: BlockInput + Digest, + H: BlockSizeUser + Digest + FixedOutputReset, L: ArrayLength, M: IntoIterator, D: ArrayLength + Add, @@ -52,13 +53,13 @@ where let mut h = H::new(); // msg_prime = Z_pad || msg || l_i_b_str || I2OSP(0, 1) || DST_prime - h.update(z_pad); + Digest::update(&mut h, z_pad); for bytes in msg { - h.update(bytes) + Digest::update(&mut h, bytes) } - h.update(l_i_b_str); - h.update(i2osp::(0)?); - h.update(&dst_prime); + Digest::update(&mut h, l_i_b_str); + Digest::update(&mut h, i2osp::(0)?); + Digest::update(&mut h, &dst_prime); // b[0] let b_0 = h.finalize_reset(); @@ -67,9 +68,9 @@ where let mut uniform_bytes = GenericArray::default(); for (i, chunk) in (1..(ell + 1)).zip(uniform_bytes.chunks_mut(digest_len)) { - h.update(xor(b_0.clone(), b_i.clone())); - h.update(i2osp::(i)?); - h.update(&dst_prime); + Digest::update(&mut h, xor(b_0.clone(), b_i.clone())); + Digest::update(&mut h, i2osp::(i)?); + Digest::update(&mut h, &dst_prime); b_i = h.finalize_reset(); chunk.copy_from_slice(&b_i[..digest_len.min(chunk.len())]); } diff --git a/src/group/mod.rs b/src/group/mod.rs index 890bcaa..5f9f8e8 100644 --- a/src/group/mod.rs +++ b/src/group/mod.rs @@ -16,7 +16,8 @@ mod ristretto; use core::ops::{Add, Mul, Sub}; -use digest::{BlockInput, Digest}; +use digest::core_api::BlockSizeUser; +use digest::{Digest, FixedOutputReset}; use generic_array::typenum::U1; use generic_array::{ArrayLength, GenericArray}; use rand_core::{CryptoRng, RngCore}; @@ -39,7 +40,7 @@ pub trait Group: const SUITE_ID: usize; /// transforms a password and domain separation tag (DST) into a curve point - fn hash_to_curve + Add>( + fn hash_to_curve + Add>( msg: &[u8], dst: GenericArray, ) -> Result @@ -49,7 +50,7 @@ pub trait Group: /// Hashes a slice of pseudo-random bytes to a scalar fn hash_to_scalar< 'a, - H: BlockInput + Digest, + H: BlockSizeUser + Digest + FixedOutputReset, D: ArrayLength + Add, I: IntoIterator, >( diff --git a/src/group/p256.rs b/src/group/p256.rs index 86ec5bd..44edb94 100644 --- a/src/group/p256.rs +++ b/src/group/p256.rs @@ -16,7 +16,8 @@ use core::ops::{Add, Div, Mul, Neg}; use core::str::FromStr; -use digest::{BlockInput, Digest}; +use digest::core_api::BlockSizeUser; +use digest::{Digest, FixedOutputReset}; use generic_array::typenum::{Unsigned, U1, U2, U32, U33, U48}; use generic_array::{ArrayLength, GenericArray}; use num_bigint::{BigInt, Sign}; @@ -44,7 +45,7 @@ impl Group for ProjectivePoint { // Implements the `hash_to_curve()` function from // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3 - fn hash_to_curve + Add>( + fn hash_to_curve + Add>( msg: &[u8], dst: GenericArray, ) -> Result @@ -100,7 +101,7 @@ impl Group for ProjectivePoint { // Implements the `HashToScalar()` function fn hash_to_scalar< 'a, - H: BlockInput + Digest, + H: BlockSizeUser + Digest + FixedOutputReset, D: ArrayLength + Add, I: IntoIterator, >( diff --git a/src/group/ristretto.rs b/src/group/ristretto.rs index a58902a..ddcdfce 100644 --- a/src/group/ristretto.rs +++ b/src/group/ristretto.rs @@ -12,7 +12,8 @@ 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 digest::core_api::BlockSizeUser; +use digest::{Digest, FixedOutputReset}; use generic_array::typenum::{U1, U32, U64}; use generic_array::{ArrayLength, GenericArray}; use rand_core::{CryptoRng, RngCore}; @@ -28,7 +29,7 @@ impl Group for RistrettoPoint { // 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 + Add>( + fn hash_to_curve + Add>( msg: &[u8], dst: GenericArray, ) -> Result @@ -49,7 +50,7 @@ impl Group for RistrettoPoint { // https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.1 fn hash_to_scalar< 'a, - H: BlockInput + Digest, + H: BlockSizeUser + Digest + FixedOutputReset, D: ArrayLength + Add, I: IntoIterator, >( diff --git a/src/serialization.rs b/src/serialization.rs index ef3b10d..60cc26e 100644 --- a/src/serialization.rs +++ b/src/serialization.rs @@ -11,7 +11,8 @@ use core::marker::PhantomData; use core::ops::Add; -use digest::{BlockInput, Digest}; +use digest::core_api::BlockSizeUser; +use digest::{Digest, FixedOutputReset}; use generic_array::sequence::Concat; use generic_array::typenum::Sum; use generic_array::{ArrayLength, GenericArray}; @@ -29,7 +30,7 @@ use crate::voprf::{ // ==================================================== // ////////////////////////////////////////////////////////// -impl NonVerifiableClient { +impl NonVerifiableClient { /// Serialization into bytes pub fn serialize(&self) -> GenericArray { G::scalar_as_bytes(self.blind) @@ -48,7 +49,7 @@ impl NonVerifiableClient { } } -impl VerifiableClient { +impl VerifiableClient { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where @@ -73,7 +74,7 @@ impl VerifiableClient { } } -impl NonVerifiableServer { +impl NonVerifiableServer { /// Serialization into bytes pub fn serialize(&self) -> GenericArray { G::scalar_as_bytes(self.sk) @@ -92,7 +93,7 @@ impl NonVerifiableServer { } } -impl VerifiableServer { +impl VerifiableServer { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where @@ -117,7 +118,7 @@ impl VerifiableServer { } } -impl Proof { +impl Proof { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where @@ -142,7 +143,7 @@ impl Proof { } } -impl BlindedElement { +impl BlindedElement { /// Serialization into bytes pub fn serialize(&self) -> GenericArray { self.value.to_arr() @@ -161,7 +162,7 @@ impl BlindedElement { } } -impl EvaluationElement { +impl EvaluationElement { /// Serialization into bytes pub fn serialize(&self) -> GenericArray { self.value.to_arr() diff --git a/src/tests/voprf_test_vectors.rs b/src/tests/voprf_test_vectors.rs index 5b0487c..d5a7fc8 100644 --- a/src/tests/voprf_test_vectors.rs +++ b/src/tests/voprf_test_vectors.rs @@ -9,7 +9,8 @@ use alloc::string::{String, ToString}; use alloc::vec; use alloc::vec::Vec; -use digest::{BlockInput, Digest}; +use digest::core_api::BlockSizeUser; +use digest::{Digest, FixedOutputReset}; use generic_array::GenericArray; use json::JsonValue; #[cfg(feature = "alloc")] @@ -152,7 +153,7 @@ fn test_vectors() -> Result<(), InternalError> { Ok(()) } -fn test_base_seed_to_key( +fn test_base_seed_to_key( tvs: &[VOPRFTestVectorParameters], ) -> Result<(), InternalError> { for parameters in tvs { @@ -166,7 +167,7 @@ fn test_base_seed_to_key( Ok(()) } -fn test_verifiable_seed_to_key( +fn test_verifiable_seed_to_key( tvs: &[VOPRFTestVectorParameters], ) -> Result<(), InternalError> { for parameters in tvs { @@ -182,7 +183,7 @@ fn test_verifiable_seed_to_key( } // Tests input -> blind, blinded_element -fn test_base_blind( +fn test_base_blind( tvs: &[VOPRFTestVectorParameters], ) -> Result<(), InternalError> { for parameters in tvs { @@ -208,7 +209,7 @@ fn test_base_blind( } // Tests input -> blind, blinded_element -fn test_verifiable_blind( +fn test_verifiable_blind( tvs: &[VOPRFTestVectorParameters], ) -> Result<(), InternalError> { for parameters in tvs { @@ -234,7 +235,7 @@ fn test_verifiable_blind( } // Tests sksm, blinded_element -> evaluation_element -fn test_base_evaluate( +fn test_base_evaluate( tvs: &[VOPRFTestVectorParameters], ) -> Result<(), InternalError> { for parameters in tvs { @@ -255,7 +256,7 @@ fn test_base_evaluate( } #[cfg(feature = "alloc")] -fn test_verifiable_evaluate( +fn test_verifiable_evaluate( tvs: &[VOPRFTestVectorParameters], ) -> Result<(), InternalError> where @@ -290,7 +291,7 @@ where } // Tests input, blind, evaluation_element -> output -fn test_base_finalize( +fn test_base_finalize( tvs: &[VOPRFTestVectorParameters], ) -> Result<(), InternalError> { for parameters in tvs { @@ -311,7 +312,7 @@ fn test_base_finalize( Ok(()) } -fn test_verifiable_finalize( +fn test_verifiable_finalize( tvs: &[VOPRFTestVectorParameters], ) -> Result<(), InternalError> { for parameters in tvs { diff --git a/src/voprf.rs b/src/voprf.rs index dd0a9b7..4d72e90 100644 --- a/src/voprf.rs +++ b/src/voprf.rs @@ -14,7 +14,8 @@ use core::iter::{self, Map, Repeat, Zip}; use core::marker::PhantomData; use derive_where::DeriveWhere; -use digest::{BlockInput, Digest}; +use digest::core_api::BlockSizeUser; +use digest::{Digest, FixedOutputReset}; use generic_array::sequence::Concat; use generic_array::typenum::{U1, U11, U2, U20}; use generic_array::GenericArray; @@ -64,7 +65,7 @@ enum Mode { serialize = "G::Scalar: serde::Serialize" )) )] -pub struct NonVerifiableClient { +pub struct NonVerifiableClient { pub(crate) blind: G::Scalar, #[derive_where(skip(Zeroize))] pub(crate) hash: PhantomData, @@ -83,7 +84,7 @@ pub struct NonVerifiableClient { serialize = "G::Scalar: serde::Serialize, G: serde::Serialize" )) )] -pub struct VerifiableClient { +pub struct VerifiableClient { pub(crate) blind: G::Scalar, pub(crate) blinded_element: G, #[derive_where(skip(Zeroize))] @@ -103,7 +104,7 @@ pub struct VerifiableClient { serialize = "G::Scalar: serde::Serialize" )) )] -pub struct NonVerifiableServer { +pub struct NonVerifiableServer { pub(crate) sk: G::Scalar, #[derive_where(skip(Zeroize))] pub(crate) hash: PhantomData, @@ -122,7 +123,7 @@ pub struct NonVerifiableServer { serialize = "G::Scalar: serde::Serialize, G: serde::Serialize" )) )] -pub struct VerifiableServer { +pub struct VerifiableServer { pub(crate) sk: G::Scalar, pub(crate) pk: G, #[derive_where(skip(Zeroize))] @@ -142,7 +143,7 @@ pub struct VerifiableServer { serialize = "G::Scalar: serde::Serialize" )) )] -pub struct Proof { +pub struct Proof { pub(crate) c_scalar: G::Scalar, pub(crate) s_scalar: G::Scalar, #[derive_where(skip(Zeroize))] @@ -162,7 +163,7 @@ pub struct Proof { serialize = "G: serde::Serialize" )) )] -pub struct BlindedElement { +pub struct BlindedElement { pub(crate) value: G, #[derive_where(skip(Zeroize))] pub(crate) hash: PhantomData, @@ -181,7 +182,7 @@ pub struct BlindedElement { serialize = "G: serde::Serialize" )) )] -pub struct EvaluationElement { +pub struct EvaluationElement { pub(crate) value: G, #[derive_where(skip(Zeroize))] pub(crate) hash: PhantomData, @@ -192,7 +193,7 @@ pub struct EvaluationElement { // =================== // ///////////////////////// -impl NonVerifiableClient { +impl NonVerifiableClient { /// Computes the first step for the multiplicative blinding version of /// DH-OPRF. pub fn blind( @@ -271,7 +272,7 @@ impl NonVerifiableClient { } } -impl VerifiableClient { +impl VerifiableClient { /// Computes the first step for the multiplicative blinding version of /// DH-OPRF. pub fn blind( @@ -394,7 +395,7 @@ impl VerifiableClient { } } -impl NonVerifiableServer { +impl NonVerifiableServer { /// Produces a new instance of a [NonVerifiableServer] using a supplied RNG pub fn new(rng: &mut R) -> Result { let mut seed = GenericArray::<_, H::OutputSize>::default(); @@ -460,7 +461,7 @@ impl NonVerifiableServer { } } -impl VerifiableServer { +impl VerifiableServer { /// Produces a new instance of a [VerifiableServer] using a supplied RNG pub fn new(rng: &mut R) -> Result { let mut seed = GenericArray::<_, H::OutputSize>::default(); @@ -626,7 +627,7 @@ impl VerifiableServer { ///////////////////////// /// Contains the fields that are returned by a non-verifiable client blind -pub struct NonVerifiableClientBlindResult { +pub struct NonVerifiableClientBlindResult { /// The state to be persisted on the client pub state: NonVerifiableClient, /// The message to send to the server @@ -634,13 +635,14 @@ pub struct NonVerifiableClientBlindResult { } /// Contains the fields that are returned by a non-verifiable server evaluate -pub struct NonVerifiableServerEvaluateResult { +pub struct NonVerifiableServerEvaluateResult +{ /// The message to send to the client pub message: EvaluationElement, } /// Contains the fields that are returned by a verifiable client blind -pub struct VerifiableClientBlindResult { +pub struct VerifiableClientBlindResult { /// The state to be persisted on the client pub state: VerifiableClient, /// The message to send to the server @@ -656,7 +658,7 @@ pub type VerifiableClientBatchFinalizeResult<'a, G, H, I, II, IC, IM> = Finalize >; /// Contains the fields that are returned by a verifiable server evaluate -pub struct VerifiableServerEvaluateResult { +pub struct VerifiableServerEvaluateResult { /// The message to send to the client pub message: EvaluationElement, /// The proof for the client to verify @@ -665,7 +667,10 @@ pub struct VerifiableServerEvaluateResult { /// Contains the fields that are returned by a verifiable server batch evaluate #[cfg(feature = "alloc")] -pub struct VerifiableServerBatchEvaluateResult { +pub struct VerifiableServerBatchEvaluateResult< + G: Group, + H: BlockSizeUser + Digest + FixedOutputReset, +> { /// The messages to send to the client pub messages: alloc::vec::Vec>, /// The proof for the client to verify @@ -677,7 +682,7 @@ pub struct VerifiableServerBatchEvaluateResult // ========================================= // /////////////////////////////////////////////// -impl BlindedElement { +impl BlindedElement { /// Only used to easier validate allocation fn copy(&self) -> Self { Self { @@ -707,7 +712,7 @@ impl BlindedElement { } } -impl EvaluationElement { +impl EvaluationElement { /// Only used to easier validate allocation fn copy(&self) -> Self { Self { @@ -738,7 +743,7 @@ impl EvaluationElement { } // Inner function for blind. Returns the blind scalar and the blinded element -fn blind( +fn blind( input: &[u8], blinding_factor_rng: &mut R, mode: Mode, @@ -752,7 +757,7 @@ fn blind( // 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( +fn deterministic_blind_unchecked( input: &[u8], blind: &G::Scalar, mode: Mode, @@ -771,7 +776,13 @@ type VerifiableUnblindResult<'a, G: Group, H, IC, IM> = Map< fn((G::Scalar, &EvaluationElement)) -> G, >; -fn verifiable_unblind<'a, G: 'a + Group, H: 'a + BlockInput + Digest, IC, IM>( +fn verifiable_unblind< + 'a, + G: 'a + Group, + H: 'a + BlockSizeUser + Digest + FixedOutputReset, + IC, + IM, +>( clients: &'a IC, messages: &'a IM, pk: G, @@ -816,7 +827,11 @@ where } #[allow(clippy::many_single_char_names)] -fn generate_proof( +fn generate_proof< + G: Group, + H: BlockSizeUser + Digest + FixedOutputReset, + R: RngCore + CryptoRng, +>( rng: &mut R, k: G::Scalar, a: G, @@ -856,7 +871,7 @@ fn generate_proof( } #[allow(clippy::many_single_char_names)] -fn verify_proof( +fn verify_proof( a: G, b: G, cs: impl Iterator> + ExactSizeIterator, @@ -900,7 +915,7 @@ type FinalizeAfterUnblindResult<'a, G, H: Digest, I, IE> = Map< fn finalize_after_unblind< 'a, G: Group, - H: BlockInput + Digest, + H: BlockSizeUser + Digest + FixedOutputReset, I: AsRef<[u8]>, IE: 'a + Iterator, >( @@ -924,12 +939,12 @@ fn finalize_after_unblind< ); Ok(hash_input - .fold(H::new(), |h, bytes| h.chain(bytes)) + .fold(H::new(), |h, bytes| h.chain_update(bytes)) .finalize()) })) } -fn compute_composites( +fn compute_composites( k_option: Option, b: G, c_slice: impl Iterator> + ExactSizeIterator, @@ -949,7 +964,7 @@ fn compute_composites( serialize_owned::(seed_dst)?, ); let seed = h1_input - .fold(H::new(), |h, bytes| h.chain(bytes)) + .fold(H::new(), |h, bytes| h.chain_update(bytes)) .finalize(); let mut m = G::identity(); @@ -1008,7 +1023,7 @@ mod tests { use super::*; use crate::group::Group; - fn prf( + fn prf( input: &[u8], key: G::Scalar, info: &[u8], @@ -1037,7 +1052,7 @@ mod tests { .unwrap() } - fn base_retrieval() { + fn base_retrieval() { let input = b"input"; let info = b"info"; let mut rng = OsRng; @@ -1054,7 +1069,7 @@ mod tests { assert_eq!(client_finalize_result, res2); } - fn verifiable_retrieval() { + fn verifiable_retrieval() { let input = b"input"; let info = b"info"; let mut rng = OsRng; @@ -1078,7 +1093,7 @@ mod tests { } #[cfg(feature = "alloc")] - fn verifiable_bad_public_key() { + fn verifiable_bad_public_key() { let input = b"input"; let info = b"info"; let mut rng = OsRng; @@ -1102,7 +1117,7 @@ mod tests { } #[cfg(feature = "alloc")] - fn verifiable_batch_retrieval() { + fn verifiable_batch_retrieval() { let info = b"info"; let mut rng = OsRng; let mut inputs = vec![]; @@ -1141,7 +1156,7 @@ mod tests { } #[cfg(feature = "alloc")] - fn verifiable_batch_bad_public_key() { + fn verifiable_batch_bad_public_key() { let info = b"info"; let mut rng = OsRng; let mut inputs = vec![]; @@ -1175,7 +1190,7 @@ mod tests { assert!(client_finalize_result.is_err()); } - fn base_inversion_unsalted() { + fn base_inversion_unsalted() { let mut rng = OsRng; let mut input = [0u8; 64]; rng.fill_bytes(&mut input); @@ -1209,7 +1224,7 @@ mod tests { assert_eq!(client_finalize_result, res2); } - fn zeroize_base_client() { + fn zeroize_base_client() { let input = b"input"; let mut rng = OsRng; let client_blind_result = NonVerifiableClient::::blind(input, &mut rng).unwrap(); @@ -1223,7 +1238,7 @@ mod tests { assert!(message.serialize().iter().all(|&x| x == 0)); } - fn zeroize_verifiable_client() + fn zeroize_verifiable_client() where G::ScalarLen: Add, Sum: ArrayLength, @@ -1241,7 +1256,7 @@ mod tests { assert!(message.serialize().iter().all(|&x| x == 0)); } - fn zeroize_base_server() { + fn zeroize_base_server() { let input = b"input"; let info = b"info"; let mut rng = OsRng; @@ -1260,7 +1275,7 @@ mod tests { assert!(message.serialize().iter().all(|&x| x == 0)); } - fn zeroize_verifiable_server() + fn zeroize_verifiable_server() where G::ScalarLen: Add, Sum: ArrayLength,