As a way to roll back the genericity, implement an extension trait of group for password-to-curve hashing,
This supersedes #18. Co-authored-by: KevinLewi <[email protected]>
This commit is contained in:
co-authored by
KevinLewi
parent
41cd80ccb5
commit
9d40aa7659
Generated
-1
@@ -202,7 +202,6 @@ dependencies = [
|
||||
"aead 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"generic-array 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hkdf 0.9.0-alpha.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
||||
@@ -15,7 +15,6 @@ slow-hash = ["scrypt"]
|
||||
[dependencies]
|
||||
aead = "0.3.1"
|
||||
curve25519-dalek = "2.1.0"
|
||||
digest = "0.9"
|
||||
generic-array = "0.14.2"
|
||||
hkdf = "0.9.0-alpha.0"
|
||||
hmac = "0.8.0"
|
||||
|
||||
+7
-9
@@ -7,24 +7,22 @@
|
||||
|
||||
use crate::{
|
||||
errors::InternalPakeError,
|
||||
group::Group,
|
||||
keypair::{Key, KeyPair},
|
||||
oprf::HkdfDigest,
|
||||
map_to_curve::GroupWithMapToCurve,
|
||||
slow_hash::SlowHash,
|
||||
};
|
||||
use digest::FixedOutput;
|
||||
use generic_array::typenum::{U32};
|
||||
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
/// Configures the underlying primitives used in OPAQUE
|
||||
/// * `Digest`: a digest suitable for use in an Hkdf, with an output length equal
|
||||
/// to the input of the hash-to-curve function of the `Group` parameter.
|
||||
/// * `Group`: a finite cyclic group along with a point representation
|
||||
/// * `Group`: a finite cyclic group along with a point representation, along
|
||||
/// with an extension trait PasswordToCurve that allows some customization on
|
||||
/// how to hash a password to a curve point. See `group::Group` and
|
||||
/// `map_to_curve::GroupWithMapToCurve`.
|
||||
/// * `KeyFormat`: a keypair type composed of public and private components
|
||||
/// * `SlowHash`: a slow hashing function, typically used for password hashing
|
||||
pub trait CipherSuite {
|
||||
type Digest: HkdfDigest;
|
||||
type Group: Group<ScalarLen = U32, UniformBytesLen = <Self::Digest as FixedOutput>::OutputSize>;
|
||||
type Group: GroupWithMapToCurve;
|
||||
type KeyFormat: KeyPair<Repr = Key> + PartialEq;
|
||||
type SlowHash: SlowHash;
|
||||
|
||||
|
||||
+4
-10
@@ -21,7 +21,6 @@
|
||||
//! use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! struct Default;
|
||||
//! impl CipherSuite for Default {
|
||||
//! type Digest = sha2::Sha512;
|
||||
//! type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -42,7 +41,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -74,7 +72,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -103,7 +100,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -135,7 +131,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -169,7 +164,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -211,7 +205,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -240,7 +233,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -284,7 +276,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -340,7 +331,6 @@
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Digest = sha2::Sha512;
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -390,9 +380,13 @@ pub mod opaque;
|
||||
|
||||
pub mod ciphersuite;
|
||||
mod envelope;
|
||||
|
||||
mod group;
|
||||
mod map_to_curve;
|
||||
|
||||
mod key_exchange;
|
||||
pub mod keypair;
|
||||
|
||||
mod oprf;
|
||||
pub mod slow_hash;
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use crate::group::Group;
|
||||
use curve25519_dalek::{edwards::EdwardsPoint, ristretto::RistrettoPoint};
|
||||
|
||||
use generic_array::GenericArray;
|
||||
use hkdf::Hkdf;
|
||||
|
||||
pub trait GroupWithMapToCurve: Group {
|
||||
fn map_to_curve(password: &[u8], pepper: Option<&[u8]>) -> Self;
|
||||
}
|
||||
|
||||
impl GroupWithMapToCurve for RistrettoPoint {
|
||||
fn map_to_curve(password: &[u8], pepper: Option<&[u8]>) -> Self {
|
||||
let (hashed_input, _) = Hkdf::<sha2::Sha512>::extract(pepper, password);
|
||||
<Self as Group>::hash_to_curve(GenericArray::from_slice(&hashed_input))
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupWithMapToCurve for EdwardsPoint {
|
||||
fn map_to_curve(password: &[u8], pepper: Option<&[u8]>) -> Self {
|
||||
let (hashed_input, _) = Hkdf::<sha2::Sha256>::extract(pepper, password);
|
||||
<Self as Group>::hash_to_curve(GenericArray::from_slice(&hashed_input))
|
||||
}
|
||||
}
|
||||
+2
-14
@@ -290,7 +290,6 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
/// struct Default;
|
||||
/// impl CipherSuite for Default {
|
||||
/// type Digest = sha2::Sha512;
|
||||
/// type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
/// type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -307,11 +306,7 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
let OprfClientBytes {
|
||||
alpha,
|
||||
blinding_factor,
|
||||
} = oprf::generate_oprf1::<R, CS::Digest, CS::Group>(
|
||||
&password,
|
||||
pepper,
|
||||
blinding_factor_rng,
|
||||
)?;
|
||||
} = oprf::generate_oprf1::<R, CS::Group>(&password, pepper, blinding_factor_rng)?;
|
||||
|
||||
Ok((
|
||||
RegisterFirstMessage::<CS::Group> { alpha },
|
||||
@@ -345,7 +340,6 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
/// struct Default;
|
||||
/// impl CipherSuite for Default {
|
||||
/// type Digest = sha2::Sha512;
|
||||
/// type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
/// type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -509,7 +503,6 @@ where
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
/// struct Default;
|
||||
/// impl CipherSuite for Default {
|
||||
/// type Digest = sha2::Sha512;
|
||||
/// type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
/// type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -556,7 +549,6 @@ where
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
/// struct Default;
|
||||
/// impl CipherSuite for Default {
|
||||
/// type Digest = sha2::Sha512;
|
||||
/// type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
/// type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -645,7 +637,6 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
/// struct Default;
|
||||
/// impl CipherSuite for Default {
|
||||
/// type Digest = sha2::Sha512;
|
||||
/// type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
/// type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -662,7 +653,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
let OprfClientBytes {
|
||||
alpha,
|
||||
blinding_factor,
|
||||
} = oprf::generate_oprf1::<R, CS::Digest, CS::Group>(&password, pepper, rng)?;
|
||||
} = oprf::generate_oprf1::<R, CS::Group>(&password, pepper, rng)?;
|
||||
|
||||
let (ke1_state, ke1_message) =
|
||||
generate_ke1::<_, CS::KeyFormat>(alpha.to_arr().to_vec(), rng)?;
|
||||
@@ -697,7 +688,6 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
/// struct Default;
|
||||
/// impl CipherSuite for Default {
|
||||
/// type Digest = sha2::Sha512;
|
||||
/// type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
/// type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -793,7 +783,6 @@ impl ServerLogin {
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
/// struct Default;
|
||||
/// impl CipherSuite for Default {
|
||||
/// type Digest = sha2::Sha512;
|
||||
/// type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
/// type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -863,7 +852,6 @@ impl ServerLogin {
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
/// struct Default;
|
||||
/// impl CipherSuite for Default {
|
||||
/// type Digest = sha2::Sha512;
|
||||
/// type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
/// type KeyFormat = opaque_ke::keypair::X25519KeyPair;
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
|
||||
+7
-31
@@ -3,9 +3,8 @@
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
use crate::{errors::InternalPakeError, group::Group};
|
||||
use digest::{BlockInput, FixedOutput, Reset, Update};
|
||||
use generic_array::{typenum::U32, ArrayLength, GenericArray};
|
||||
use crate::{errors::InternalPakeError, group::Group, map_to_curve::GroupWithMapToCurve};
|
||||
use generic_array::{typenum::U32, GenericArray};
|
||||
use hkdf::Hkdf;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
@@ -14,41 +13,18 @@ pub(crate) struct OprfClientBytes<Grp: Group> {
|
||||
pub(crate) blinding_factor: Grp::Scalar,
|
||||
}
|
||||
|
||||
/// The `HkDFDigest` trait specifies the interface required for a parameter of `hkdf::Hkdf`.
|
||||
///
|
||||
/// It's a convenience wrapper around [`Blockinput`], [`Update`], [`FixedOutput`], [`Reset`],
|
||||
/// [`Clone`], and [`Default`] traits.
|
||||
pub trait HkdfDigest: Update + BlockInput + FixedOutput + Reset + Default + Clone
|
||||
where
|
||||
Self::BlockSize: ArrayLength<u8>,
|
||||
Self::OutputSize: ArrayLength<u8>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T> HkdfDigest for T
|
||||
where
|
||||
T: Update + BlockInput + FixedOutput + Reset + Default + Clone,
|
||||
T::BlockSize: ArrayLength<u8>,
|
||||
T::OutputSize: ArrayLength<u8>,
|
||||
{
|
||||
}
|
||||
|
||||
/// Computes the first step for the multiplicative blinding version of DH-OPRF. This
|
||||
/// message is sent from the client (who holds the input) to the server (who holds the OPRF key).
|
||||
/// The client can also pass in an optional "pepper" string to be mixed in with the input through
|
||||
/// an HKDF computation.
|
||||
pub(crate) fn generate_oprf1<
|
||||
R: RngCore + CryptoRng,
|
||||
D: HkdfDigest,
|
||||
G: Group<UniformBytesLen = D::OutputSize>,
|
||||
>(
|
||||
pub(crate) fn generate_oprf1<R: RngCore + CryptoRng, G: GroupWithMapToCurve>(
|
||||
input: &[u8],
|
||||
pepper: Option<&[u8]>,
|
||||
blinding_factor_rng: &mut R,
|
||||
) -> Result<OprfClientBytes<G>, InternalPakeError> {
|
||||
let (hashed_input, _) = Hkdf::<D>::extract(pepper, &input);
|
||||
let mapped_point = G::map_to_curve(input, pepper);
|
||||
let blinding_factor = G::random_scalar(blinding_factor_rng);
|
||||
let alpha = G::hash_to_curve(GenericArray::from_slice(&hashed_input)) * &blinding_factor;
|
||||
let alpha = mapped_point * &blinding_factor;
|
||||
Ok(OprfClientBytes {
|
||||
alpha,
|
||||
blinding_factor,
|
||||
@@ -112,7 +88,7 @@ mod tests {
|
||||
let OprfClientBytes {
|
||||
alpha,
|
||||
blinding_factor,
|
||||
} = generate_oprf1::<_, Sha512, RistrettoPoint>(&input[..], None, &mut rng)?;
|
||||
} = generate_oprf1::<_, RistrettoPoint>(&input[..], None, &mut rng)?;
|
||||
let salt_bytes = arr![
|
||||
u8; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||
@@ -133,7 +109,7 @@ mod tests {
|
||||
let OprfClientBytes {
|
||||
alpha,
|
||||
blinding_factor,
|
||||
} = generate_oprf1::<_, Sha512, RistrettoPoint>(&input, None, &mut rng).unwrap();
|
||||
} = generate_oprf1::<_, RistrettoPoint>(&input, None, &mut rng).unwrap();
|
||||
let res = generate_oprf3::<RistrettoPoint>(&input, alpha, &blinding_factor).unwrap();
|
||||
|
||||
let (hashed_input, _) = Hkdf::<Sha512>::extract(None, &input);
|
||||
|
||||
@@ -23,7 +23,6 @@ use std::convert::TryFrom;
|
||||
|
||||
struct X255193dhNoSlowHash;
|
||||
impl CipherSuite for X255193dhNoSlowHash {
|
||||
type Digest = sha2::Sha256;
|
||||
type Group = EdwardsPoint;
|
||||
type KeyFormat = X25519KeyPair;
|
||||
type SlowHash = NoOpHash;
|
||||
@@ -248,13 +247,14 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
)
|
||||
.unwrap();
|
||||
let r1_bytes = r1.to_bytes().to_vec();
|
||||
let blinding_factor_bytes = *CS::Group::scalar_as_bytes(&client_registration.blinding_factor);
|
||||
let blinding_factor_bytes =
|
||||
CS::Group::scalar_as_bytes(&client_registration.blinding_factor).clone();
|
||||
let client_registration_state = client_registration.to_bytes().to_vec();
|
||||
|
||||
let mut oprf_key_rng = CycleRng::new(oprf_key_raw.to_vec());
|
||||
let (r2, server_registration) = ServerRegistration::<CS>::start(r1, &mut oprf_key_rng).unwrap();
|
||||
let r2_bytes = r2.to_bytes().to_vec();
|
||||
let oprf_key_bytes = *CS::Group::scalar_as_bytes(&server_registration.oprf_key);
|
||||
let oprf_key_bytes = CS::Group::scalar_as_bytes(&server_registration.oprf_key).clone();
|
||||
let server_registration_state = server_registration.to_bytes().to_vec();
|
||||
|
||||
let mut client_s_sk_and_nonce: Vec<u8> = Vec::new();
|
||||
|
||||
@@ -21,7 +21,6 @@ use std::convert::TryFrom;
|
||||
|
||||
struct Default;
|
||||
impl CipherSuite for Default {
|
||||
type Digest = sha2::Sha512;
|
||||
type Group = RistrettoPoint;
|
||||
type KeyFormat = crate::keypair::X25519KeyPair;
|
||||
type SlowHash = crate::slow_hash::NoOpHash;
|
||||
|
||||
Reference in New Issue
Block a user