Add SlowHash configuration (#234)
* Add `SlowHash` configuration * Use a reference * Changing generic argument to be CipherSuite instead of SlowHash Co-authored-by: Kevin Lewi <[email protected]>
This commit is contained in:
+1
-1
@@ -22,7 +22,7 @@ std = ["curve25519-dalek/std", "getrandom", "rand/std", "rand/std_rng", "num-big
|
|||||||
serialize = ["serde", "base64", "generic-array/serde", "curve25519-dalek/serde"]
|
serialize = ["serde", "base64", "generic-array/serde", "curve25519-dalek/serde"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
argon2 = { version = "0.2", default-features = false, optional = true }
|
argon2 = { version = "0.3", default-features = false, features = ["alloc"], optional = true }
|
||||||
base64 = { version = "0.13", default-features = false, features = ["alloc"], optional = true }
|
base64 = { version = "0.13", default-features = false, features = ["alloc"], optional = true }
|
||||||
constant_time_eq = "0.1"
|
constant_time_eq = "0.1"
|
||||||
curve25519-dalek = { version = "3", default-features = false }
|
curve25519-dalek = { version = "3", default-features = false }
|
||||||
|
|||||||
+3
-3
@@ -127,7 +127,7 @@ fn test() -> Result<(), ProtocolError> {
|
|||||||
} = client.finish(
|
} = client.finish(
|
||||||
&mut OsRng,
|
&mut OsRng,
|
||||||
message,
|
message,
|
||||||
ClientRegistrationFinishParameters::Default,
|
ClientRegistrationFinishParameters::default(),
|
||||||
)?;
|
)?;
|
||||||
let server_registration = ServerRegistration::finish(message);
|
let server_registration = ServerRegistration::finish(message);
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ fn test() -> Result<(), ProtocolError> {
|
|||||||
session_key: client_session_key,
|
session_key: client_session_key,
|
||||||
export_key: login_export_key,
|
export_key: login_export_key,
|
||||||
..
|
..
|
||||||
} = client.finish(message, ClientLoginFinishParameters::Default)?;
|
} = client.finish(message, ClientLoginFinishParameters::default())?;
|
||||||
let server_session_key = server.finish(message)?.session_key;
|
let server_session_key = server.finish(message)?.session_key;
|
||||||
|
|
||||||
assert_eq!(register_export_key, login_export_key);
|
assert_eq!(register_export_key, login_export_key);
|
||||||
@@ -172,7 +172,7 @@ fn test() -> Result<(), ProtocolError> {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
client.finish(message, ClientLoginFinishParameters::Default),
|
client.finish(message, ClientLoginFinishParameters::default()),
|
||||||
Err(ProtocolError::InvalidLoginError)
|
Err(ProtocolError::InvalidLoginError)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -507,7 +507,7 @@ mod tests {
|
|||||||
.finish(
|
.finish(
|
||||||
&mut OsRng,
|
&mut OsRng,
|
||||||
message,
|
message,
|
||||||
ClientRegistrationFinishParameters::Default,
|
ClientRegistrationFinishParameters::default(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let file = ServerRegistration::finish(message);
|
let file = ServerRegistration::finish(message);
|
||||||
@@ -530,7 +530,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ClientLoginFinishResult { message, .. } = client
|
let ClientLoginFinishResult { message, .. } = client
|
||||||
.finish(message, ClientLoginFinishParameters::Default)
|
.finish(message, ClientLoginFinishParameters::default())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server.finish(message).unwrap();
|
server.finish(message).unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-12
@@ -578,7 +578,7 @@
|
|||||||
//!
|
//!
|
||||||
//! But, for applications that wish to cryptographically bind these identities to
|
//! But, for applications that wish to cryptographically bind these identities to
|
||||||
//! the registered password file as well as the session key output by the login phase, these custom identifiers can be specified through
|
//! the registered password file as well as the session key output by the login phase, these custom identifiers can be specified through
|
||||||
//! [ClientRegistrationFinishParameters::WithIdentifiers] in [Client Registration Finish](#client-registration-finish):
|
//! [ClientRegistrationFinishParameters] in [Client Registration Finish](#client-registration-finish):
|
||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
@@ -606,11 +606,12 @@
|
|||||||
//! let client_registration_finish_result = client_registration_start_result.state.finish(
|
//! let client_registration_finish_result = client_registration_start_result.state.finish(
|
||||||
//! &mut client_rng,
|
//! &mut client_rng,
|
||||||
//! server_registration_start_result.message,
|
//! server_registration_start_result.message,
|
||||||
//! ClientRegistrationFinishParameters::WithIdentifiers(
|
//! ClientRegistrationFinishParameters::new(
|
||||||
//! Identifiers::ClientAndServerIdentifiers(
|
//! Some(Identifiers::ClientAndServerIdentifiers(
|
||||||
//! b"Alice_the_Cryptographer".to_vec(),
|
//! b"Alice_the_Cryptographer".to_vec(),
|
||||||
//! b"Facebook".to_vec(),
|
//! b"Facebook".to_vec(),
|
||||||
//! ),
|
//! )),
|
||||||
|
//! None,
|
||||||
//! ),
|
//! ),
|
||||||
//! )?;
|
//! )?;
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
@@ -641,7 +642,7 @@
|
|||||||
//! # let mut server_rng = OsRng;
|
//! # let mut server_rng = OsRng;
|
||||||
//! # let server_setup = ServerSetup::<Default>::new(&mut server_rng);
|
//! # let server_setup = ServerSetup::<Default>::new(&mut server_rng);
|
||||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&server_setup, client_registration_start_result.message, b"[email protected]")?;
|
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&server_setup, client_registration_start_result.message, b"[email protected]")?;
|
||||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::WithIdentifiers(Identifiers::ClientAndServerIdentifiers(b"Alice_the_Cryptographer".to_vec(), b"Facebook".to_vec())))?;
|
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::new(Some(Identifiers::ClientAndServerIdentifiers(b"Alice_the_Cryptographer".to_vec(), b"Facebook".to_vec())), None))?;
|
||||||
//! # let password_file_bytes = ServerRegistration::<Default>::finish(client_registration_finish_result.message).serialize();
|
//! # let password_file_bytes = ServerRegistration::<Default>::finish(client_registration_finish_result.message).serialize();
|
||||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
@@ -666,7 +667,7 @@
|
|||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! as well as [ClientLoginFinishParameters::WithIdentifiers] in [Client Login Finish](#client-login-finish):
|
//! as well as [ClientLoginFinishParameters] in [Client Login Finish](#client-login-finish):
|
||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
@@ -691,7 +692,7 @@
|
|||||||
//! # let mut server_rng = OsRng;
|
//! # let mut server_rng = OsRng;
|
||||||
//! # let server_setup = ServerSetup::<Default>::new(&mut server_rng);
|
//! # let server_setup = ServerSetup::<Default>::new(&mut server_rng);
|
||||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&server_setup, client_registration_start_result.message, b"[email protected]")?;
|
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&server_setup, client_registration_start_result.message, b"[email protected]")?;
|
||||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::WithIdentifiers(Identifiers::ClientAndServerIdentifiers(b"Alice_the_Cryptographer".to_vec(), b"Facebook".to_vec())))?;
|
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::new(Some(Identifiers::ClientAndServerIdentifiers(b"Alice_the_Cryptographer".to_vec(), b"Facebook".to_vec())), None))?;
|
||||||
//! # let password_file_bytes = ServerRegistration::<Default>::finish(client_registration_finish_result.message).serialize();
|
//! # let password_file_bytes = ServerRegistration::<Default>::finish(client_registration_finish_result.message).serialize();
|
||||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
@@ -705,11 +706,13 @@
|
|||||||
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginStartParameters::WithIdentifiers(Identifiers::ClientAndServerIdentifiers(b"Alice_the_Cryptographer".to_vec(), b"Facebook".to_vec())))?;
|
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginStartParameters::WithIdentifiers(Identifiers::ClientAndServerIdentifiers(b"Alice_the_Cryptographer".to_vec(), b"Facebook".to_vec())))?;
|
||||||
//! let client_login_finish_result = client_login_start_result.state.finish(
|
//! let client_login_finish_result = client_login_start_result.state.finish(
|
||||||
//! server_login_start_result.message,
|
//! server_login_start_result.message,
|
||||||
//! ClientLoginFinishParameters::WithIdentifiers(
|
//! ClientLoginFinishParameters::new(
|
||||||
//! Identifiers::ClientAndServerIdentifiers(
|
//! None,
|
||||||
|
//! Some(Identifiers::ClientAndServerIdentifiers(
|
||||||
//! b"Alice_the_Cryptographer".to_vec(),
|
//! b"Alice_the_Cryptographer".to_vec(),
|
||||||
//! b"Facebook".to_vec(),
|
//! b"Facebook".to_vec(),
|
||||||
//! ),
|
//! )),
|
||||||
|
//! None,
|
||||||
//! ),
|
//! ),
|
||||||
//! )?;
|
//! )?;
|
||||||
//!
|
//!
|
||||||
@@ -727,7 +730,7 @@
|
|||||||
//! so as to bind the integrity of application-specific data or configuration parameters to the security of the key exchange.
|
//! so as to bind the integrity of application-specific data or configuration parameters to the security of the key exchange.
|
||||||
//! During the login phase, the client and server can specify this context using:
|
//! During the login phase, the client and server can specify this context using:
|
||||||
//! - The second login message, where the server can populate [ServerLoginStartParameters::WithContext], and
|
//! - The second login message, where the server can populate [ServerLoginStartParameters::WithContext], and
|
||||||
//! - The third login message, where the client can populate [ClientLoginFinishParameters::WithContext].
|
//! - The third login message, where the client can populate [ClientLoginFinishParameters].
|
||||||
//!
|
//!
|
||||||
//! For both of these messages, the `WithContextAndIdentifiers` variant can be used to specify these fields in addition to
|
//! For both of these messages, the `WithContextAndIdentifiers` variant can be used to specify these fields in addition to
|
||||||
//! [custom identifiers](#custom-identifiers), with the ordering of the fields as
|
//! [custom identifiers](#custom-identifiers), with the ordering of the fields as
|
||||||
@@ -780,7 +783,8 @@
|
|||||||
//! fn public_key(
|
//! fn public_key(
|
||||||
//! &self
|
//! &self
|
||||||
//! ) -> Result<PublicKey<RistrettoPoint>, InternalError<Self::Error>> {
|
//! ) -> Result<PublicKey<RistrettoPoint>, InternalError<Self::Error>> {
|
||||||
//! YourRemoteKey::public_key(self).map(PublicKey::from_arr).map_err(InternalError::Custom)
|
//! YourRemoteKey::public_key(self).map(PublicKey::from_arr)
|
||||||
|
//! .map_err(InternalError::Custom)
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn serialize(&self) -> Vec<u8> {
|
//! fn serialize(&self) -> Vec<u8> {
|
||||||
|
|||||||
+75
-47
@@ -222,16 +222,29 @@ pub(crate) fn bytestrings_from_identifiers(
|
|||||||
|
|
||||||
/// Optional parameters for client registration finish
|
/// Optional parameters for client registration finish
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum ClientRegistrationFinishParameters {
|
pub struct ClientRegistrationFinishParameters<'h, CS: CipherSuite> {
|
||||||
/// Specifying the identifiers idU and idS
|
/// Specifying the identifiers idU and idS
|
||||||
WithIdentifiers(Identifiers),
|
pub identifiers: Option<Identifiers>,
|
||||||
/// No identifiers or private key specified
|
/// Specifying a configuration for the slow hash
|
||||||
Default,
|
pub slow_hash: Option<&'h CS::SlowHash>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ClientRegistrationFinishParameters {
|
impl<'h, CS: CipherSuite> Default for ClientRegistrationFinishParameters<'h, CS> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Default
|
Self {
|
||||||
|
identifiers: None,
|
||||||
|
slow_hash: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'h, CS: CipherSuite> ClientRegistrationFinishParameters<'h, CS> {
|
||||||
|
/// Create a new [`ClientRegistrationFinishParameters`]
|
||||||
|
pub fn new(identifiers: Option<Identifiers>, slow_hash: Option<&'h CS::SlowHash>) -> Self {
|
||||||
|
Self {
|
||||||
|
identifiers,
|
||||||
|
slow_hash,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,22 +325,15 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
|||||||
self,
|
self,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
r2: RegistrationResponse<CS>,
|
r2: RegistrationResponse<CS>,
|
||||||
params: ClientRegistrationFinishParameters,
|
params: ClientRegistrationFinishParameters<CS>,
|
||||||
) -> Result<ClientRegistrationFinishResult<CS>, ProtocolError> {
|
) -> Result<ClientRegistrationFinishResult<CS>, ProtocolError> {
|
||||||
let optional_ids = match params {
|
|
||||||
ClientRegistrationFinishParameters::WithIdentifiers(ids) => Some(ids),
|
|
||||||
ClientRegistrationFinishParameters::Default => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check for reflected value from server and halt if detected
|
// Check for reflected value from server and halt if detected
|
||||||
if self.alpha.ct_equal(&r2.beta) {
|
if self.alpha.ct_equal(&r2.beta) {
|
||||||
return Err(ProtocolError::ReflectedValueError);
|
return Err(ProtocolError::ReflectedValueError);
|
||||||
}
|
}
|
||||||
|
|
||||||
let password_derived_key = get_password_derived_key::<CS::OprfGroup, CS::SlowHash, CS::Hash>(
|
let password_derived_key =
|
||||||
&self.token,
|
get_password_derived_key::<CS>(&self.token, r2.beta, params.slow_hash)?;
|
||||||
r2.beta,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
#[cfg_attr(not(test), allow(unused_variables))]
|
#[cfg_attr(not(test), allow(unused_variables))]
|
||||||
let (randomized_pwd, h) = Hkdf::<CS::Hash>::extract(None, &password_derived_key);
|
let (randomized_pwd, h) = Hkdf::<CS::Hash>::extract(None, &password_derived_key);
|
||||||
@@ -335,8 +341,12 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
|||||||
h.expand(STR_MASKING_KEY, &mut masking_key)
|
h.expand(STR_MASKING_KEY, &mut masking_key)
|
||||||
.map_err(|_| InternalError::HkdfError)?;
|
.map_err(|_| InternalError::HkdfError)?;
|
||||||
|
|
||||||
let result =
|
let result = Envelope::<CS>::seal(
|
||||||
Envelope::<CS>::seal(rng, &password_derived_key, &r2.server_s_pk, optional_ids)?;
|
rng,
|
||||||
|
&password_derived_key,
|
||||||
|
&r2.server_s_pk,
|
||||||
|
params.identifiers,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(ClientRegistrationFinishResult {
|
Ok(ClientRegistrationFinishResult {
|
||||||
message: RegistrationUpload {
|
message: RegistrationUpload {
|
||||||
@@ -553,21 +563,37 @@ impl<CS: CipherSuite> Clone for ClientLoginStartResult<CS> {
|
|||||||
|
|
||||||
/// Optional parameters for client login finish
|
/// Optional parameters for client login finish
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum ClientLoginFinishParameters {
|
pub struct ClientLoginFinishParameters<'h, CS: CipherSuite> {
|
||||||
/// Specifying a context field that the server must agree on
|
/// Specifying a context field that the server must agree on
|
||||||
WithContext(Vec<u8>),
|
pub context: Option<Vec<u8>>,
|
||||||
/// Specifying a user identifier and server identifier that will be matched against the server
|
/// Specifying a user identifier and server identifier that will be matched against the server
|
||||||
WithIdentifiers(Identifiers),
|
pub identifiers: Option<Identifiers>,
|
||||||
/// Specifying a context field that the server must agree on,
|
/// Specifying a configuration for the slow hash
|
||||||
/// along with a user identifier and server identifier and context that will be matched against the server
|
pub slow_hash: Option<&'h CS::SlowHash>,
|
||||||
WithContextAndIdentifiers(Vec<u8>, Identifiers),
|
|
||||||
/// No custom identifiers and no context
|
|
||||||
Default,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ClientLoginFinishParameters {
|
impl<'h, CS: CipherSuite> Default for ClientLoginFinishParameters<'h, CS> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Default
|
Self {
|
||||||
|
context: None,
|
||||||
|
identifiers: None,
|
||||||
|
slow_hash: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'h, CS: CipherSuite> ClientLoginFinishParameters<'h, CS> {
|
||||||
|
/// Create a new [`ClientLoginFinishParameters`]
|
||||||
|
pub fn new(
|
||||||
|
context: Option<Vec<u8>>,
|
||||||
|
identifiers: Option<Identifiers>,
|
||||||
|
slow_hash: Option<&'h CS::SlowHash>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
context,
|
||||||
|
identifiers,
|
||||||
|
slow_hash,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,18 +664,8 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
|||||||
pub fn finish(
|
pub fn finish(
|
||||||
self,
|
self,
|
||||||
credential_response: CredentialResponse<CS>,
|
credential_response: CredentialResponse<CS>,
|
||||||
params: ClientLoginFinishParameters,
|
params: ClientLoginFinishParameters<CS>,
|
||||||
) -> Result<ClientLoginFinishResult<CS>, ProtocolError> {
|
) -> Result<ClientLoginFinishResult<CS>, ProtocolError> {
|
||||||
let (context, optional_ids) = match params {
|
|
||||||
ClientLoginFinishParameters::Default => (vec![], None),
|
|
||||||
ClientLoginFinishParameters::WithContext(context) => (context, None),
|
|
||||||
ClientLoginFinishParameters::WithIdentifiers(ids) => (vec![], Some(ids)),
|
|
||||||
// add context
|
|
||||||
ClientLoginFinishParameters::WithContextAndIdentifiers(context, ids) => {
|
|
||||||
(context, Some(ids))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if beta value from server is equal to alpha value from client
|
// Check if beta value from server is equal to alpha value from client
|
||||||
let credential_request =
|
let credential_request =
|
||||||
CredentialRequest::<CS>::deserialize(&self.serialized_credential_request[..])?;
|
CredentialRequest::<CS>::deserialize(&self.serialized_credential_request[..])?;
|
||||||
@@ -657,9 +673,10 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
|||||||
return Err(ProtocolError::ReflectedValueError);
|
return Err(ProtocolError::ReflectedValueError);
|
||||||
}
|
}
|
||||||
|
|
||||||
let password_derived_key = get_password_derived_key::<CS::OprfGroup, CS::SlowHash, CS::Hash>(
|
let password_derived_key = get_password_derived_key::<CS>(
|
||||||
&self.token,
|
&self.token,
|
||||||
credential_response.beta,
|
credential_response.beta,
|
||||||
|
params.slow_hash,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let h = Hkdf::<CS::Hash>::new(None, &password_derived_key);
|
let h = Hkdf::<CS::Hash>::new(None, &password_derived_key);
|
||||||
@@ -679,7 +696,11 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
|||||||
let server_s_pk_bytes = server_s_pk.to_arr().to_vec();
|
let server_s_pk_bytes = server_s_pk.to_arr().to_vec();
|
||||||
|
|
||||||
let opened_envelope = &envelope
|
let opened_envelope = &envelope
|
||||||
.open(&password_derived_key, &server_s_pk_bytes, &optional_ids)
|
.open(
|
||||||
|
&password_derived_key,
|
||||||
|
&server_s_pk_bytes,
|
||||||
|
¶ms.identifiers,
|
||||||
|
)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
ProtocolError::LibraryError(InternalError::SealOpenHmacError) => {
|
ProtocolError::LibraryError(InternalError::SealOpenHmacError) => {
|
||||||
ProtocolError::InvalidLoginError
|
ProtocolError::InvalidLoginError
|
||||||
@@ -702,7 +723,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
|||||||
opened_envelope.client_static_keypair.private().clone(),
|
opened_envelope.client_static_keypair.private().clone(),
|
||||||
opened_envelope.id_u.clone(),
|
opened_envelope.id_u.clone(),
|
||||||
opened_envelope.id_s.clone(),
|
opened_envelope.id_s.clone(),
|
||||||
context,
|
params.context.unwrap_or_default(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(ClientLoginFinishResult {
|
Ok(ClientLoginFinishResult {
|
||||||
@@ -1007,12 +1028,19 @@ impl<CS: CipherSuite> Drop for ServerLogin<CS> {
|
|||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
|
|
||||||
fn get_password_derived_key<G: Group, SH: SlowHash<D>, D: Hash>(
|
fn get_password_derived_key<CS: CipherSuite>(
|
||||||
token: &oprf::Token<G>,
|
token: &oprf::Token<CS::OprfGroup>,
|
||||||
beta: G,
|
beta: CS::OprfGroup,
|
||||||
|
slow_hash: Option<&CS::SlowHash>,
|
||||||
) -> Result<Vec<u8>, ProtocolError> {
|
) -> Result<Vec<u8>, ProtocolError> {
|
||||||
let oprf_output = oprf::finalize::<G, D>(&token.data, &token.blind, beta)?;
|
let oprf_output = oprf::finalize::<CS::OprfGroup, CS::Hash>(&token.data, &token.blind, beta)?;
|
||||||
SH::hash(oprf_output).map_err(ProtocolError::from)
|
|
||||||
|
if let Some(slow_hash) = slow_hash {
|
||||||
|
slow_hash.hash(oprf_output)
|
||||||
|
} else {
|
||||||
|
CS::SlowHash::default().hash(oprf_output)
|
||||||
|
}
|
||||||
|
.map_err(ProtocolError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn oprf_key_from_seed<G: Group, D: Hash>(
|
fn oprf_key_from_seed<G: Group, D: Hash>(
|
||||||
|
|||||||
+15
-13
@@ -13,33 +13,35 @@ use generic_array::typenum::Unsigned;
|
|||||||
use generic_array::GenericArray;
|
use generic_array::GenericArray;
|
||||||
|
|
||||||
/// Used for the slow hashing function in OPAQUE
|
/// Used for the slow hashing function in OPAQUE
|
||||||
pub trait SlowHash<D: Hash> {
|
pub trait SlowHash<D: Hash>: Default {
|
||||||
/// Computes the slow hashing function
|
/// Computes the slow hashing function
|
||||||
fn hash(input: GenericArray<u8, <D as Digest>::OutputSize>) -> Result<Vec<u8>, InternalError>;
|
fn hash(
|
||||||
|
&self,
|
||||||
|
input: GenericArray<u8, <D as Digest>::OutputSize>,
|
||||||
|
) -> Result<Vec<u8>, InternalError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A no-op hash which simply returns its input
|
/// A no-op hash which simply returns its input
|
||||||
|
#[derive(Default)]
|
||||||
pub struct NoOpHash;
|
pub struct NoOpHash;
|
||||||
|
|
||||||
impl<D: Hash> SlowHash<D> for NoOpHash {
|
impl<D: Hash> SlowHash<D> for NoOpHash {
|
||||||
fn hash(input: GenericArray<u8, <D as Digest>::OutputSize>) -> Result<Vec<u8>, InternalError> {
|
fn hash(
|
||||||
|
&self,
|
||||||
|
input: GenericArray<u8, <D as Digest>::OutputSize>,
|
||||||
|
) -> Result<Vec<u8>, InternalError> {
|
||||||
Ok(input.to_vec())
|
Ok(input.to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "slow-hash")]
|
#[cfg(feature = "slow-hash")]
|
||||||
impl<D: Hash> SlowHash<D> for argon2::Argon2<'_> {
|
impl<D: Hash> SlowHash<D> for argon2::Argon2<'_> {
|
||||||
fn hash(input: GenericArray<u8, <D as Digest>::OutputSize>) -> Result<Vec<u8>, InternalError> {
|
fn hash(
|
||||||
let params = argon2::Argon2::default();
|
&self,
|
||||||
|
input: GenericArray<u8, <D as Digest>::OutputSize>,
|
||||||
|
) -> Result<Vec<u8>, InternalError> {
|
||||||
let mut output = alloc::vec![0u8; <D as Digest>::OutputSize::USIZE];
|
let mut output = alloc::vec![0u8; <D as Digest>::OutputSize::USIZE];
|
||||||
params
|
self.hash_password_into(&input, &[0; argon2::MIN_SALT_LEN], &mut output)
|
||||||
.hash_password_into(
|
|
||||||
argon2::Algorithm::Argon2id,
|
|
||||||
&input,
|
|
||||||
&[0; argon2::MIN_SALT_LENGTH],
|
|
||||||
&[],
|
|
||||||
&mut output,
|
|
||||||
)
|
|
||||||
.map_err(|_| InternalError::SlowHashError)?;
|
.map_err(|_| InternalError::SlowHashError)?;
|
||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-10
@@ -347,8 +347,12 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
|||||||
.finish(
|
.finish(
|
||||||
&mut finish_registration_rng,
|
&mut finish_registration_rng,
|
||||||
server_registration_start_result.message,
|
server_registration_start_result.message,
|
||||||
ClientRegistrationFinishParameters::WithIdentifiers(
|
ClientRegistrationFinishParameters::new(
|
||||||
Identifiers::ClientAndServerIdentifiers(id_u.to_vec(), id_s.to_vec()),
|
Some(Identifiers::ClientAndServerIdentifiers(
|
||||||
|
id_u.to_vec(),
|
||||||
|
id_s.to_vec(),
|
||||||
|
)),
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -402,9 +406,13 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
|||||||
.state
|
.state
|
||||||
.finish(
|
.finish(
|
||||||
server_login_start_result.message,
|
server_login_start_result.message,
|
||||||
ClientLoginFinishParameters::WithContextAndIdentifiers(
|
ClientLoginFinishParameters::new(
|
||||||
context.to_vec(),
|
Some(context.to_vec()),
|
||||||
Identifiers::ClientAndServerIdentifiers(id_u.to_vec(), id_s.to_vec()),
|
Some(Identifiers::ClientAndServerIdentifiers(
|
||||||
|
id_u.to_vec(),
|
||||||
|
id_s.to_vec(),
|
||||||
|
)),
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -544,8 +552,12 @@ fn test_registration_upload() -> Result<(), ProtocolError> {
|
|||||||
.finish(
|
.finish(
|
||||||
&mut finish_registration_rng,
|
&mut finish_registration_rng,
|
||||||
RegistrationResponse::deserialize(¶meters.registration_response[..])?,
|
RegistrationResponse::deserialize(¶meters.registration_response[..])?,
|
||||||
ClientRegistrationFinishParameters::WithIdentifiers(
|
ClientRegistrationFinishParameters::new(
|
||||||
Identifiers::ClientAndServerIdentifiers(parameters.id_u, parameters.id_s),
|
Some(Identifiers::ClientAndServerIdentifiers(
|
||||||
|
parameters.id_u,
|
||||||
|
parameters.id_s,
|
||||||
|
)),
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -662,9 +674,13 @@ fn test_credential_finalization() -> Result<(), ProtocolError> {
|
|||||||
CredentialResponse::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
CredentialResponse::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||||
¶meters.credential_response[..],
|
¶meters.credential_response[..],
|
||||||
)?,
|
)?,
|
||||||
ClientLoginFinishParameters::WithContextAndIdentifiers(
|
ClientLoginFinishParameters::new(
|
||||||
parameters.context,
|
Some(parameters.context),
|
||||||
Identifiers::ClientAndServerIdentifiers(parameters.id_u, parameters.id_s),
|
Some(Identifiers::ClientAndServerIdentifiers(
|
||||||
|
parameters.id_u,
|
||||||
|
parameters.id_s,
|
||||||
|
)),
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@@ -881,8 +881,8 @@ fn test_registration_upload<CS: CipherSuite>(tvs: &[&str]) -> Result<(), Protoco
|
|||||||
&mut finish_registration_rng,
|
&mut finish_registration_rng,
|
||||||
RegistrationResponse::deserialize(¶meters.registration_response[..]).unwrap(),
|
RegistrationResponse::deserialize(¶meters.registration_response[..]).unwrap(),
|
||||||
match parse_identifiers(parameters.client_identity, parameters.server_identity) {
|
match parse_identifiers(parameters.client_identity, parameters.server_identity) {
|
||||||
None => ClientRegistrationFinishParameters::Default,
|
None => ClientRegistrationFinishParameters::default(),
|
||||||
Some(ids) => ClientRegistrationFinishParameters::WithIdentifiers(ids),
|
Some(ids) => ClientRegistrationFinishParameters::new(Some(ids), None),
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -998,9 +998,9 @@ fn test_ke3<CS: CipherSuite>(tvs: &[&str]) -> Result<(), ProtocolError> {
|
|||||||
let client_login_finish_result = client_login_start_result.state.finish(
|
let client_login_finish_result = client_login_start_result.state.finish(
|
||||||
CredentialResponse::<CS>::deserialize(¶meters.KE2[..])?,
|
CredentialResponse::<CS>::deserialize(¶meters.KE2[..])?,
|
||||||
match parse_identifiers(parameters.client_identity, parameters.server_identity) {
|
match parse_identifiers(parameters.client_identity, parameters.server_identity) {
|
||||||
None => ClientLoginFinishParameters::WithContext(parameters.context),
|
None => ClientLoginFinishParameters::new(Some(parameters.context), None, None),
|
||||||
Some(ids) => {
|
Some(ids) => {
|
||||||
ClientLoginFinishParameters::WithContextAndIdentifiers(parameters.context, ids)
|
ClientLoginFinishParameters::new(Some(parameters.context), Some(ids), None)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user