diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c0a095..0ecf73a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,6 @@ ## 0.7.0-pre.0 (June 28, 2026) * MSRV bumped to 1.87 -* `CipherSuite` no longer has a blanket impl via `VoprfParameters`; use `Suite` instead (breaking change) * Migrated from `elliptic-curve 0.13` to `0.14` * Replaced `generic-array` with `hybrid-array` * Updated `digest` dependency to 0.11 diff --git a/src/ciphersuite.rs b/src/ciphersuite.rs index d0eb7ef..1eb0887 100644 --- a/src/ciphersuite.rs +++ b/src/ciphersuite.rs @@ -13,7 +13,7 @@ use core::ops::Mul; use digest::block_api::BlockSizeUser; use digest::typenum::{IsLess, IsLessOrEqual, U256}; use digest::{Digest, FixedOutput, HashMarker, OutputSizeUser}; -use hash2curve::OprfParameters; +use hash2curve::{ExpandMsg, GroupDigest, OprfParameters}; use hybrid_array::ArraySize; use hybrid_array::typenum::{IsGreaterOrEqual, Prod, True, U2}; @@ -39,22 +39,31 @@ where type Hash: Digest + BlockSizeUser + Default + FixedOutput + HashMarker; } -/// A generic [`CipherSuite`] implementation for any compatible (Group, Hash) pair -#[allow(dead_code)] -#[derive(Debug)] -pub struct Suite(core::marker::PhantomData<(G, H)>); - -impl CipherSuite for Suite -where - G: Group + OprfParameters, - H: BlockSizeUser + Default + FixedOutput + HashMarker + OutputSizeUser, - ::SecurityLevel: Mul, - ::OutputSize: ArraySize - + IsLess - + IsLessOrEqual<::BlockSize, Output = True> - + IsGreaterOrEqual::SecurityLevel, U2>, Output = True>, -{ - const ID: &'static [u8] = G::ID; - type Group = G; - type Hash = H; +/// Trait associating a hash to an elliptic curve for OPRF usage. +pub trait OprfCipherSuite: OprfParameters + Group { + type Hash: Digest + BlockSizeUser + Default + FixedOutput + HashMarker + OutputSizeUser; +} + +impl OprfCipherSuite for T +where + T: OprfParameters + Group, + ::ExpandMsg: ExpandMsg<::SecurityLevel>, + <::ExpandMsg as ExpandMsg<::SecurityLevel>>::Hash: + Digest + BlockSizeUser + Default + FixedOutput + HashMarker + OutputSizeUser, +{ + type Hash = <::ExpandMsg as ExpandMsg<::SecurityLevel>>::Hash; +} + +impl CipherSuite for T +where + T: Group, + ::SecurityLevel: Mul, + <::Hash as OutputSizeUser>::OutputSize: ArraySize + + IsLess + + IsLessOrEqual<<::Hash as BlockSizeUser>::BlockSize, Output = True> + + IsGreaterOrEqual::SecurityLevel, U2>, Output = True>, +{ + const ID: &'static [u8] = T::ID; + type Group = T; + type Hash = ::Hash; } diff --git a/src/lib.rs b/src/lib.rs index 29d232a..873995c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,7 +53,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! use rand::rngs::SysRng; //! use rand::Rng; //! use voprf_vexahub::OprfServer; @@ -73,7 +73,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! use rand::rngs::SysRng; //! use rand::Rng; //! use voprf_vexahub::OprfClient; @@ -94,7 +94,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::OprfClient; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -119,7 +119,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::OprfClient; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -152,7 +152,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::OprfClient; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -199,7 +199,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! use rand::rngs::SysRng; //! use rand::Rng; //! use voprf_vexahub::VoprfServer; @@ -226,7 +226,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! use rand::rngs::SysRng; //! use rand::Rng; //! use voprf_vexahub::VoprfClient; @@ -248,7 +248,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::{VoprfServerEvaluateResult, VoprfClient}; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -275,7 +275,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::VoprfClient; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -316,7 +316,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::VoprfClient; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -370,7 +370,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::VoprfClient; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -394,7 +394,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::{VoprfServerBatchEvaluateFinishResult, VoprfClient}; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -428,7 +428,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::{VoprfServerBatchEvaluateResult, VoprfClient}; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -462,7 +462,7 @@ //! # #[cfg(feature = "ristretto255")] //! # type CipherSuite = voprf_vexahub::Ristretto255; //! # #[cfg(not(feature = "ristretto255"))] -//! # type CipherSuite = voprf_vexahub::P256CipherSuite; +//! # type CipherSuite = p256::NistP256; //! # use voprf_vexahub::{VoprfServerBatchEvaluateResult, VoprfClient}; //! # use rand::{rngs::SysRng, Rng}; //! # @@ -566,13 +566,9 @@ mod voprf; #[cfg(test)] mod tests; -/// A [`CipherSuite`] using P-256 and SHA-256, exposed for doctests. -#[cfg(feature = "doctest")] -pub type P256CipherSuite = Suite; - // Exports -pub use crate::ciphersuite::{CipherSuite, Suite}; +pub use crate::ciphersuite::CipherSuite; #[cfg(feature = "danger")] pub use crate::common::derive_key; pub use crate::common::{ diff --git a/src/oprf.rs b/src/oprf.rs index 0a072c4..488c93b 100644 --- a/src/oprf.rs +++ b/src/oprf.rs @@ -271,8 +271,8 @@ mod tests { use rand::rngs::SysRng; use super::*; + use crate::Group; use crate::common::{Dst, STR_HASH_TO_GROUP}; - use crate::{Group, Suite}; fn prf( input: &[u8], @@ -393,26 +393,26 @@ mod tests { zeroize_oprf_server::(); } - base_retrieval::>(); - base_inversion_unsalted::>(); - server_evaluate::>(); + base_retrieval::(); + base_inversion_unsalted::(); + server_evaluate::(); - zeroize_oprf_client::>(); - zeroize_oprf_server::>(); + zeroize_oprf_client::(); + zeroize_oprf_server::(); - base_retrieval::>(); - base_inversion_unsalted::>(); - server_evaluate::>(); + base_retrieval::(); + base_inversion_unsalted::(); + server_evaluate::(); - zeroize_oprf_client::>(); - zeroize_oprf_server::>(); + zeroize_oprf_client::(); + zeroize_oprf_server::(); - base_retrieval::>(); - base_inversion_unsalted::>(); - server_evaluate::>(); + base_retrieval::(); + base_inversion_unsalted::(); + server_evaluate::(); - zeroize_oprf_client::>(); - zeroize_oprf_server::>(); + zeroize_oprf_client::(); + zeroize_oprf_server::(); Ok(()) } diff --git a/src/poprf.rs b/src/poprf.rs index 9f926fb..7f12169 100644 --- a/src/poprf.rs +++ b/src/poprf.rs @@ -736,8 +736,8 @@ mod tests { use rand::rngs::SysRng; use super::*; + use crate::Group; use crate::common::STR_HASH_TO_GROUP; - use crate::{Group, Suite}; fn prf( input: &[u8], @@ -895,26 +895,26 @@ mod tests { zeroize_verifiable_server::(); } - verifiable_retrieval::>(); - verifiable_bad_public_key::>(); - verifiable_server_evaluate::>(); + verifiable_retrieval::(); + verifiable_bad_public_key::(); + verifiable_server_evaluate::(); - zeroize_verifiable_client::>(); - zeroize_verifiable_server::>(); + zeroize_verifiable_client::(); + zeroize_verifiable_server::(); - verifiable_retrieval::>(); - verifiable_bad_public_key::>(); - verifiable_server_evaluate::>(); + verifiable_retrieval::(); + verifiable_bad_public_key::(); + verifiable_server_evaluate::(); - zeroize_verifiable_client::>(); - zeroize_verifiable_server::>(); + zeroize_verifiable_client::(); + zeroize_verifiable_server::(); - verifiable_retrieval::>(); - verifiable_bad_public_key::>(); - verifiable_server_evaluate::>(); + verifiable_retrieval::(); + verifiable_bad_public_key::(); + verifiable_server_evaluate::(); - zeroize_verifiable_client::>(); - zeroize_verifiable_server::>(); + zeroize_verifiable_client::(); + zeroize_verifiable_server::(); Ok(()) } diff --git a/src/serialization.rs b/src/serialization.rs index 167d024..ecaa8d6 100644 --- a/src/serialization.rs +++ b/src/serialization.rs @@ -328,9 +328,9 @@ mod test { let _ = $item::::deserialize(&$bytes[..]); } - let _ = $item::>::deserialize(&$bytes[..]); - let _ = $item::>::deserialize(&$bytes[..]); - let _ = $item::>::deserialize(&$bytes[..]); + let _ = $item::::deserialize(&$bytes[..]); + let _ = $item::::deserialize(&$bytes[..]); + let _ = $item::::deserialize(&$bytes[..]); }; } diff --git a/src/tests/test_cfrg_vectors.rs b/src/tests/test_cfrg_vectors.rs index bb7cd58..99c96aa 100644 --- a/src/tests/test_cfrg_vectors.rs +++ b/src/tests/test_cfrg_vectors.rs @@ -17,7 +17,7 @@ use crate::tests::parser::*; use crate::{ BlindedElement, CipherSuite, EvaluationElement, Group, OprfClient, OprfServer, PoprfClient, PoprfServer, PoprfServerBatchEvaluateFinishResult, PoprfServerBatchEvaluatePrepareResult, - Proof, Result, Suite, VoprfClient, VoprfServer, VoprfServerBatchEvaluateFinishResult, + Proof, Result, VoprfClient, VoprfServer, VoprfServerBatchEvaluateFinishResult, }; #[derive(Debug)] @@ -133,83 +133,83 @@ fn test_vectors() -> Result<()> { let p256_oprf_tvs = json_to_test_vectors!(rfc, String::from("P256-SHA256"), String::from("OPRF")); assert_ne!(p256_oprf_tvs.len(), 0); - test_oprf_seed_to_key::>(&p256_oprf_tvs)?; - test_oprf_blind::>(&p256_oprf_tvs)?; - test_oprf_blind_evaluate::>(&p256_oprf_tvs)?; - test_oprf_finalize::>(&p256_oprf_tvs)?; - test_oprf_evaluate::>(&p256_oprf_tvs)?; + test_oprf_seed_to_key::(&p256_oprf_tvs)?; + test_oprf_blind::(&p256_oprf_tvs)?; + test_oprf_blind_evaluate::(&p256_oprf_tvs)?; + test_oprf_finalize::(&p256_oprf_tvs)?; + test_oprf_evaluate::(&p256_oprf_tvs)?; let p256_voprf_tvs = json_to_test_vectors!(rfc, String::from("P256-SHA256"), String::from("VOPRF")); assert_ne!(p256_voprf_tvs.len(), 0); - test_voprf_seed_to_key::>(&p256_voprf_tvs)?; - test_voprf_blind::>(&p256_voprf_tvs)?; - test_voprf_blind_evaluate::>(&p256_voprf_tvs)?; - test_voprf_finalize::>(&p256_voprf_tvs)?; - test_voprf_evaluate::>(&p256_voprf_tvs)?; + test_voprf_seed_to_key::(&p256_voprf_tvs)?; + test_voprf_blind::(&p256_voprf_tvs)?; + test_voprf_blind_evaluate::(&p256_voprf_tvs)?; + test_voprf_finalize::(&p256_voprf_tvs)?; + test_voprf_evaluate::(&p256_voprf_tvs)?; let p256_poprf_tvs = json_to_test_vectors!(rfc, String::from("P256-SHA256"), String::from("POPRF")); assert_ne!(p256_poprf_tvs.len(), 0); - test_poprf_seed_to_key::>(&p256_poprf_tvs)?; - test_poprf_blind::>(&p256_poprf_tvs)?; - test_poprf_blind_evaluate::>(&p256_poprf_tvs)?; - test_poprf_finalize::>(&p256_poprf_tvs)?; - test_poprf_evaluate::>(&p256_poprf_tvs)?; + test_poprf_seed_to_key::(&p256_poprf_tvs)?; + test_poprf_blind::(&p256_poprf_tvs)?; + test_poprf_blind_evaluate::(&p256_poprf_tvs)?; + test_poprf_finalize::(&p256_poprf_tvs)?; + test_poprf_evaluate::(&p256_poprf_tvs)?; let p384_oprf_tvs = json_to_test_vectors!(rfc, String::from("P384-SHA384"), String::from("OPRF")); assert_ne!(p384_oprf_tvs.len(), 0); - test_oprf_seed_to_key::>(&p384_oprf_tvs)?; - test_oprf_blind::>(&p384_oprf_tvs)?; - test_oprf_blind_evaluate::>(&p384_oprf_tvs)?; - test_oprf_finalize::>(&p384_oprf_tvs)?; - test_oprf_evaluate::>(&p384_oprf_tvs)?; + test_oprf_seed_to_key::(&p384_oprf_tvs)?; + test_oprf_blind::(&p384_oprf_tvs)?; + test_oprf_blind_evaluate::(&p384_oprf_tvs)?; + test_oprf_finalize::(&p384_oprf_tvs)?; + test_oprf_evaluate::(&p384_oprf_tvs)?; let p384_voprf_tvs = json_to_test_vectors!(rfc, String::from("P384-SHA384"), String::from("VOPRF")); assert_ne!(p384_voprf_tvs.len(), 0); - test_voprf_seed_to_key::>(&p384_voprf_tvs)?; - test_voprf_blind::>(&p384_voprf_tvs)?; - test_voprf_blind_evaluate::>(&p384_voprf_tvs)?; - test_voprf_finalize::>(&p384_voprf_tvs)?; - test_voprf_evaluate::>(&p384_voprf_tvs)?; + test_voprf_seed_to_key::(&p384_voprf_tvs)?; + test_voprf_blind::(&p384_voprf_tvs)?; + test_voprf_blind_evaluate::(&p384_voprf_tvs)?; + test_voprf_finalize::(&p384_voprf_tvs)?; + test_voprf_evaluate::(&p384_voprf_tvs)?; let p384_poprf_tvs = json_to_test_vectors!(rfc, String::from("P384-SHA384"), String::from("POPRF")); assert_ne!(p384_poprf_tvs.len(), 0); - test_poprf_seed_to_key::>(&p384_poprf_tvs)?; - test_poprf_blind::>(&p384_poprf_tvs)?; - test_poprf_blind_evaluate::>(&p384_poprf_tvs)?; - test_poprf_finalize::>(&p384_poprf_tvs)?; - test_poprf_evaluate::>(&p384_poprf_tvs)?; + test_poprf_seed_to_key::(&p384_poprf_tvs)?; + test_poprf_blind::(&p384_poprf_tvs)?; + test_poprf_blind_evaluate::(&p384_poprf_tvs)?; + test_poprf_finalize::(&p384_poprf_tvs)?; + test_poprf_evaluate::(&p384_poprf_tvs)?; let p521_oprf_tvs = json_to_test_vectors!(rfc, String::from("P521-SHA512"), String::from("OPRF")); assert_ne!(p521_oprf_tvs.len(), 0); - test_oprf_seed_to_key::>(&p521_oprf_tvs)?; - test_oprf_blind::>(&p521_oprf_tvs)?; - test_oprf_blind_evaluate::>(&p521_oprf_tvs)?; - test_oprf_finalize::>(&p521_oprf_tvs)?; - test_oprf_evaluate::>(&p521_oprf_tvs)?; + test_oprf_seed_to_key::(&p521_oprf_tvs)?; + test_oprf_blind::(&p521_oprf_tvs)?; + test_oprf_blind_evaluate::(&p521_oprf_tvs)?; + test_oprf_finalize::(&p521_oprf_tvs)?; + test_oprf_evaluate::(&p521_oprf_tvs)?; let p521_voprf_tvs = json_to_test_vectors!(rfc, String::from("P521-SHA512"), String::from("VOPRF")); assert_ne!(p521_voprf_tvs.len(), 0); - test_voprf_seed_to_key::>(&p521_voprf_tvs)?; - test_voprf_blind::>(&p521_voprf_tvs)?; - test_voprf_blind_evaluate::>(&p521_voprf_tvs)?; - test_voprf_finalize::>(&p521_voprf_tvs)?; - test_voprf_evaluate::>(&p521_voprf_tvs)?; + test_voprf_seed_to_key::(&p521_voprf_tvs)?; + test_voprf_blind::(&p521_voprf_tvs)?; + test_voprf_blind_evaluate::(&p521_voprf_tvs)?; + test_voprf_finalize::(&p521_voprf_tvs)?; + test_voprf_evaluate::(&p521_voprf_tvs)?; let p521_poprf_tvs = json_to_test_vectors!(rfc, String::from("P521-SHA512"), String::from("POPRF")); assert_ne!(p521_poprf_tvs.len(), 0); - test_poprf_seed_to_key::>(&p521_poprf_tvs)?; - test_poprf_blind::>(&p521_poprf_tvs)?; - test_poprf_blind_evaluate::>(&p521_poprf_tvs)?; - test_poprf_finalize::>(&p521_poprf_tvs)?; - test_poprf_evaluate::>(&p521_poprf_tvs)?; + test_poprf_seed_to_key::(&p521_poprf_tvs)?; + test_poprf_blind::(&p521_poprf_tvs)?; + test_poprf_blind_evaluate::(&p521_poprf_tvs)?; + test_poprf_finalize::(&p521_poprf_tvs)?; + test_poprf_evaluate::(&p521_poprf_tvs)?; Ok(()) } diff --git a/src/voprf.rs b/src/voprf.rs index 3e46ac1..ebf43fd 100644 --- a/src/voprf.rs +++ b/src/voprf.rs @@ -553,8 +553,8 @@ mod tests { use rand::rngs::SysRng; use super::*; + use crate::Group; use crate::common::{Dst, STR_HASH_TO_GROUP}; - use crate::{Group, Suite}; fn prf( input: &[u8], @@ -774,32 +774,32 @@ mod tests { zeroize_voprf_server::(); } - verifiable_retrieval::>(); - verifiable_batch_retrieval::>(); - verifiable_bad_public_key::>(); - verifiable_batch_bad_public_key::>(); - verifiable_server_evaluate::>(); + verifiable_retrieval::(); + verifiable_batch_retrieval::(); + verifiable_bad_public_key::(); + verifiable_batch_bad_public_key::(); + verifiable_server_evaluate::(); - zeroize_voprf_client::>(); - zeroize_voprf_server::>(); + zeroize_voprf_client::(); + zeroize_voprf_server::(); - verifiable_retrieval::>(); - verifiable_batch_retrieval::>(); - verifiable_bad_public_key::>(); - verifiable_batch_bad_public_key::>(); - verifiable_server_evaluate::>(); + verifiable_retrieval::(); + verifiable_batch_retrieval::(); + verifiable_bad_public_key::(); + verifiable_batch_bad_public_key::(); + verifiable_server_evaluate::(); - zeroize_voprf_client::>(); - zeroize_voprf_server::>(); + zeroize_voprf_client::(); + zeroize_voprf_server::(); - verifiable_retrieval::>(); - verifiable_batch_retrieval::>(); - verifiable_bad_public_key::>(); - verifiable_batch_bad_public_key::>(); - verifiable_server_evaluate::>(); + verifiable_retrieval::(); + verifiable_batch_retrieval::(); + verifiable_bad_public_key::(); + verifiable_batch_bad_public_key::(); + verifiable_server_evaluate::(); - zeroize_voprf_client::>(); - zeroize_voprf_server::>(); + zeroize_voprf_client::(); + zeroize_voprf_server::(); Ok(()) }