Separate AKE from OPRF take 2 (#222)
* Separate AKE from OPRF Introduce X25519 implementation * Rename `AkeGroup` to `KeGroup` and `Group` to `OprfGroup` * Add documentation to "Overview"
This commit is contained in:
@@ -44,7 +44,8 @@ use opaque_ke::{
|
||||
#[allow(dead_code)]
|
||||
struct Default;
|
||||
impl CipherSuite for Default {
|
||||
type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
type Hash = sha2::Sha512;
|
||||
type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
|
||||
@@ -37,7 +37,8 @@ use opaque_ke::{
|
||||
#[allow(dead_code)]
|
||||
struct Default;
|
||||
impl CipherSuite for Default {
|
||||
type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
type Hash = sha2::Sha512;
|
||||
type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
|
||||
+6
-3
@@ -8,9 +8,10 @@
|
||||
use crate::{group::Group, hash::Hash, key_exchange::traits::KeyExchange, slow_hash::SlowHash};
|
||||
|
||||
/// Configures the underlying primitives used in OPAQUE
|
||||
/// * `Group`: a finite cyclic group along with a point representation, along
|
||||
/// * `OprfGroup`: 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`.
|
||||
/// * `KeGroup`: A `Group` used for the `KeyExchange`.
|
||||
/// * `KeyExchange`: The key exchange protocol to use in the login step
|
||||
/// * `Hash`: The main hashing function to use
|
||||
/// * `SlowHash`: A slow hashing function, typically used for password hashing
|
||||
@@ -18,9 +19,11 @@ pub trait CipherSuite {
|
||||
/// 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`.
|
||||
type Group: Group;
|
||||
type OprfGroup: Group;
|
||||
/// A `Group` used for the `KeyExchange`.
|
||||
type KeGroup: Group;
|
||||
/// A key exchange protocol
|
||||
type KeyExchange: KeyExchange<Self::Hash, Self::Group>;
|
||||
type KeyExchange: KeyExchange<Self::Hash, Self::KeGroup>;
|
||||
/// The main hash function use (for HKDF computations and hashing transcripts)
|
||||
type Hash: Hash;
|
||||
/// A slow hashing function, typically used for password hashing
|
||||
|
||||
+19
-15
@@ -31,15 +31,17 @@ const NONCE_LEN: usize = 32;
|
||||
fn build_inner_envelope_internal<CS: CipherSuite>(
|
||||
random_pwd: &[u8],
|
||||
nonce: &[u8],
|
||||
) -> Result<PublicKey<CS::Group>, ProtocolError> {
|
||||
) -> Result<PublicKey<CS::KeGroup>, ProtocolError> {
|
||||
let h = Hkdf::<CS::Hash>::new(None, random_pwd);
|
||||
let mut keypair_seed = vec![0u8; <PrivateKey<CS::Group> as SizedBytes>::Len::to_usize()];
|
||||
let mut keypair_seed = vec![0u8; <PrivateKey<CS::KeGroup> as SizedBytes>::Len::to_usize()];
|
||||
h.expand(&[nonce, STR_PRIVATE_KEY].concat(), &mut keypair_seed)
|
||||
.map_err(|_| InternalPakeError::HkdfError)?;
|
||||
let client_static_keypair =
|
||||
KeyPair::<CS::Group>::from_private_key_slice(&CS::Group::scalar_as_bytes(
|
||||
CS::Group::hash_to_scalar::<CS::Hash>(&keypair_seed[..], STR_OPAQUE_HASH_TO_SCALAR)?,
|
||||
))?;
|
||||
let client_static_keypair = KeyPair::<CS::KeGroup>::from_private_key_slice(
|
||||
&CS::OprfGroup::scalar_as_bytes(CS::OprfGroup::hash_to_scalar::<CS::Hash>(
|
||||
&keypair_seed[..],
|
||||
STR_OPAQUE_HASH_TO_SCALAR,
|
||||
)?),
|
||||
)?;
|
||||
|
||||
Ok(client_static_keypair.public().clone())
|
||||
}
|
||||
@@ -47,15 +49,17 @@ fn build_inner_envelope_internal<CS: CipherSuite>(
|
||||
fn recover_keys_internal<CS: CipherSuite>(
|
||||
random_pwd: &[u8],
|
||||
nonce: &[u8],
|
||||
) -> Result<KeyPair<CS::Group>, ProtocolError> {
|
||||
) -> Result<KeyPair<CS::KeGroup>, ProtocolError> {
|
||||
let h = Hkdf::<CS::Hash>::new(None, random_pwd);
|
||||
let mut keypair_seed = vec![0u8; <PrivateKey<CS::Group> as SizedBytes>::Len::to_usize()];
|
||||
let mut keypair_seed = vec![0u8; <PrivateKey<CS::KeGroup> as SizedBytes>::Len::to_usize()];
|
||||
h.expand(&[nonce, STR_PRIVATE_KEY].concat(), &mut keypair_seed)
|
||||
.map_err(|_| InternalPakeError::HkdfError)?;
|
||||
let client_static_keypair =
|
||||
KeyPair::<CS::Group>::from_private_key_slice(&CS::Group::scalar_as_bytes(
|
||||
CS::Group::hash_to_scalar::<CS::Hash>(&keypair_seed[..], STR_OPAQUE_HASH_TO_SCALAR)?,
|
||||
))?;
|
||||
let client_static_keypair = KeyPair::<CS::KeGroup>::from_private_key_slice(
|
||||
&CS::OprfGroup::scalar_as_bytes(CS::OprfGroup::hash_to_scalar::<CS::Hash>(
|
||||
&keypair_seed[..],
|
||||
STR_OPAQUE_HASH_TO_SCALAR,
|
||||
)?),
|
||||
)?;
|
||||
|
||||
Ok(client_static_keypair)
|
||||
}
|
||||
@@ -110,7 +114,7 @@ impl_debug_eq_hash_for!(struct Envelope<CS: CipherSuite>, [mode, nonce, hmac]);
|
||||
// key. This key is also used to derive the export_key parameter, which is technically
|
||||
// unrelated to the envelope's encrypted and authenticated contents.
|
||||
pub(crate) struct OpenedEnvelope<CS: CipherSuite> {
|
||||
pub(crate) client_static_keypair: KeyPair<CS::Group>,
|
||||
pub(crate) client_static_keypair: KeyPair<CS::KeGroup>,
|
||||
pub(crate) export_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||
pub(crate) id_u: Vec<u8>,
|
||||
pub(crate) id_s: Vec<u8>,
|
||||
@@ -134,13 +138,13 @@ type SealRawResult<CS> = (
|
||||
#[cfg(not(test))]
|
||||
type SealResult<CS> = (
|
||||
Envelope<CS>,
|
||||
PublicKey<<CS as CipherSuite>::Group>,
|
||||
PublicKey<<CS as CipherSuite>::KeGroup>,
|
||||
GenericArray<u8, <<CS as CipherSuite>::Hash as Digest>::OutputSize>,
|
||||
);
|
||||
#[cfg(test)]
|
||||
type SealResult<CS> = (
|
||||
Envelope<CS>,
|
||||
PublicKey<<CS as CipherSuite>::Group>,
|
||||
PublicKey<<CS as CipherSuite>::KeGroup>,
|
||||
GenericArray<u8, <<CS as CipherSuite>::Hash as Digest>::OutputSize>,
|
||||
Vec<u8>,
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ mod expand;
|
||||
#[cfg(feature = "p256")]
|
||||
pub(crate) mod p256;
|
||||
mod ristretto;
|
||||
mod x25519;
|
||||
|
||||
use crate::errors::{InternalPakeError, ProtocolError};
|
||||
use crate::hash::Hash;
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
//
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
use super::Group;
|
||||
use crate::errors::{InternalPakeError, ProtocolError};
|
||||
use crate::hash::Hash;
|
||||
use curve25519_dalek::{constants::X25519_BASEPOINT, montgomery::MontgomeryPoint, scalar::Scalar};
|
||||
use generic_array::{typenum::U32, GenericArray};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
|
||||
/// The implementation of such a subgroup for Ristretto
|
||||
impl Group for MontgomeryPoint {
|
||||
const SUITE_ID: usize = 0xFFFF;
|
||||
|
||||
fn map_to_curve<H: Hash>(_msg: &[u8], _dst: &[u8]) -> Result<Self, ProtocolError> {
|
||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
||||
}
|
||||
|
||||
fn hash_to_scalar<H: Hash>(_input: &[u8], _dst: &[u8]) -> Result<Self::Scalar, ProtocolError> {
|
||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
||||
}
|
||||
|
||||
type Scalar = Scalar;
|
||||
type ScalarLen = U32;
|
||||
fn from_scalar_slice(
|
||||
scalar_bits: &GenericArray<u8, Self::ScalarLen>,
|
||||
) -> Result<Self::Scalar, InternalPakeError> {
|
||||
Ok(Scalar::from_bytes_mod_order(*scalar_bits.as_ref()))
|
||||
}
|
||||
fn random_nonzero_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
|
||||
loop {
|
||||
let scalar = {
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let mut scalar_bytes = [0u8; 64];
|
||||
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() {
|
||||
break scalar;
|
||||
}
|
||||
}
|
||||
}
|
||||
fn scalar_as_bytes(scalar: Self::Scalar) -> GenericArray<u8, Self::ScalarLen> {
|
||||
scalar.to_bytes().into()
|
||||
}
|
||||
fn scalar_invert(_scalar: &Self::Scalar) -> Self::Scalar {
|
||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
||||
}
|
||||
|
||||
// The byte length necessary to represent group elements
|
||||
type ElemLen = U32;
|
||||
fn from_element_slice(
|
||||
element_bits: &GenericArray<u8, Self::ElemLen>,
|
||||
) -> Result<Self, InternalPakeError> {
|
||||
Ok(Self(*element_bits.as_ref()))
|
||||
}
|
||||
// serialization of a group element
|
||||
fn to_arr(&self) -> GenericArray<u8, Self::ElemLen> {
|
||||
self.to_bytes().into()
|
||||
}
|
||||
|
||||
fn base_point() -> Self {
|
||||
X25519_BASEPOINT
|
||||
}
|
||||
|
||||
fn mult_by_slice(&self, scalar: &GenericArray<u8, Self::ScalarLen>) -> Self {
|
||||
self * Scalar::from_bits(*scalar.as_ref())
|
||||
}
|
||||
|
||||
/// Returns if the group element is equal to the identity (1)
|
||||
fn is_identity(&self) -> bool {
|
||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
||||
}
|
||||
|
||||
fn ct_equal(&self, _other: &Self) -> bool {
|
||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() -> Result<(), ProtocolError> {
|
||||
use crate::{
|
||||
errors::PakeError, key_exchange::tripledh::TripleDH, slow_hash::NoOpHash, CipherSuite,
|
||||
ClientLogin, ClientLoginFinishParameters, ClientLoginFinishResult, ClientLoginStartResult,
|
||||
ClientRegistration, ClientRegistrationFinishParameters, ClientRegistrationFinishResult,
|
||||
ClientRegistrationStartResult, ServerLogin, ServerLoginStartParameters,
|
||||
ServerLoginStartResult, ServerRegistration, ServerSetup,
|
||||
};
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
struct X25519Sha512NoSlowHash;
|
||||
impl CipherSuite for X25519Sha512NoSlowHash {
|
||||
type OprfGroup = RistrettoPoint;
|
||||
type KeGroup = MontgomeryPoint;
|
||||
type KeyExchange = TripleDH;
|
||||
type Hash = sha2::Sha512;
|
||||
type SlowHash = NoOpHash;
|
||||
}
|
||||
|
||||
const PASSWORD: &[u8] = b"1234";
|
||||
|
||||
let server_setup = ServerSetup::<X25519Sha512NoSlowHash>::new(&mut OsRng);
|
||||
|
||||
let ClientRegistrationStartResult {
|
||||
message,
|
||||
state: client,
|
||||
} = ClientRegistration::start(&mut OsRng, PASSWORD)?;
|
||||
let message = ServerRegistration::start(&server_setup, message, &[])?.message;
|
||||
let ClientRegistrationFinishResult {
|
||||
message,
|
||||
export_key: register_export_key,
|
||||
..
|
||||
} = client.finish(
|
||||
&mut OsRng,
|
||||
message,
|
||||
ClientRegistrationFinishParameters::Default,
|
||||
)?;
|
||||
let server_registration = ServerRegistration::finish(message);
|
||||
|
||||
let ClientLoginStartResult {
|
||||
message,
|
||||
state: client,
|
||||
} = ClientLogin::start(&mut OsRng, PASSWORD)?;
|
||||
let ServerLoginStartResult {
|
||||
message,
|
||||
state: server,
|
||||
..
|
||||
} = ServerLogin::start(
|
||||
&mut OsRng,
|
||||
&server_setup,
|
||||
Some(server_registration),
|
||||
message,
|
||||
&[],
|
||||
ServerLoginStartParameters::default(),
|
||||
)?;
|
||||
let ClientLoginFinishResult {
|
||||
message,
|
||||
session_key: client_session_key,
|
||||
export_key: login_export_key,
|
||||
..
|
||||
} = client.finish(message, ClientLoginFinishParameters::Default)?;
|
||||
let server_session_key = server.finish(message)?.session_key;
|
||||
|
||||
assert_eq!(register_export_key, login_export_key);
|
||||
assert_eq!(client_session_key, server_session_key);
|
||||
|
||||
let ClientLoginStartResult {
|
||||
message,
|
||||
state: client,
|
||||
} = ClientLogin::start(&mut OsRng, PASSWORD)?;
|
||||
let ServerLoginStartResult { message, .. } = ServerLogin::start(
|
||||
&mut OsRng,
|
||||
&server_setup,
|
||||
None,
|
||||
message,
|
||||
&[],
|
||||
ServerLoginStartParameters::default(),
|
||||
)?;
|
||||
|
||||
assert!(matches!(
|
||||
client.finish(message, ClientLoginFinishParameters::Default),
|
||||
Err(ProtocolError::VerificationError(
|
||||
PakeError::InvalidLoginError
|
||||
))
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -411,7 +411,7 @@ impl<G: Group, HashLen: ArrayLength<u8>> FromBytes for Ke2Message<G, HashLen> {
|
||||
)?;
|
||||
|
||||
// Check the public key bytes
|
||||
let server_e_pk = KeyPair::<CS::Group>::check_public_key(PublicKey::from_bytes(
|
||||
let server_e_pk = KeyPair::<CS::OprfGroup>::check_public_key(PublicKey::from_bytes(
|
||||
&unchecked_server_e_pk[..key_len],
|
||||
)?)?;
|
||||
|
||||
|
||||
+2
-1
@@ -462,7 +462,8 @@ mod tests {
|
||||
struct Default;
|
||||
|
||||
impl CipherSuite for Default {
|
||||
type Group = RistrettoPoint;
|
||||
type OprfGroup = RistrettoPoint;
|
||||
type KeGroup = RistrettoPoint;
|
||||
type KeyExchange = crate::key_exchange::tripledh::TripleDH;
|
||||
type Hash = sha2::Sha512;
|
||||
type SlowHash = crate::slow_hash::NoOpHash;
|
||||
|
||||
+35
-17
@@ -16,7 +16,9 @@
|
||||
//!
|
||||
//! OPAQUE is a protocol between a client and a server. They must first agree on a collection of primitives
|
||||
//! to be kept consistent throughout protocol execution. These include:
|
||||
//! * a finite cyclic group along with a point representation,
|
||||
//! * a finite cyclic group along with a point representation
|
||||
//! * for the OPRF and
|
||||
//! * for the key exchange
|
||||
//! * a key exchange protocol,
|
||||
//! * a hashing function, and
|
||||
//! * a slow hashing function.
|
||||
@@ -26,7 +28,8 @@
|
||||
//! use opaque_ke::CipherSuite;
|
||||
//! struct Default;
|
||||
//! impl CipherSuite for Default {
|
||||
//! type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! type Hash = sha2::Sha512;
|
||||
//! type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -47,7 +50,8 @@
|
||||
//! # use opaque_ke::ServerSetup;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -79,7 +83,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -109,7 +114,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -146,7 +152,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -184,7 +191,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -226,7 +234,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -259,7 +268,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -312,7 +322,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -357,7 +368,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -432,7 +444,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -509,7 +522,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -574,7 +588,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -611,7 +626,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -660,7 +676,8 @@
|
||||
//! # use opaque_ke::CipherSuite;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
@@ -737,7 +754,8 @@
|
||||
//! # use zeroize::Zeroize;
|
||||
//! # struct Default;
|
||||
//! # impl CipherSuite for Default {
|
||||
//! # type Group = RistrettoPoint;
|
||||
//! # type OprfGroup = RistrettoPoint;
|
||||
//! # type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
|
||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||
//! # type Hash = sha2::Sha512;
|
||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
|
||||
+38
-38
@@ -28,13 +28,13 @@ use rand::{CryptoRng, RngCore};
|
||||
/// The message sent by the client to the server, to initiate registration
|
||||
pub struct RegistrationRequest<CS: CipherSuite> {
|
||||
/// blinded password information
|
||||
pub(crate) alpha: CS::Group,
|
||||
pub(crate) alpha: CS::OprfGroup,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> RegistrationRequest<CS> {
|
||||
/// Only used for testing purposes
|
||||
#[cfg(test)]
|
||||
pub fn get_alpha_for_testing(&self) -> CS::Group {
|
||||
pub fn get_alpha_for_testing(&self) -> CS::OprfGroup {
|
||||
self.alpha
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ impl<CS: CipherSuite> Clone for RegistrationRequest<CS> {
|
||||
}
|
||||
}
|
||||
|
||||
impl_debug_eq_hash_for!(struct RegistrationRequest<CS: CipherSuite>, [alpha], [CS::Group]);
|
||||
impl_debug_eq_hash_for!(struct RegistrationRequest<CS: CipherSuite>, [alpha], [CS::OprfGroup]);
|
||||
|
||||
impl<CS: CipherSuite> RegistrationRequest<CS> {
|
||||
/// Serialization into bytes
|
||||
@@ -56,12 +56,12 @@ impl<CS: CipherSuite> RegistrationRequest<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
|
||||
let checked_slice = check_slice_size(input, elem_len, "first_message_bytes")?;
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
let arr = GenericArray::from_slice(checked_slice);
|
||||
let alpha = CS::Group::from_element_slice(arr)?;
|
||||
let alpha = CS::OprfGroup::from_element_slice(arr)?;
|
||||
|
||||
// Throw an error if the identity group element is encountered
|
||||
if alpha.is_identity() {
|
||||
@@ -77,9 +77,9 @@ impl_serialize_and_deserialize_for!(RegistrationRequest);
|
||||
/// registration attempt
|
||||
pub struct RegistrationResponse<CS: CipherSuite> {
|
||||
/// The server's oprf output
|
||||
pub(crate) beta: CS::Group,
|
||||
pub(crate) beta: CS::OprfGroup,
|
||||
/// Server's static public key
|
||||
pub(crate) server_s_pk: PublicKey<CS::Group>,
|
||||
pub(crate) server_s_pk: PublicKey<CS::KeGroup>,
|
||||
}
|
||||
|
||||
// Cannot be derived because it would require for CS to be Clone.
|
||||
@@ -95,7 +95,7 @@ impl<CS: CipherSuite> Clone for RegistrationResponse<CS> {
|
||||
impl_debug_eq_hash_for!(
|
||||
struct RegistrationResponse<CS: CipherSuite>,
|
||||
[beta, server_s_pk],
|
||||
[CS::Group],
|
||||
[CS::OprfGroup],
|
||||
);
|
||||
|
||||
impl<CS: CipherSuite> RegistrationResponse<CS> {
|
||||
@@ -106,15 +106,15 @@ impl<CS: CipherSuite> RegistrationResponse<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||
let key_len = <PublicKey<CS::Group> as SizedBytes>::Len::to_usize();
|
||||
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
|
||||
let key_len = <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
|
||||
let checked_slice =
|
||||
check_slice_size(input, elem_len + key_len, "registration_response_bytes")?;
|
||||
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
let arr = GenericArray::from_slice(&checked_slice[..elem_len]);
|
||||
let beta = CS::Group::from_element_slice(arr)?;
|
||||
let beta = CS::OprfGroup::from_element_slice(arr)?;
|
||||
|
||||
// Throw an error if the identity group element is encountered
|
||||
if beta.is_identity() {
|
||||
@@ -122,7 +122,7 @@ impl<CS: CipherSuite> RegistrationResponse<CS> {
|
||||
}
|
||||
|
||||
// Ensure that public key is valid
|
||||
let server_s_pk = KeyPair::<CS::Group>::check_public_key(PublicKey::from_bytes(
|
||||
let server_s_pk = KeyPair::<CS::KeGroup>::check_public_key(PublicKey::from_bytes(
|
||||
&checked_slice[elem_len..],
|
||||
)?)?;
|
||||
|
||||
@@ -132,7 +132,7 @@ impl<CS: CipherSuite> RegistrationResponse<CS> {
|
||||
#[cfg(test)]
|
||||
/// Only used for tests, where we can set the beta value to test for the reflection
|
||||
/// error case
|
||||
pub fn set_beta_for_testing(&self, new_beta: CS::Group) -> Self {
|
||||
pub fn set_beta_for_testing(&self, new_beta: CS::OprfGroup) -> Self {
|
||||
Self {
|
||||
beta: new_beta,
|
||||
server_s_pk: self.server_s_pk.clone(),
|
||||
@@ -151,7 +151,7 @@ pub struct RegistrationUpload<CS: CipherSuite> {
|
||||
/// The masking key used to mask the envelope
|
||||
pub(crate) masking_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||
/// The user's public key
|
||||
pub(crate) client_s_pk: PublicKey<CS::Group>,
|
||||
pub(crate) client_s_pk: PublicKey<CS::KeGroup>,
|
||||
}
|
||||
|
||||
impl_clone_for!(
|
||||
@@ -176,7 +176,7 @@ impl<CS: CipherSuite> RegistrationUpload<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let key_len = <PublicKey<CS::Group> as SizedBytes>::Len::to_usize();
|
||||
let key_len = <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
|
||||
let hash_len = <CS::Hash as Digest>::OutputSize::to_usize();
|
||||
let checked_slice =
|
||||
check_slice_size_atleast(input, key_len + hash_len, "registration_upload_bytes")?;
|
||||
@@ -186,14 +186,14 @@ impl<CS: CipherSuite> RegistrationUpload<CS> {
|
||||
masking_key: GenericArray::clone_from_slice(
|
||||
&checked_slice[key_len..key_len + hash_len],
|
||||
),
|
||||
client_s_pk: KeyPair::<CS::Group>::check_public_key(PublicKey::from_bytes(
|
||||
client_s_pk: KeyPair::<CS::KeGroup>::check_public_key(PublicKey::from_bytes(
|
||||
&checked_slice[..key_len],
|
||||
)?)?,
|
||||
})
|
||||
}
|
||||
|
||||
// Creates a dummy instance used for faking a [CredentialResponse]
|
||||
pub(crate) fn dummy<R: RngCore + CryptoRng, S: SecretKey<CS::Group>>(
|
||||
pub(crate) fn dummy<R: RngCore + CryptoRng, S: SecretKey<CS::KeGroup>>(
|
||||
rng: &mut R,
|
||||
server_setup: &ServerSetup<CS, S>,
|
||||
) -> Self {
|
||||
@@ -213,8 +213,8 @@ impl_serialize_and_deserialize_for!(RegistrationUpload);
|
||||
/// The message sent by the user to the server, to initiate registration
|
||||
pub struct CredentialRequest<CS: CipherSuite> {
|
||||
/// blinded password information
|
||||
pub(crate) alpha: CS::Group,
|
||||
pub(crate) ke1_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1Message,
|
||||
pub(crate) alpha: CS::OprfGroup,
|
||||
pub(crate) ke1_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE1Message,
|
||||
}
|
||||
|
||||
// Cannot be derived because it would require for CS to be Clone.
|
||||
@@ -231,8 +231,8 @@ impl_debug_eq_hash_for!(
|
||||
struct CredentialRequest<CS: CipherSuite>,
|
||||
[alpha, ke1_message],
|
||||
[
|
||||
CS::Group,
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1Message
|
||||
CS::OprfGroup,
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE1Message
|
||||
],
|
||||
);
|
||||
|
||||
@@ -244,14 +244,14 @@ impl<CS: CipherSuite> CredentialRequest<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
|
||||
|
||||
let checked_slice = check_slice_size_atleast(input, elem_len, "login_first_message_bytes")?;
|
||||
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
let arr = GenericArray::from_slice(&checked_slice[..elem_len]);
|
||||
let alpha = CS::Group::from_element_slice(arr)?;
|
||||
let alpha = CS::OprfGroup::from_element_slice(arr)?;
|
||||
|
||||
// Throw an error if the identity group element is encountered
|
||||
if alpha.is_identity() {
|
||||
@@ -259,7 +259,7 @@ impl<CS: CipherSuite> CredentialRequest<CS> {
|
||||
}
|
||||
|
||||
let ke1_message =
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1Message::from_bytes::<CS>(
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE1Message::from_bytes::<CS>(
|
||||
&checked_slice[elem_len..],
|
||||
)?;
|
||||
|
||||
@@ -268,7 +268,7 @@ impl<CS: CipherSuite> CredentialRequest<CS> {
|
||||
|
||||
/// Only used for testing purposes
|
||||
#[cfg(test)]
|
||||
pub fn get_alpha_for_testing(&self) -> CS::Group {
|
||||
pub fn get_alpha_for_testing(&self) -> CS::OprfGroup {
|
||||
self.alpha
|
||||
}
|
||||
}
|
||||
@@ -279,10 +279,10 @@ impl_serialize_and_deserialize_for!(CredentialRequest);
|
||||
/// login attempt
|
||||
pub struct CredentialResponse<CS: CipherSuite> {
|
||||
/// the server's oprf output
|
||||
pub(crate) beta: CS::Group,
|
||||
pub(crate) beta: CS::OprfGroup,
|
||||
pub(crate) masking_nonce: Vec<u8>,
|
||||
pub(crate) masked_response: Vec<u8>,
|
||||
pub(crate) ke2_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2Message,
|
||||
pub(crate) ke2_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE2Message,
|
||||
}
|
||||
|
||||
// Cannot be derived because it would require for CS to be Clone.
|
||||
@@ -301,8 +301,8 @@ impl_debug_eq_hash_for!(
|
||||
struct CredentialResponse<CS: CipherSuite>,
|
||||
[beta, masking_nonce, masked_response, ke2_message],
|
||||
[
|
||||
CS::Group,
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2Message,
|
||||
CS::OprfGroup,
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE2Message,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -317,7 +317,7 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||
}
|
||||
|
||||
pub(crate) fn serialize_without_ke(
|
||||
beta: &CS::Group,
|
||||
beta: &CS::OprfGroup,
|
||||
masking_nonce: &[u8],
|
||||
masked_response: &[u8],
|
||||
) -> Vec<u8> {
|
||||
@@ -326,8 +326,8 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||
let key_len = <PublicKey<CS::Group> as SizedBytes>::Len::to_usize();
|
||||
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
|
||||
let key_len = <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
|
||||
let nonce_len: usize = 32;
|
||||
let envelope_len = Envelope::<CS>::len();
|
||||
let masked_response_len = key_len + envelope_len;
|
||||
@@ -343,7 +343,7 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||
// correct subgroup
|
||||
let beta_bytes = &checked_slice[..elem_len];
|
||||
let arr = GenericArray::from_slice(beta_bytes);
|
||||
let beta = CS::Group::from_element_slice(arr)?;
|
||||
let beta = CS::OprfGroup::from_element_slice(arr)?;
|
||||
|
||||
// Throw an error if the identity group element is encountered
|
||||
if beta.is_identity() {
|
||||
@@ -355,7 +355,7 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||
[elem_len + nonce_len..elem_len + nonce_len + masked_response_len]
|
||||
.to_vec();
|
||||
let ke2_message =
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2Message::from_bytes::<CS>(
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE2Message::from_bytes::<CS>(
|
||||
&checked_slice[elem_len + nonce_len + masked_response_len..],
|
||||
)?;
|
||||
|
||||
@@ -370,7 +370,7 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||
#[cfg(test)]
|
||||
/// Only used for tests, where we can set the beta value to test for the reflection
|
||||
/// error case
|
||||
pub fn set_beta_for_testing(&self, new_beta: CS::Group) -> Self {
|
||||
pub fn set_beta_for_testing(&self, new_beta: CS::OprfGroup) -> Self {
|
||||
Self {
|
||||
beta: new_beta,
|
||||
masking_nonce: self.masking_nonce.clone(),
|
||||
@@ -385,14 +385,14 @@ impl_serialize_and_deserialize_for!(CredentialResponse);
|
||||
/// The answer sent by the client to the server, upon reception of the
|
||||
/// sealed envelope
|
||||
pub struct CredentialFinalization<CS: CipherSuite> {
|
||||
pub(crate) ke3_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message,
|
||||
pub(crate) ke3_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE3Message,
|
||||
}
|
||||
|
||||
impl_clone_for!(struct CredentialFinalization<CS: CipherSuite>, [ke3_message]);
|
||||
impl_debug_eq_hash_for!(
|
||||
struct CredentialFinalization<CS: CipherSuite>,
|
||||
[ke3_message],
|
||||
[<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message],
|
||||
[<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE3Message],
|
||||
);
|
||||
|
||||
impl<CS: CipherSuite> CredentialFinalization<CS> {
|
||||
@@ -404,7 +404,7 @@ impl<CS: CipherSuite> CredentialFinalization<CS> {
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let ke3_message =
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message::from_bytes::<CS>(
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE3Message::from_bytes::<CS>(
|
||||
input,
|
||||
)?;
|
||||
Ok(Self { ke3_message })
|
||||
|
||||
+64
-59
@@ -40,32 +40,32 @@ const STR_OPAQUE_DERIVE_KEY_PAIR: &[u8] = b"OPAQUE-DeriveKeyPair";
|
||||
feature = "serialize",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound(
|
||||
deserialize = "KeyPair<CS::Group, S>: serde::Deserialize<'de>",
|
||||
serialize = "KeyPair<CS::Group, S>: serde::Serialize"
|
||||
deserialize = "KeyPair<CS::KeGroup, S>: serde::Deserialize<'de>",
|
||||
serialize = "KeyPair<CS::KeGroup, S>: serde::Serialize"
|
||||
))
|
||||
)]
|
||||
pub struct ServerSetup<
|
||||
CS: CipherSuite,
|
||||
S: SecretKey<CS::Group> = PrivateKey<<CS as CipherSuite>::Group>,
|
||||
S: SecretKey<CS::KeGroup> = PrivateKey<<CS as CipherSuite>::KeGroup>,
|
||||
> {
|
||||
oprf_seed: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||
keypair: KeyPair<CS::Group, S>,
|
||||
pub(crate) fake_keypair: KeyPair<CS::Group>,
|
||||
keypair: KeyPair<CS::KeGroup, S>,
|
||||
pub(crate) fake_keypair: KeyPair<CS::KeGroup>,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ServerSetup<CS, PrivateKey<CS::Group>> {
|
||||
impl<CS: CipherSuite> ServerSetup<CS, PrivateKey<CS::KeGroup>> {
|
||||
/// Generate a new instance of server setup
|
||||
pub fn new<R: CryptoRng + RngCore>(rng: &mut R) -> Self {
|
||||
let keypair = KeyPair::<CS::Group>::generate_random(rng);
|
||||
let keypair = KeyPair::<CS::KeGroup>::generate_random(rng);
|
||||
Self::new_with_key(rng, keypair)
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite, S: SecretKey<CS::Group>> ServerSetup<CS, S> {
|
||||
impl<CS: CipherSuite, S: SecretKey<CS::KeGroup>> ServerSetup<CS, S> {
|
||||
/// Create [`ServerSetup`] with the given keypair
|
||||
pub fn new_with_key<R: CryptoRng + RngCore>(
|
||||
rng: &mut R,
|
||||
keypair: KeyPair<CS::Group, S>,
|
||||
keypair: KeyPair<CS::KeGroup, S>,
|
||||
) -> Self {
|
||||
let mut seed = vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()];
|
||||
rng.fill_bytes(&mut seed);
|
||||
@@ -73,7 +73,7 @@ impl<CS: CipherSuite, S: SecretKey<CS::Group>> ServerSetup<CS, S> {
|
||||
Self {
|
||||
oprf_seed: GenericArray::clone_from_slice(&seed[..]),
|
||||
keypair,
|
||||
fake_keypair: KeyPair::<CS::Group>::generate_random(rng),
|
||||
fake_keypair: KeyPair::<CS::KeGroup>::generate_random(rng),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ impl<CS: CipherSuite, S: SecretKey<CS::Group>> ServerSetup<CS, S> {
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError<S::Error>> {
|
||||
let seed_len = <CS::Hash as Digest>::OutputSize::to_usize();
|
||||
let key_len = <PrivateKey<CS::Group> as SizedBytes>::Len::to_usize();
|
||||
let key_len = <PrivateKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
|
||||
let checked_slice = check_slice_size(input, seed_len + key_len + key_len, "server_setup")?;
|
||||
|
||||
Ok(Self {
|
||||
@@ -102,7 +102,7 @@ impl<CS: CipherSuite, S: SecretKey<CS::Group>> ServerSetup<CS, S> {
|
||||
}
|
||||
|
||||
/// Returns the keypair
|
||||
pub fn keypair(&self) -> &KeyPair<CS::Group, S> {
|
||||
pub fn keypair(&self) -> &KeyPair<CS::KeGroup, S> {
|
||||
&self.keypair
|
||||
}
|
||||
}
|
||||
@@ -122,16 +122,16 @@ impl_debug_eq_hash_for!(
|
||||
|
||||
/// The state elements the client holds to register itself
|
||||
pub struct ClientRegistration<CS: CipherSuite> {
|
||||
alpha: CS::Group,
|
||||
alpha: CS::OprfGroup,
|
||||
/// token containing the client's password and the blinding factor
|
||||
pub(crate) token: oprf::Token<CS::Group>,
|
||||
pub(crate) token: oprf::Token<CS::OprfGroup>,
|
||||
}
|
||||
|
||||
impl_clone_for!(struct ClientRegistration<CS: CipherSuite>, [token, alpha]);
|
||||
impl_debug_eq_hash_for!(
|
||||
struct ClientRegistration<CS: CipherSuite>,
|
||||
[token],
|
||||
[oprf::Token<CS::Group>],
|
||||
[oprf::Token<CS::OprfGroup>],
|
||||
);
|
||||
|
||||
impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
@@ -139,7 +139,7 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
[
|
||||
&self.alpha.to_arr().to_vec(),
|
||||
&CS::Group::scalar_as_bytes(self.token.blind)[..],
|
||||
&CS::OprfGroup::scalar_as_bytes(self.token.blind)[..],
|
||||
&self.token.data,
|
||||
]
|
||||
.concat()
|
||||
@@ -147,8 +147,8 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||
let scalar_len = <CS::Group as Group>::ScalarLen::to_usize();
|
||||
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
|
||||
let scalar_len = <CS::OprfGroup as Group>::ScalarLen::to_usize();
|
||||
let min_expected_len = elem_len + scalar_len;
|
||||
let checked_slice = (if input.len() <= min_expected_len {
|
||||
Err(InternalPakeError::SizeError {
|
||||
@@ -160,14 +160,15 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
Ok(input)
|
||||
})?;
|
||||
|
||||
let alpha =
|
||||
CS::Group::from_element_slice(GenericArray::from_slice(&checked_slice[..elem_len]))?;
|
||||
let alpha = CS::OprfGroup::from_element_slice(GenericArray::from_slice(
|
||||
&checked_slice[..elem_len],
|
||||
))?;
|
||||
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
let blinding_factor_bytes =
|
||||
GenericArray::from_slice(&checked_slice[elem_len..elem_len + scalar_len]);
|
||||
let blinding_factor = CS::Group::from_scalar_slice(blinding_factor_bytes)?;
|
||||
let blinding_factor = CS::OprfGroup::from_scalar_slice(blinding_factor_bytes)?;
|
||||
|
||||
let password = checked_slice[elem_len + scalar_len..].to_vec();
|
||||
Ok(Self {
|
||||
@@ -257,7 +258,8 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
blinding_factor_rng: &mut R,
|
||||
password: &[u8],
|
||||
) -> Result<ClientRegistrationStartResult<CS>, ProtocolError> {
|
||||
let (token, alpha) = oprf::blind::<R, CS::Group, CS::Hash>(password, blinding_factor_rng)?;
|
||||
let (token, alpha) =
|
||||
oprf::blind::<R, CS::OprfGroup, CS::Hash>(password, blinding_factor_rng)?;
|
||||
|
||||
Ok(ClientRegistrationStartResult {
|
||||
message: RegistrationRequest::<CS> { alpha },
|
||||
@@ -273,7 +275,7 @@ pub struct ClientRegistrationFinishResult<CS: CipherSuite> {
|
||||
/// The export key output by client registration
|
||||
pub export_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||
/// The server's static public key
|
||||
pub server_s_pk: PublicKey<CS::Group>,
|
||||
pub server_s_pk: PublicKey<CS::KeGroup>,
|
||||
/// Instance of the ClientRegistration, only used in tests for checking zeroize
|
||||
#[cfg(test)]
|
||||
pub state: ClientRegistration<CS>,
|
||||
@@ -321,8 +323,10 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
return Err(ProtocolError::ReflectedValueError);
|
||||
}
|
||||
|
||||
let password_derived_key =
|
||||
get_password_derived_key::<CS::Group, CS::SlowHash, CS::Hash>(&self.token, r2.beta)?;
|
||||
let password_derived_key = get_password_derived_key::<CS::OprfGroup, CS::SlowHash, CS::Hash>(
|
||||
&self.token,
|
||||
r2.beta,
|
||||
)?;
|
||||
|
||||
#[cfg_attr(not(test), allow(unused_variables))]
|
||||
let (randomized_pwd, h) = Hkdf::<CS::Hash>::extract(None, &password_derived_key);
|
||||
@@ -358,7 +362,7 @@ pub struct ServerRegistrationStartResult<CS: CipherSuite> {
|
||||
pub message: RegistrationResponse<CS>,
|
||||
/// OPRF key, only used in tests
|
||||
#[cfg(test)]
|
||||
pub oprf_key: GenericArray<u8, <CS::Group as Group>::ScalarLen>,
|
||||
pub oprf_key: GenericArray<u8, <CS::OprfGroup as Group>::ScalarLen>,
|
||||
}
|
||||
|
||||
// Cannot be derived because it would require for CS to be Clone.
|
||||
@@ -403,18 +407,18 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
|
||||
|
||||
/// From the client's "blinded" password, returns a response to be
|
||||
/// sent back to the client, as well as a ServerRegistration
|
||||
pub fn start<S: SecretKey<CS::Group>>(
|
||||
pub fn start<S: SecretKey<CS::KeGroup>>(
|
||||
server_setup: &ServerSetup<CS, S>,
|
||||
message: RegistrationRequest<CS>,
|
||||
credential_identifier: &[u8],
|
||||
) -> Result<ServerRegistrationStartResult<CS>, ProtocolError> {
|
||||
let oprf_key = oprf_key_from_seed::<CS::Group, CS::Hash>(
|
||||
let oprf_key = oprf_key_from_seed::<CS::OprfGroup, CS::Hash>(
|
||||
&server_setup.oprf_seed,
|
||||
credential_identifier,
|
||||
)?;
|
||||
|
||||
// Compute beta = alpha^oprf_key
|
||||
let beta = oprf::evaluate::<CS::Group>(message.alpha, &oprf_key);
|
||||
let beta = oprf::evaluate::<CS::OprfGroup>(message.alpha, &oprf_key);
|
||||
|
||||
Ok(ServerRegistrationStartResult {
|
||||
message: RegistrationResponse {
|
||||
@@ -422,7 +426,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
|
||||
server_s_pk: server_setup.keypair.public().clone(),
|
||||
},
|
||||
#[cfg(test)]
|
||||
oprf_key: CS::Group::scalar_as_bytes(oprf_key),
|
||||
oprf_key: CS::OprfGroup::scalar_as_bytes(oprf_key),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -433,7 +437,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
|
||||
}
|
||||
|
||||
// Creates a dummy instance used for faking a [CredentialResponse]
|
||||
pub(crate) fn dummy<R: RngCore + CryptoRng, S: SecretKey<CS::Group>>(
|
||||
pub(crate) fn dummy<R: RngCore + CryptoRng, S: SecretKey<CS::KeGroup>>(
|
||||
rng: &mut R,
|
||||
server_setup: &ServerSetup<CS, S>,
|
||||
) -> Self {
|
||||
@@ -451,14 +455,14 @@ impl_serialize_and_deserialize_for!(ServerRegistration);
|
||||
#[cfg_attr(
|
||||
feature = "serialize",
|
||||
serde(bound(
|
||||
deserialize = "oprf::Token<CS::Group>: serde::Deserialize<'de>, <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State: serde::Deserialize<'de>",
|
||||
serialize = "oprf::Token<CS::Group>: serde::Serialize, <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State: serde::Serialize"
|
||||
deserialize = "oprf::Token<CS::OprfGroup>: serde::Deserialize<'de>, <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE1State: serde::Deserialize<'de>",
|
||||
serialize = "oprf::Token<CS::OprfGroup>: serde::Serialize, <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE1State: serde::Serialize"
|
||||
))
|
||||
)]
|
||||
pub struct ClientLogin<CS: CipherSuite> {
|
||||
/// token containing the client's password and the blinding factor
|
||||
token: oprf::Token<CS::Group>,
|
||||
ke1_state: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State,
|
||||
token: oprf::Token<CS::OprfGroup>,
|
||||
ke1_state: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE1State,
|
||||
serialized_credential_request: Vec<u8>,
|
||||
}
|
||||
|
||||
@@ -466,14 +470,14 @@ impl_clone_for!(struct ClientLogin<CS: CipherSuite>, [token, ke1_state, serializ
|
||||
impl_debug_eq_hash_for!(
|
||||
struct ClientLogin<CS: CipherSuite>,
|
||||
[token, ke1_state, serialized_credential_request],
|
||||
[oprf::Token<CS::Group>, <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State],
|
||||
[oprf::Token<CS::OprfGroup>, <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE1State],
|
||||
);
|
||||
|
||||
impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
|
||||
let output: Vec<u8> = [
|
||||
&CS::Group::scalar_as_bytes(self.token.blind)[..],
|
||||
&CS::OprfGroup::scalar_as_bytes(self.token.blind)[..],
|
||||
&serialize(&self.serialized_credential_request, 2)?,
|
||||
&serialize(&self.ke1_state.to_bytes(), 2)?,
|
||||
&self.token.data,
|
||||
@@ -484,7 +488,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let scalar_len = <CS::Group as Group>::ScalarLen::to_usize();
|
||||
let scalar_len = <CS::OprfGroup as Group>::ScalarLen::to_usize();
|
||||
let checked_slice = (if input.len() <= scalar_len {
|
||||
Err(InternalPakeError::SizeError {
|
||||
name: "client_login_bytes",
|
||||
@@ -496,13 +500,13 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
})?;
|
||||
|
||||
let blinding_factor_bytes = GenericArray::from_slice(&checked_slice[..scalar_len]);
|
||||
let blinding_factor = CS::Group::from_scalar_slice(blinding_factor_bytes)?;
|
||||
let blinding_factor = CS::OprfGroup::from_scalar_slice(blinding_factor_bytes)?;
|
||||
|
||||
let (serialized_credential_request, remainder) = tokenize(&checked_slice[scalar_len..], 2)?;
|
||||
let (ke1_state_bytes, password) = tokenize(&remainder, 2)?;
|
||||
|
||||
let ke1_state =
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State::from_bytes::<CS>(
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE1State::from_bytes::<CS>(
|
||||
&ke1_state_bytes[..],
|
||||
)?;
|
||||
Ok(Self {
|
||||
@@ -575,7 +579,7 @@ pub struct ClientLoginFinishResult<CS: CipherSuite> {
|
||||
/// The client-side export key
|
||||
pub export_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||
/// The server's static public key
|
||||
pub server_s_pk: PublicKey<CS::Group>,
|
||||
pub server_s_pk: PublicKey<CS::KeGroup>,
|
||||
/// Instance of the ClientLogin, only used in tests for checking zeroize
|
||||
#[cfg(test)]
|
||||
pub state: ClientLogin<CS>,
|
||||
@@ -611,7 +615,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
rng: &mut R,
|
||||
password: &[u8],
|
||||
) -> Result<ClientLoginStartResult<CS>, ProtocolError> {
|
||||
let (token, alpha) = oprf::blind::<R, CS::Group, CS::Hash>(password, rng)?;
|
||||
let (token, alpha) = oprf::blind::<R, CS::OprfGroup, CS::Hash>(password, rng)?;
|
||||
|
||||
let (ke1_state, ke1_message) = CS::KeyExchange::generate_ke1(rng)?;
|
||||
|
||||
@@ -652,7 +656,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
return Err(ProtocolError::ReflectedValueError);
|
||||
}
|
||||
|
||||
let password_derived_key = get_password_derived_key::<CS::Group, CS::SlowHash, CS::Hash>(
|
||||
let password_derived_key = get_password_derived_key::<CS::OprfGroup, CS::SlowHash, CS::Hash>(
|
||||
&self.token,
|
||||
credential_response.beta,
|
||||
)?;
|
||||
@@ -722,7 +726,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
|
||||
/// The state elements the server holds to record a login
|
||||
pub struct ServerLogin<CS: CipherSuite> {
|
||||
ke2_state: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2State,
|
||||
ke2_state: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE2State,
|
||||
_cs: PhantomData<CS>,
|
||||
}
|
||||
|
||||
@@ -730,7 +734,7 @@ impl_clone_for!(struct ServerLogin<CS: CipherSuite>, [ke2_state, _cs]);
|
||||
impl_debug_eq_hash_for!(
|
||||
struct ServerLogin<CS: CipherSuite>,
|
||||
[ke2_state, _cs],
|
||||
[<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2State],
|
||||
[<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE2State],
|
||||
);
|
||||
|
||||
/// Optional parameters for server login start
|
||||
@@ -766,7 +770,7 @@ pub struct ServerLoginStartResult<CS: CipherSuite> {
|
||||
pub server_mac_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||
/// OPRF key, only used in tests
|
||||
#[cfg(test)]
|
||||
pub oprf_key: GenericArray<u8, <CS::Group as Group>::ScalarLen>,
|
||||
pub oprf_key: GenericArray<u8, <CS::OprfGroup as Group>::ScalarLen>,
|
||||
}
|
||||
|
||||
// Cannot be derived because it would require for CS to be Clone.
|
||||
@@ -817,15 +821,16 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
pub fn deserialize(bytes: &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
_cs: PhantomData,
|
||||
ke2_state: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2State::from_bytes::<
|
||||
CS,
|
||||
>(bytes)?,
|
||||
ke2_state:
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::KE2State::from_bytes::<CS>(
|
||||
bytes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// From the client's "blinded" password, returns a challenge to be
|
||||
/// sent back to the client, as well as a ServerLogin
|
||||
pub fn start<R: RngCore + CryptoRng, S: SecretKey<CS::Group>>(
|
||||
pub fn start<R: RngCore + CryptoRng, S: SecretKey<CS::KeGroup>>(
|
||||
rng: &mut R,
|
||||
server_setup: &ServerSetup<CS, S>,
|
||||
password_file: Option<ServerRegistration<CS>>,
|
||||
@@ -871,7 +876,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
|
||||
let l1_bytes = &l1.serialize();
|
||||
|
||||
let oprf_key = oprf_key_from_seed::<CS::Group, CS::Hash>(
|
||||
let oprf_key = oprf_key_from_seed::<CS::OprfGroup, CS::Hash>(
|
||||
&server_setup.oprf_seed,
|
||||
credential_identifier,
|
||||
)
|
||||
@@ -911,7 +916,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
#[cfg(test)]
|
||||
server_mac_key: result.3,
|
||||
#[cfg(test)]
|
||||
oprf_key: CS::Group::scalar_as_bytes(oprf_key),
|
||||
oprf_key: CS::OprfGroup::scalar_as_bytes(oprf_key),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -921,7 +926,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
self,
|
||||
message: CredentialFinalization<CS>,
|
||||
) -> Result<ServerLoginFinishResult<CS>, ProtocolError> {
|
||||
let session_key = <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::finish_ke(
|
||||
let session_key = <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeGroup>>::finish_ke(
|
||||
message.ke3_message,
|
||||
&self.ke2_state,
|
||||
)
|
||||
@@ -1033,11 +1038,11 @@ fn oprf_key_from_seed<G: Group, D: Hash>(
|
||||
fn mask_response<CS: CipherSuite>(
|
||||
masking_key: &[u8],
|
||||
masking_nonce: &[u8],
|
||||
server_s_pk: &PublicKey<CS::Group>,
|
||||
server_s_pk: &PublicKey<CS::KeGroup>,
|
||||
envelope: &Envelope<CS>,
|
||||
) -> Result<Vec<u8>, ProtocolError> {
|
||||
let mut xor_pad =
|
||||
vec![0u8; <PublicKey<CS::Group> as SizedBytes>::Len::to_usize() + Envelope::<CS>::len()];
|
||||
vec![0u8; <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize() + Envelope::<CS>::len()];
|
||||
Hkdf::<CS::Hash>::from_prk(masking_key)
|
||||
.map_err(|_| InternalPakeError::HkdfError)?
|
||||
.expand(
|
||||
@@ -1059,9 +1064,9 @@ fn unmask_response<CS: CipherSuite>(
|
||||
masking_key: &[u8],
|
||||
masking_nonce: &[u8],
|
||||
masked_response: &[u8],
|
||||
) -> Result<(PublicKey<CS::Group>, Envelope<CS>), ProtocolError> {
|
||||
) -> Result<(PublicKey<CS::KeGroup>, Envelope<CS>), ProtocolError> {
|
||||
let mut xor_pad =
|
||||
vec![0u8; <PublicKey<CS::Group> as SizedBytes>::Len::to_usize() + Envelope::<CS>::len()];
|
||||
vec![0u8; <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize() + Envelope::<CS>::len()];
|
||||
Hkdf::<CS::Hash>::from_prk(masking_key)
|
||||
.map_err(|_| InternalPakeError::HkdfError)?
|
||||
.expand(
|
||||
@@ -1074,13 +1079,13 @@ fn unmask_response<CS: CipherSuite>(
|
||||
.zip(masked_response.iter())
|
||||
.map(|(&x1, &x2)| x1 ^ x2)
|
||||
.collect();
|
||||
let key_len = <PublicKey<CS::Group> as SizedBytes>::Len::to_usize();
|
||||
let key_len = <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
|
||||
let unchecked_server_s_pk =
|
||||
PublicKey::from_arr(&GenericArray::clone_from_slice(&plaintext[..key_len]))?;
|
||||
let envelope = Envelope::deserialize(&plaintext[key_len..])?;
|
||||
|
||||
// Ensure that public key is valid
|
||||
let server_s_pk = KeyPair::<CS::Group>::check_public_key(unchecked_server_s_pk)
|
||||
let server_s_pk = KeyPair::<CS::KeGroup>::check_public_key(unchecked_server_s_pk)
|
||||
.map_err(|_| ProtocolError::VerificationError(PakeError::SerializationError))?;
|
||||
|
||||
Ok((server_s_pk, envelope))
|
||||
|
||||
@@ -27,7 +27,8 @@ use sha2::Digest;
|
||||
|
||||
struct Default;
|
||||
impl CipherSuite for Default {
|
||||
type Group = RistrettoPoint;
|
||||
type OprfGroup = RistrettoPoint;
|
||||
type KeGroup = RistrettoPoint;
|
||||
type KeyExchange = TripleDH;
|
||||
type Hash = sha2::Sha512;
|
||||
type SlowHash = crate::slow_hash::NoOpHash;
|
||||
@@ -78,7 +79,7 @@ fn server_registration_roundtrip() {
|
||||
// mock_envelope_bytes.extend_from_slice(&ciphertext); // ciphertext which is an encrypted private key
|
||||
mock_envelope_bytes.extend_from_slice(&[0; MAC_SIZE]); // length-MAC_SIZE hmac
|
||||
|
||||
let mock_client_kp = KeyPair::<<Default as CipherSuite>::Group>::generate_random(&mut rng);
|
||||
let mock_client_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
|
||||
// serialization order: oprf_key, public key, envelope
|
||||
let mut bytes = Vec::<u8>::new();
|
||||
bytes.extend_from_slice(&mock_client_kp.public().to_arr());
|
||||
@@ -118,7 +119,7 @@ fn registration_response_roundtrip() {
|
||||
let pt = random_ristretto_point();
|
||||
let beta_bytes = pt.to_arr();
|
||||
let mut rng = OsRng;
|
||||
let skp = KeyPair::<<Default as CipherSuite>::Group>::generate_random(&mut rng);
|
||||
let skp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
|
||||
let pubkey_bytes = skp.public().to_arr();
|
||||
|
||||
let mut input = Vec::new();
|
||||
@@ -144,7 +145,7 @@ fn registration_response_roundtrip() {
|
||||
#[test]
|
||||
fn registration_upload_roundtrip() {
|
||||
let mut rng = OsRng;
|
||||
let skp = KeyPair::<<Default as CipherSuite>::Group>::generate_random(&mut rng);
|
||||
let skp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
|
||||
let pubkey_bytes = skp.public().to_arr();
|
||||
|
||||
let mut key = [0u8; 32];
|
||||
@@ -176,7 +177,7 @@ fn credential_request_roundtrip() {
|
||||
let alpha = random_ristretto_point();
|
||||
let alpha_bytes = alpha.to_arr().to_vec();
|
||||
|
||||
let client_e_kp = KeyPair::<<Default as CipherSuite>::Group>::generate_random(&mut rng);
|
||||
let client_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
|
||||
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut client_nonce);
|
||||
|
||||
@@ -219,7 +220,7 @@ fn credential_response_roundtrip() {
|
||||
];
|
||||
rng.fill_bytes(&mut masked_response);
|
||||
|
||||
let server_e_kp = KeyPair::<<Default as CipherSuite>::Group>::generate_random(&mut rng);
|
||||
let server_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
|
||||
let mut mac = [0u8; MAC_SIZE];
|
||||
rng.fill_bytes(&mut mac);
|
||||
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
@@ -274,7 +275,7 @@ fn client_login_roundtrip() {
|
||||
let mut rng = OsRng;
|
||||
let sc = <RistrettoPoint as Group>::random_nonzero_scalar(&mut rng);
|
||||
|
||||
let client_e_kp = KeyPair::<<Default as CipherSuite>::Group>::generate_random(&mut rng);
|
||||
let client_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
|
||||
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut client_nonce);
|
||||
|
||||
@@ -298,7 +299,7 @@ fn client_login_roundtrip() {
|
||||
fn ke1_message_roundtrip() {
|
||||
let mut rng = OsRng;
|
||||
|
||||
let client_e_kp = KeyPair::<<Default as CipherSuite>::Group>::generate_random(&mut rng);
|
||||
let client_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
|
||||
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut client_nonce);
|
||||
|
||||
@@ -315,7 +316,7 @@ fn ke1_message_roundtrip() {
|
||||
fn ke2_message_roundtrip() {
|
||||
let mut rng = OsRng;
|
||||
|
||||
let server_e_kp = KeyPair::<<Default as CipherSuite>::Group>::generate_random(&mut rng);
|
||||
let server_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
|
||||
let mut mac = [0u8; MAC_SIZE];
|
||||
rng.fill_bytes(&mut mac);
|
||||
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
|
||||
+10
-9
@@ -29,7 +29,8 @@ use zeroize::Zeroize;
|
||||
|
||||
struct RistrettoSha5123dhNoSlowHash;
|
||||
impl CipherSuite for RistrettoSha5123dhNoSlowHash {
|
||||
type Group = RistrettoPoint;
|
||||
type OprfGroup = RistrettoPoint;
|
||||
type KeGroup = RistrettoPoint;
|
||||
type KeyExchange = TripleDH;
|
||||
type Hash = sha2::Sha512;
|
||||
type SlowHash = NoOpHash;
|
||||
@@ -280,11 +281,11 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
let mut rng = OsRng;
|
||||
|
||||
// Inputs
|
||||
let server_s_kp = KeyPair::<CS::Group>::generate_random(&mut rng);
|
||||
let server_e_kp = KeyPair::<CS::Group>::generate_random(&mut rng);
|
||||
let client_s_kp = KeyPair::<CS::Group>::generate_random(&mut rng);
|
||||
let client_e_kp = KeyPair::<CS::Group>::generate_random(&mut rng);
|
||||
let fake_kp = KeyPair::<CS::Group>::generate_random(&mut rng);
|
||||
let server_s_kp = KeyPair::<CS::OprfGroup>::generate_random(&mut rng);
|
||||
let server_e_kp = KeyPair::<CS::OprfGroup>::generate_random(&mut rng);
|
||||
let client_s_kp = KeyPair::<CS::OprfGroup>::generate_random(&mut rng);
|
||||
let client_e_kp = KeyPair::<CS::OprfGroup>::generate_random(&mut rng);
|
||||
let fake_kp = KeyPair::<CS::OprfGroup>::generate_random(&mut rng);
|
||||
let credential_identifier = b"credIdentifier";
|
||||
let id_u = b"idU";
|
||||
let id_s = b"idS";
|
||||
@@ -307,14 +308,14 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let blinding_factor = CS::Group::random_nonzero_scalar(&mut rng);
|
||||
let blinding_factor_bytes = CS::Group::scalar_as_bytes(blinding_factor);
|
||||
let blinding_factor = CS::OprfGroup::random_nonzero_scalar(&mut rng);
|
||||
let blinding_factor_bytes = CS::OprfGroup::scalar_as_bytes(blinding_factor);
|
||||
|
||||
let mut blinding_factor_registration_rng = CycleRng::new(blinding_factor_bytes.to_vec());
|
||||
let client_registration_start_result =
|
||||
ClientRegistration::<CS>::start(&mut blinding_factor_registration_rng, password).unwrap();
|
||||
let blinding_factor_bytes_returned =
|
||||
CS::Group::scalar_as_bytes(client_registration_start_result.state.token.blind);
|
||||
CS::OprfGroup::scalar_as_bytes(client_registration_start_result.state.token.blind);
|
||||
assert_eq!(
|
||||
hex::encode(&blinding_factor_bytes),
|
||||
hex::encode(&blinding_factor_bytes_returned)
|
||||
|
||||
@@ -17,7 +17,8 @@ use serde_json::Value;
|
||||
|
||||
struct Ristretto255Sha512NoSlowHash;
|
||||
impl CipherSuite for Ristretto255Sha512NoSlowHash {
|
||||
type Group = RistrettoPoint;
|
||||
type OprfGroup = RistrettoPoint;
|
||||
type KeGroup = RistrettoPoint;
|
||||
type KeyExchange = TripleDH;
|
||||
type Hash = sha2::Sha512;
|
||||
type SlowHash = NoOpHash;
|
||||
@@ -27,7 +28,8 @@ impl CipherSuite for Ristretto255Sha512NoSlowHash {
|
||||
struct P256Sha256NoSlowHash;
|
||||
#[cfg(feature = "p256")]
|
||||
impl CipherSuite for P256Sha256NoSlowHash {
|
||||
type Group = p256_::ProjectivePoint;
|
||||
type OprfGroup = p256_::ProjectivePoint;
|
||||
type KeGroup = p256_::ProjectivePoint;
|
||||
type KeyExchange = TripleDH;
|
||||
type Hash = sha2::Sha256;
|
||||
type SlowHash = NoOpHash;
|
||||
@@ -750,7 +752,7 @@ fn populate_test_vectors<CS: CipherSuite>(values: &Value) -> TestVectorParameter
|
||||
dummy_private_key: parse_default!(
|
||||
values,
|
||||
"client_private_key",
|
||||
vec![0u8; <PrivateKey<CS::Group> as SizedBytes>::Len::to_usize()]
|
||||
vec![0u8; <PrivateKey<CS::OprfGroup> as SizedBytes>::Len::to_usize()]
|
||||
),
|
||||
dummy_masking_key: parse_default!(values, "masking_key", vec![0u8; 64]),
|
||||
context: parse!(values, "Context"),
|
||||
|
||||
Reference in New Issue
Block a user