diff --git a/.github/workflows/elliptic-curve.yml b/.github/workflows/elliptic-curve.yml index ac4bdccdc..57d4d4c9a 100644 --- a/.github/workflows/elliptic-curve.yml +++ b/.github/workflows/elliptic-curve.yml @@ -45,16 +45,16 @@ jobs: - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features ecdh - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features hash2curve - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features jwk + - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features oprf - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features pem - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features pkcs8 - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features sec1 - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features serde - - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features voprf - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,arithmetic - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,arithmetic,pkcs8 - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,serde - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features arithmetic,serde - - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,digest,ecdh,hash2curve,jwk,pem,pkcs8,sec1,serde,voprf + - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,digest,ecdh,hash2curve,jwk,oprf,pem,pkcs8,sec1,serde minimal-versions: # Temporarily disabled until elliptic-curve 0.13.0-pre.0 is published diff --git a/Cargo.lock b/Cargo.lock index f11b4d85b..9aadabffd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -540,7 +540,7 @@ dependencies = [ [[package]] name = "sha2" version = "0.11.0-pre.5" -source = "git+https://github.com/RustCrypto/hashes.git#7d44caf065dbeb3f10a372a26a8b9f1c927f8433" +source = "git+https://github.com/RustCrypto/hashes.git#d9ad085ed12dba58d2a6d75d76a17a1b2706c4c7" dependencies = [ "cfg-if", "cpufeatures", @@ -550,7 +550,7 @@ dependencies = [ [[package]] name = "sha3" version = "0.11.0-pre.5" -source = "git+https://github.com/RustCrypto/hashes.git#7d44caf065dbeb3f10a372a26a8b9f1c927f8433" +source = "git+https://github.com/RustCrypto/hashes.git#d9ad085ed12dba58d2a6d75d76a17a1b2706c4c7" dependencies = [ "digest", "keccak", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index f60db0eca..f9b545a4d 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -66,10 +66,10 @@ hash2curve = ["arithmetic", "digest"] ecdh = ["arithmetic", "digest", "dep:hkdf"] group = ["dep:group", "ff"] jwk = ["dep:base64ct", "dep:serde_json", "alloc", "serde", "zeroize/alloc"] +oprf = ["digest", "hash2curve"] pkcs8 = ["dep:pkcs8", "sec1"] pem = ["dep:pem-rfc7468", "alloc", "arithmetic", "pkcs8", "sec1/pem"] serde = ["dep:serdect", "alloc", "pkcs8", "sec1/serde"] -voprf = ["digest", "hash2curve"] [package.metadata.docs.rs] -features = ["bits", "ecdh", "hash2curve", "jwk", "pem", "std", "voprf"] +features = ["bits", "ecdh", "hash2curve", "jwk", "oprf", "pem", "std"] diff --git a/elliptic-curve/src/hash2curve.rs b/elliptic-curve/src/hash2curve.rs index 3df394f79..da923e4d2 100644 --- a/elliptic-curve/src/hash2curve.rs +++ b/elliptic-curve/src/hash2curve.rs @@ -1,6 +1,6 @@ //! Traits for hashing byte sequences to curve points. //! -//! +//! mod group_digest; mod hash2field; diff --git a/elliptic-curve/src/hash2curve/group_digest.rs b/elliptic-curve/src/hash2curve/group_digest.rs index 5320c5a69..571f43e81 100644 --- a/elliptic-curve/src/hash2curve/group_digest.rs +++ b/elliptic-curve/src/hash2curve/group_digest.rs @@ -1,6 +1,6 @@ //! Traits for handling hash to curve. -use super::{ExpandMsg, FromOkm, MapToCurve, hash_to_field}; +use super::{ExpandMsg, MapToCurve, hash_to_field}; use crate::{ProjectivePoint, Result}; use hybrid_array::typenum::Unsigned; @@ -13,7 +13,7 @@ pub trait GroupDigest: MapToCurve { /// Computes the hash to curve routine. /// - /// From : + /// From : /// /// > Uniform encoding from byte strings to points in G. /// > That is, the distribution of its output is statistically close @@ -22,20 +22,6 @@ pub trait GroupDigest: MapToCurve { /// > oracle returning points in G assuming a cryptographically secure /// > hash function is used. /// - /// # Examples - /// - /// ## Using a fixed size hash function - /// - /// ```ignore - /// let pt = ProjectivePoint::hash_from_bytes::>(b"test data", b"CURVE_XMD:SHA-256_SSWU_RO_"); - /// ``` - /// - /// ## Using an extendable output function - /// - /// ```ignore - /// let pt = ProjectivePoint::hash_from_bytes::>(b"test data", b"CURVE_XOF:SHAKE-256_SSWU_RO_"); - /// ``` - /// /// # Errors /// See implementors of [`ExpandMsg`] for errors: /// - [`ExpandMsgXmd`] @@ -45,12 +31,12 @@ pub trait GroupDigest: MapToCurve { /// /// [`ExpandMsgXmd`]: crate::hash2curve::ExpandMsgXmd /// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof - fn hash_from_bytes<'a, X: ExpandMsg<'a>>( - msgs: &[&[u8]], - dsts: &'a [&'a [u8]], - ) -> Result> { + fn hash_from_bytes(msg: &[&[u8]], dst: &[&[u8]]) -> Result> + where + X: ExpandMsg, + { let mut u = [Self::FieldElement::default(), Self::FieldElement::default()]; - hash_to_field::(msgs, dsts, &mut u)?; + hash_to_field::(msg, dst, &mut u)?; let q0 = Self::map_to_curve(u[0]); let q1 = Self::map_to_curve(u[1]); Ok(Self::add_and_map_to_subgroup(q0, q1)) @@ -58,7 +44,7 @@ pub trait GroupDigest: MapToCurve { /// Computes the encode to curve routine. /// - /// From : + /// From : /// /// > Nonuniform encoding from byte strings to /// > points in G. That is, the distribution of its output is not @@ -75,18 +61,18 @@ pub trait GroupDigest: MapToCurve { /// /// [`ExpandMsgXmd`]: crate::hash2curve::ExpandMsgXmd /// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof - fn encode_from_bytes<'a, X: ExpandMsg<'a>>( - msgs: &[&[u8]], - dsts: &'a [&'a [u8]], - ) -> Result> { + fn encode_from_bytes(msg: &[&[u8]], dst: &[&[u8]]) -> Result> + where + X: ExpandMsg, + { let mut u = [Self::FieldElement::default()]; - hash_to_field::(msgs, dsts, &mut u)?; + hash_to_field::(msg, dst, &mut u)?; let q0 = Self::map_to_curve(u[0]); Ok(Self::map_to_subgroup(q0)) } /// Computes the hash to field routine according to - /// + /// /// and returns a scalar. /// /// # Errors @@ -98,15 +84,12 @@ pub trait GroupDigest: MapToCurve { /// /// [`ExpandMsgXmd`]: crate::hash2curve::ExpandMsgXmd /// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof - fn hash_to_scalar<'a, X: ExpandMsg<'a>>( - msgs: &[&[u8]], - dsts: &'a [&'a [u8]], - ) -> Result + fn hash_to_scalar(msg: &[&[u8]], dst: &[&[u8]]) -> Result where - Self::Scalar: FromOkm, + X: ExpandMsg, { let mut u = [Self::Scalar::default()]; - hash_to_field::(msgs, dsts, &mut u)?; + hash_to_field::(msg, dst, &mut u)?; Ok(u[0]) } } diff --git a/elliptic-curve/src/hash2curve/hash2field.rs b/elliptic-curve/src/hash2curve/hash2field.rs index 4ffcf8062..990230105 100644 --- a/elliptic-curve/src/hash2curve/hash2field.rs +++ b/elliptic-curve/src/hash2curve/hash2field.rs @@ -1,6 +1,6 @@ //! Traits for hashing to field elements. //! -//! +//! mod expand_msg; @@ -25,7 +25,7 @@ pub trait FromOkm { /// Convert an arbitrary byte sequence into a field element. /// -/// +/// /// /// # Errors /// See implementors of [`ExpandMsg`] for errors: @@ -37,9 +37,9 @@ pub trait FromOkm { /// [`ExpandMsgXmd`]: crate::hash2field::ExpandMsgXmd /// [`ExpandMsgXof`]: crate::hash2field::ExpandMsgXof #[doc(hidden)] -pub fn hash_to_field<'a, E, T>(data: &[&[u8]], domain: &'a [&'a [u8]], out: &mut [T]) -> Result<()> +pub fn hash_to_field(data: &[&[u8]], domain: &[&[u8]], out: &mut [T]) -> Result<()> where - E: ExpandMsg<'a>, + E: ExpandMsg, T: FromOkm + Default, { let len_in_bytes = T::Length::to_usize() diff --git a/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs b/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs index e8fb802a6..233b6b9f0 100644 --- a/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs +++ b/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs @@ -17,21 +17,25 @@ const MAX_DST_LEN: usize = 255; /// Trait for types implementing expand_message interface for `hash_to_field`. /// +/// `K` is the target security level in bytes: +/// +/// +/// /// # Errors /// See implementors of [`ExpandMsg`] for errors. -pub trait ExpandMsg<'a> { +pub trait ExpandMsg { /// Type holding data for the [`Expander`]. - type Expander: Expander + Sized; + type Expander<'dst>: Expander + Sized; /// Expands `msg` to the required number of bytes. /// /// Returns an expander that can be used to call `read` until enough /// bytes have been consumed - fn expand_message( - msgs: &[&[u8]], - dsts: &'a [&'a [u8]], + fn expand_message<'dst>( + msg: &[&[u8]], + dst: &'dst [&[u8]], len_in_bytes: NonZero, - ) -> Result; + ) -> Result>; } /// Expander that, call `read` until enough bytes have been consumed. @@ -42,9 +46,9 @@ pub trait Expander { /// The domain separation tag /// -/// Implements [section 5.4.3 of `draft-irtf-cfrg-hash-to-curve-13`][dst]. +/// Implements [section 5.3.3 of RFC9380][dst]. /// -/// [dst]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-13#section-5.4.3 +/// [dst]: https://www.rfc-editor.org/rfc/rfc9380.html#name-using-dsts-longer-than-255- #[derive(Debug)] pub(crate) enum Domain<'a, L> where @@ -60,48 +64,50 @@ impl<'a, L> Domain<'a, L> where L: ArraySize + IsLess, { - pub fn xof(dsts: &'a [&'a [u8]]) -> Result + pub fn xof(dst: &'a [&'a [u8]]) -> Result where X: Default + ExtendableOutput + Update, { - if dsts.is_empty() { + // https://www.rfc-editor.org/rfc/rfc9380.html#section-3.1-4.2 + if dst.iter().map(|slice| slice.len()).sum::() == 0 { Err(Error) - } else if dsts.iter().map(|dst| dst.len()).sum::() > MAX_DST_LEN { + } else if dst.iter().map(|slice| slice.len()).sum::() > MAX_DST_LEN { let mut data = Array::::default(); let mut hash = X::default(); hash.update(OVERSIZE_DST_SALT); - for dst in dsts { - hash.update(dst); + for slice in dst { + hash.update(slice); } hash.finalize_xof().read(&mut data); Ok(Self::Hashed(data)) } else { - Ok(Self::Array(dsts)) + Ok(Self::Array(dst)) } } - pub fn xmd(dsts: &'a [&'a [u8]]) -> Result + pub fn xmd(dst: &'a [&'a [u8]]) -> Result where X: Digest, { - if dsts.is_empty() { + // https://www.rfc-editor.org/rfc/rfc9380.html#section-3.1-4.2 + if dst.iter().map(|slice| slice.len()).sum::() == 0 { Err(Error) - } else if dsts.iter().map(|dst| dst.len()).sum::() > MAX_DST_LEN { + } else if dst.iter().map(|slice| slice.len()).sum::() > MAX_DST_LEN { Ok(Self::Hashed({ let mut hash = X::new(); hash.update(OVERSIZE_DST_SALT); - for dst in dsts { - hash.update(dst); + for slice in dst { + hash.update(slice); } hash.finalize() })) } else { - Ok(Self::Array(dsts)) + Ok(Self::Array(dst)) } } diff --git a/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs b/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs index fcd63dca7..8ae1ec022 100644 --- a/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs +++ b/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs @@ -8,7 +8,7 @@ use digest::{ FixedOutput, HashMarker, array::{ Array, - typenum::{IsGreaterOrEqual, IsLess, IsLessOrEqual, True, U2, U256, Unsigned}, + typenum::{IsGreaterOrEqual, IsLess, IsLessOrEqual, Prod, True, U2, U256, Unsigned}, }, block_api::BlockSizeUser, }; @@ -16,45 +16,39 @@ use digest::{ /// Implements `expand_message_xof` via the [`ExpandMsg`] trait: /// /// -/// `K` is the target security level in bytes: -/// -/// -/// /// # Errors -/// - `dst.is_empty()` +/// - `dst` contains no bytes /// - `len_in_bytes > u16::MAX` /// - `len_in_bytes > 255 * HashT::OutputSize` #[derive(Debug)] -pub struct ExpandMsgXmd(PhantomData<(HashT, K)>) +pub struct ExpandMsgXmd(PhantomData) where HashT: BlockSizeUser + Default + FixedOutput + HashMarker, HashT::OutputSize: IsLess, - HashT::OutputSize: IsLessOrEqual, - K: Mul, - HashT::OutputSize: IsGreaterOrEqual<>::Output, Output = True>; + HashT::OutputSize: IsLessOrEqual; -impl<'a, HashT, K> ExpandMsg<'a> for ExpandMsgXmd +impl ExpandMsg for ExpandMsgXmd where HashT: BlockSizeUser + Default + FixedOutput + HashMarker, // If DST is larger than 255 bytes, the length of the computed DST will depend on the output - // size of the hash, which is still not allowed to be larger than 256: - // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html#section-5.4.1-6 + // size of the hash, which is still not allowed to be larger than 255. + // https://www.rfc-editor.org/rfc/rfc9380.html#section-5.3.1-6 HashT::OutputSize: IsLess, - // Constraint set by `expand_message_xmd`: - // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html#section-5.4.1-4 + // The number of bits output by `HashT` MUST be at most `HashT::BlockSize`. + // https://www.rfc-editor.org/rfc/rfc9380.html#section-5.3.1-4 HashT::OutputSize: IsLessOrEqual, - // The number of bits output by `HashT` MUST be larger or equal to `K * 2`: + // The number of bits output by `HashT` MUST be at least `K * 2`. // https://www.rfc-editor.org/rfc/rfc9380.html#section-5.3.1-2.1 K: Mul, - HashT::OutputSize: IsGreaterOrEqual<>::Output, Output = True>, + HashT::OutputSize: IsGreaterOrEqual, Output = True>, { - type Expander = ExpanderXmd<'a, HashT>; + type Expander<'dst> = ExpanderXmd<'dst, HashT>; - fn expand_message( - msgs: &[&[u8]], - dsts: &'a [&'a [u8]], + fn expand_message<'dst>( + msg: &[&[u8]], + dst: &'dst [&[u8]], len_in_bytes: NonZero, - ) -> Result { + ) -> Result> { let len_in_bytes_u16 = u16::try_from(len_in_bytes.get()).map_err(|_| Error)?; // `255 * ` can not exceed `u16::MAX` @@ -65,11 +59,11 @@ where let b_in_bytes = HashT::OutputSize::to_usize(); let ell = u8::try_from(len_in_bytes.get().div_ceil(b_in_bytes)).map_err(|_| Error)?; - let domain = Domain::xmd::(dsts)?; + let domain = Domain::xmd::(dst)?; let mut b_0 = HashT::default(); b_0.update(&Array::::default()); - for msg in msgs { + for msg in msg { b_0.update(msg); } @@ -222,12 +216,12 @@ mod test { HashT::OutputSize: IsLess + IsLessOrEqual + Mul, - HashT::OutputSize: IsGreaterOrEqual<>::Output, Output = True>, + HashT::OutputSize: IsGreaterOrEqual, { assert_message::(self.msg, domain, L::to_u16(), self.msg_prime); let dst = [dst]; - let mut expander = ExpandMsgXmd::::expand_message( + let mut expander = as ExpandMsg>::expand_message( &[self.msg], &dst, NonZero::new(L::to_usize()).ok_or(Error)?, diff --git a/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs b/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs index 201aee156..25f6858be 100644 --- a/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs +++ b/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs @@ -2,38 +2,31 @@ use super::{Domain, ExpandMsg, Expander}; use crate::{Error, Result}; -use core::{fmt, marker::PhantomData, num::NonZero, ops::Mul}; -use digest::{ExtendableOutput, HashMarker, Update, XofReader}; +use core::{fmt, num::NonZero, ops::Mul}; +use digest::{ + CollisionResistance, ExtendableOutput, HashMarker, Update, XofReader, typenum::IsGreaterOrEqual, +}; use hybrid_array::{ ArraySize, - typenum::{IsLess, True, U2, U256}, + typenum::{IsLess, Prod, True, U2, U256}, }; /// Implements `expand_message_xof` via the [`ExpandMsg`] trait: /// /// -/// `K` is the target security level in bytes: -/// -/// -/// /// # Errors -/// - `dst.is_empty()` +/// - `dst` contains no bytes /// - `len_in_bytes > u16::MAX` -pub struct ExpandMsgXof +pub struct ExpandMsgXof where HashT: Default + ExtendableOutput + Update + HashMarker, - K: Mul, - >::Output: ArraySize + IsLess, { reader: ::Reader, - _k: PhantomData, } -impl fmt::Debug for ExpandMsgXof +impl fmt::Debug for ExpandMsgXof where HashT: Default + ExtendableOutput + Update + HashMarker, - K: Mul, - >::Output: ArraySize + IsLess, ::Reader: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -43,27 +36,29 @@ where } } -impl<'a, HashT, K> ExpandMsg<'a> for ExpandMsgXof +impl ExpandMsg for ExpandMsgXof where HashT: Default + ExtendableOutput + Update + HashMarker, // If DST is larger than 255 bytes, the length of the computed DST is calculated by `K * 2`. // https://www.rfc-editor.org/rfc/rfc9380.html#section-5.3.1-2.1 - K: Mul, - >::Output: ArraySize + IsLess, + K: Mul>, + // The collision resistance of `HashT` MUST be at least `K` bits. + // https://www.rfc-editor.org/rfc/rfc9380.html#section-5.3.2-2.1 + HashT: CollisionResistance>, { - type Expander = Self; + type Expander<'dst> = Self; - fn expand_message( - msgs: &[&[u8]], - dsts: &'a [&'a [u8]], + fn expand_message<'dst>( + msg: &[&[u8]], + dst: &'dst [&[u8]], len_in_bytes: NonZero, - ) -> Result { + ) -> Result> { let len_in_bytes = u16::try_from(len_in_bytes.get()).map_err(|_| Error)?; - let domain = Domain::<>::Output>::xof::(dsts)?; + let domain = Domain::>::xof::(dst)?; let mut reader = HashT::default(); - for msg in msgs { + for msg in msg { reader = reader.chain(msg); } @@ -71,18 +66,13 @@ where domain.update_hash(&mut reader); reader.update(&[domain.len()]); let reader = reader.finalize_xof(); - Ok(Self { - reader, - _k: PhantomData, - }) + Ok(Self { reader }) } } -impl Expander for ExpandMsgXof +impl Expander for ExpandMsgXof where HashT: Default + ExtendableOutput + Update + HashMarker, - K: Mul, - >::Output: ArraySize + IsLess, { fn fill_bytes(&mut self, okm: &mut [u8]) { self.reader.read(okm); @@ -129,12 +119,16 @@ mod test { #[allow(clippy::panic_in_result_fn)] fn assert(&self, dst: &'static [u8], domain: &Domain<'_, U32>) -> Result<()> where - HashT: Default + ExtendableOutput + Update + HashMarker, + HashT: Default + + ExtendableOutput + + Update + + HashMarker + + CollisionResistance>, L: ArraySize, { assert_message(self.msg, domain, L::to_u16(), self.msg_prime); - let mut expander = ExpandMsgXof::::expand_message( + let mut expander = as ExpandMsg>::expand_message( &[self.msg], &[dst], NonZero::new(L::to_usize()).ok_or(Error)?, diff --git a/elliptic-curve/src/hash2curve/isogeny.rs b/elliptic-curve/src/hash2curve/isogeny.rs index 4644d786a..5b11900d9 100644 --- a/elliptic-curve/src/hash2curve/isogeny.rs +++ b/elliptic-curve/src/hash2curve/isogeny.rs @@ -1,6 +1,6 @@ //! Traits for mapping an isogeny to another curve //! -//! +//! use core::ops::{AddAssign, Mul}; use ff::Field; diff --git a/elliptic-curve/src/hash2curve/map2curve.rs b/elliptic-curve/src/hash2curve/map2curve.rs index aa72e11b5..7ab69a2af 100644 --- a/elliptic-curve/src/hash2curve/map2curve.rs +++ b/elliptic-curve/src/hash2curve/map2curve.rs @@ -6,7 +6,7 @@ use super::FromOkm; /// Trait for converting field elements into a point via a mapping method like /// Simplified Shallue-van de Woestijne-Ulas or Elligator. -pub trait MapToCurve: CurveArithmetic { +pub trait MapToCurve: CurveArithmetic { /// The intermediate representation, an element of the curve which may or may not /// be in the curve subgroup. type CurvePoint; diff --git a/elliptic-curve/src/hash2curve/osswu.rs b/elliptic-curve/src/hash2curve/osswu.rs index dc5d16d57..ea8acdc5b 100644 --- a/elliptic-curve/src/hash2curve/osswu.rs +++ b/elliptic-curve/src/hash2curve/osswu.rs @@ -1,6 +1,6 @@ //! Optimized simplified Shallue-van de Woestijne-Ulas methods. //! -//! +//! use ff::Field; use subtle::Choice; diff --git a/elliptic-curve/src/lib.rs b/elliptic-curve/src/lib.rs index ff5acd88f..8e5ccacaf 100644 --- a/elliptic-curve/src/lib.rs +++ b/elliptic-curve/src/lib.rs @@ -112,8 +112,8 @@ mod public_key; #[cfg(feature = "jwk")] mod jwk; -#[cfg(feature = "voprf")] -mod voprf; +#[cfg(feature = "oprf")] +mod oprf; pub use crate::{ error::{Error, Result}, @@ -146,8 +146,8 @@ pub use crate::jwk::{JwkEcKey, JwkParameters}; #[cfg(feature = "pkcs8")] pub use pkcs8; -#[cfg(feature = "voprf")] -pub use crate::voprf::VoprfParameters; +#[cfg(feature = "oprf")] +pub use crate::oprf::OprfParameters; use core::{ fmt::Debug, diff --git a/elliptic-curve/src/oprf.rs b/elliptic-curve/src/oprf.rs new file mode 100644 index 000000000..b6806f74f --- /dev/null +++ b/elliptic-curve/src/oprf.rs @@ -0,0 +1,30 @@ +//! Oblivious Pseudorandom Functions (OPRF) using prime order groups +//! +//! + +use digest::{FixedOutput, Update}; +use hybrid_array::typenum::{IsLess, True, U65536}; + +use crate::PrimeCurve; +use crate::hash2curve::{ExpandMsg, GroupDigest}; + +/// Elliptic curve parameters used by OPRF. +pub trait OprfParameters: GroupDigest + PrimeCurve { + /// The `ID` parameter which identifies a particular elliptic curve + /// as defined in [section 4 of RFC9497][oprf]. + /// + /// [oprf]: https://www.rfc-editor.org/rfc/rfc9497.html#name-ciphersuites + const ID: &'static [u8]; + + /// The `Hash` parameter which assigns a particular hash function to this + /// ciphersuite as defined in [section 4 of RFC9497][oprf]. + /// + /// [oprf]: https://www.rfc-editor.org/rfc/rfc9497.html#name-ciphersuites + type Hash: Default + FixedOutput> + Update; + + /// The `expand_message` parameter which assigns a particular algorithm for `HashToGroup` + /// and `HashToScalar` as defined in [section 4 of RFC9497][oprf]. + /// + /// [oprf]: https://www.rfc-editor.org/rfc/rfc9497.html#name-ciphersuites + type ExpandMsg: ExpandMsg<::K>; +} diff --git a/elliptic-curve/src/voprf.rs b/elliptic-curve/src/voprf.rs deleted file mode 100644 index e882fe1b3..000000000 --- a/elliptic-curve/src/voprf.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! Verifiable Oblivious Pseudorandom Function (VOPRF) using prime order groups -//! -//! - -use crate::PrimeCurve; -use crate::hash2curve::ExpandMsg; - -/// Elliptic curve parameters used by VOPRF. -pub trait VoprfParameters: PrimeCurve { - /// The `ID` parameter which identifies a particular elliptic curve - /// as defined in [section 4 of `draft-irtf-cfrg-voprf-19`][voprf]. - /// - /// [voprf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-19.html#name-ciphersuites-2 - const ID: &'static str; - - /// The `Hash` parameter which assigns a particular hash function to this - /// ciphersuite as defined in [section 4 of `draft-irtf-cfrg-voprf-19`][voprf]. - /// - /// [voprf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-19.html#name-ciphersuites-2 - type Hash: digest::Digest; - - /// The `expand_message` parameter which assigns a particular algorithm for `HashToGroup` - /// and `HashToScalar` as defined in [section 4 of `draft-irtf-cfrg-voprf-19`][voprf]. - /// - /// [voprf]: https://www.rfc-editor.org/rfc/rfc9497#name-ciphersuites - type ExpandMsg: for<'a> ExpandMsg<'a>; -}