Adding API for handling info fields (#88)
This commit is contained in:
+29
-22
@@ -28,13 +28,11 @@ use std::convert::TryFrom;
|
|||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use opaque_ke::{
|
use opaque_ke::{
|
||||||
ciphersuite::CipherSuite,
|
ciphersuite::CipherSuite, keypair::KeyPair, ClientLogin, ClientLoginFinishParameters,
|
||||||
keypair::KeyPair,
|
ClientLoginStartParameters, ClientRegistration, ClientRegistrationStartParameters,
|
||||||
opaque::{
|
LoginFirstMessage, LoginSecondMessage, LoginThirdMessage, RegisterFirstMessage,
|
||||||
ClientLogin, ClientRegistration, LoginFirstMessage, LoginSecondMessage, LoginThirdMessage,
|
RegisterSecondMessage, RegisterThirdMessage, ServerLogin, ServerLoginStartParameters,
|
||||||
RegisterFirstMessage, RegisterSecondMessage, RegisterThirdMessage, ServerLogin,
|
ServerRegistration,
|
||||||
ServerRegistration,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The ciphersuite trait allows to specify the underlying primitives
|
// The ciphersuite trait allows to specify the underlying primitives
|
||||||
@@ -55,8 +53,12 @@ fn account_registration(
|
|||||||
password: String,
|
password: String,
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
let mut client_rng = OsRng;
|
let mut client_rng = OsRng;
|
||||||
let (r1, client_state) =
|
let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||||
ClientRegistration::<Default>::start(password.as_bytes(), &mut client_rng).unwrap();
|
password.as_bytes(),
|
||||||
|
ClientRegistrationStartParameters::default(),
|
||||||
|
&mut client_rng,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let r1_bytes = r1.serialize();
|
let r1_bytes = r1.serialize();
|
||||||
|
|
||||||
// Client sends r1_bytes to server
|
// Client sends r1_bytes to server
|
||||||
@@ -64,6 +66,7 @@ fn account_registration(
|
|||||||
let mut server_rng = OsRng;
|
let mut server_rng = OsRng;
|
||||||
let (r2, server_state) = ServerRegistration::<Default>::start(
|
let (r2, server_state) = ServerRegistration::<Default>::start(
|
||||||
RegisterFirstMessage::deserialize(&r1_bytes[..]).unwrap(),
|
RegisterFirstMessage::deserialize(&r1_bytes[..]).unwrap(),
|
||||||
|
server_kp.public(),
|
||||||
&mut server_rng,
|
&mut server_rng,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -74,7 +77,6 @@ fn account_registration(
|
|||||||
let (r3, _) = client_state
|
let (r3, _) = client_state
|
||||||
.finish(
|
.finish(
|
||||||
RegisterSecondMessage::deserialize(&r2_bytes[..]).unwrap(),
|
RegisterSecondMessage::deserialize(&r2_bytes[..]).unwrap(),
|
||||||
server_kp.public(),
|
|
||||||
&mut client_rng,
|
&mut client_rng,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -95,45 +97,50 @@ fn account_login(
|
|||||||
password_file_bytes: &[u8],
|
password_file_bytes: &[u8],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut client_rng = OsRng;
|
let mut client_rng = OsRng;
|
||||||
let (l1, client_state) =
|
let client_login_start_result = ClientLogin::<Default>::start(
|
||||||
ClientLogin::<Default>::start(password.as_bytes(), &mut client_rng).unwrap();
|
password.as_bytes(),
|
||||||
let l1_bytes = l1.serialize();
|
&mut client_rng,
|
||||||
|
ClientLoginStartParameters::default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let l1_bytes = client_login_start_result.credential_request.serialize();
|
||||||
|
|
||||||
// Client sends l1_bytes to server
|
// Client sends l1_bytes to server
|
||||||
|
|
||||||
let password_file = ServerRegistration::<Default>::try_from(password_file_bytes).unwrap();
|
let password_file = ServerRegistration::<Default>::try_from(password_file_bytes).unwrap();
|
||||||
let mut server_rng = OsRng;
|
let mut server_rng = OsRng;
|
||||||
let (l2, server_state) = ServerLogin::start(
|
let server_login_start_result = ServerLogin::start(
|
||||||
password_file,
|
password_file,
|
||||||
&server_kp.private(),
|
&server_kp.private(),
|
||||||
LoginFirstMessage::deserialize(&l1_bytes[..]).unwrap(),
|
LoginFirstMessage::deserialize(&l1_bytes[..]).unwrap(),
|
||||||
&mut server_rng,
|
&mut server_rng,
|
||||||
|
ServerLoginStartParameters::default(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let l2_bytes = l2.serialize();
|
let l2_bytes = server_login_start_result.credential_response.serialize();
|
||||||
|
|
||||||
// Server sends l2_bytes to client
|
// Server sends l2_bytes to client
|
||||||
|
|
||||||
let result = client_state.finish(
|
let result = client_login_start_result.client_login_state.finish(
|
||||||
LoginSecondMessage::deserialize(&l2_bytes[..]).unwrap(),
|
LoginSecondMessage::deserialize(&l2_bytes[..]).unwrap(),
|
||||||
&server_kp.public(),
|
ClientLoginFinishParameters::default(),
|
||||||
&mut client_rng,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
// Client-detected login failure
|
// Client-detected login failure
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let (l3, client_shared_secret, _) = result.unwrap();
|
let client_login_finish_result = result.unwrap();
|
||||||
let l3_bytes = l3.serialize();
|
let l3_bytes = client_login_finish_result.key_exchange.serialize();
|
||||||
|
|
||||||
// Client sends l3_bytes to server
|
// Client sends l3_bytes to server
|
||||||
|
|
||||||
let server_shared_secret = server_state
|
let server_login_finish_result = server_login_start_result
|
||||||
|
.server_login_state
|
||||||
.finish(LoginThirdMessage::deserialize(&l3_bytes[..]).unwrap())
|
.finish(LoginThirdMessage::deserialize(&l3_bytes[..]).unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
client_shared_secret == server_shared_secret
|
client_login_finish_result.session_secret == server_login_finish_result.session_secret
|
||||||
}
|
}
|
||||||
|
|
||||||
// A function run on the client which extracts a username and password from the CLI
|
// A function run on the client which extracts a username and password from the CLI
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ pub trait KeyExchange<D: Hash, KeyFormat: KeyPair> {
|
|||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>;
|
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>;
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||||
fn generate_ke2<R: RngCore + CryptoRng>(
|
fn generate_ke2<R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
l1_bytes: Vec<u8>,
|
l1_bytes: Vec<u8>,
|
||||||
@@ -33,24 +33,30 @@ pub trait KeyExchange<D: Hash, KeyFormat: KeyPair> {
|
|||||||
ke1_message: Self::KE1Message,
|
ke1_message: Self::KE1Message,
|
||||||
client_s_pk: KeyFormat::Repr,
|
client_s_pk: KeyFormat::Repr,
|
||||||
server_s_sk: KeyFormat::Repr,
|
server_s_sk: KeyFormat::Repr,
|
||||||
|
id_u: Vec<u8>,
|
||||||
|
id_s: Vec<u8>,
|
||||||
info: Vec<u8>,
|
info: Vec<u8>,
|
||||||
e_info: Vec<u8>,
|
e_info: Vec<u8>,
|
||||||
) -> Result<(Self::KE2State, Self::KE2Message), ProtocolError>;
|
) -> Result<(Vec<u8>, Self::KE2State, Self::KE2Message), ProtocolError>;
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||||
fn generate_ke3(
|
fn generate_ke3(
|
||||||
l2_component: Vec<u8>,
|
l2_component: Vec<u8>,
|
||||||
ke2_message: Self::KE2Message,
|
ke2_message: Self::KE2Message,
|
||||||
ke1_state: &Self::KE1State,
|
ke1_state: &Self::KE1State,
|
||||||
server_s_pk: KeyFormat::Repr,
|
server_s_pk: KeyFormat::Repr,
|
||||||
client_s_sk: KeyFormat::Repr,
|
client_s_sk: KeyFormat::Repr,
|
||||||
|
id_u: Vec<u8>,
|
||||||
|
id_s: Vec<u8>,
|
||||||
info: Vec<u8>,
|
info: Vec<u8>,
|
||||||
e_info: Vec<u8>,
|
e_info: Vec<u8>,
|
||||||
) -> Result<(Vec<u8>, Self::KE3Message), ProtocolError>;
|
) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Self::KE3Message), ProtocolError>;
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn finish_ke(
|
fn finish_ke(
|
||||||
ke3_message: Self::KE3Message,
|
ke3_message: Self::KE3Message,
|
||||||
ke2_state: &Self::KE2State,
|
ke2_state: &Self::KE2State,
|
||||||
) -> Result<Vec<u8>, ProtocolError>;
|
) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>), ProtocolError>;
|
||||||
|
|
||||||
fn ke1_state_size() -> usize;
|
fn ke1_state_size() -> usize;
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn generate_ke2<R: RngCore + CryptoRng>(
|
fn generate_ke2<R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
l1_bytes: Vec<u8>,
|
l1_bytes: Vec<u8>,
|
||||||
@@ -88,9 +89,11 @@ impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
|||||||
ke1_message: Self::KE1Message,
|
ke1_message: Self::KE1Message,
|
||||||
client_s_pk: KeyFormat::Repr,
|
client_s_pk: KeyFormat::Repr,
|
||||||
server_s_sk: KeyFormat::Repr,
|
server_s_sk: KeyFormat::Repr,
|
||||||
|
id_u: Vec<u8>,
|
||||||
|
id_s: Vec<u8>,
|
||||||
info: Vec<u8>,
|
info: Vec<u8>,
|
||||||
e_info: Vec<u8>,
|
e_info: Vec<u8>,
|
||||||
) -> Result<(Self::KE2State, Self::KE2Message), ProtocolError> {
|
) -> Result<(Vec<u8>, Self::KE2State, Self::KE2Message), ProtocolError> {
|
||||||
let server_e_kp = KeyFormat::generate_random(rng)?;
|
let server_e_kp = KeyFormat::generate_random(rng)?;
|
||||||
let server_nonce: GenericArray<u8, NonceLen> = {
|
let server_nonce: GenericArray<u8, NonceLen> = {
|
||||||
let mut server_nonce_bytes = [0u8; NONCE_LEN];
|
let mut server_nonce_bytes = [0u8; NONCE_LEN];
|
||||||
@@ -103,14 +106,14 @@ impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
|||||||
pk1: ke1_message.client_e_pk.clone(),
|
pk1: ke1_message.client_e_pk.clone(),
|
||||||
sk1: server_e_kp.private().clone(),
|
sk1: server_e_kp.private().clone(),
|
||||||
pk2: ke1_message.client_e_pk,
|
pk2: ke1_message.client_e_pk,
|
||||||
sk2: server_s_sk.clone(),
|
sk2: server_s_sk,
|
||||||
pk3: client_s_pk.clone(),
|
pk3: client_s_pk,
|
||||||
sk3: server_e_kp.private().clone(),
|
sk3: server_e_kp.private().clone(),
|
||||||
},
|
},
|
||||||
&ke1_message.client_nonce,
|
&ke1_message.client_nonce,
|
||||||
&server_nonce,
|
&server_nonce,
|
||||||
&client_s_pk.to_arr(),
|
&id_u,
|
||||||
&KeyFormat::public_from_private(&server_s_sk).to_arr(),
|
&id_s,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut hasher = D::new();
|
let mut hasher = D::new();
|
||||||
@@ -142,6 +145,7 @@ impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
|||||||
let hashed_transcript = hasher3.finalize();
|
let hashed_transcript = hasher3.finalize();
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
|
ke1_message.info,
|
||||||
KE2State {
|
KE2State {
|
||||||
km3,
|
km3,
|
||||||
hashed_transcript,
|
hashed_transcript,
|
||||||
@@ -157,28 +161,31 @@ impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn generate_ke3(
|
fn generate_ke3(
|
||||||
l2_component: Vec<u8>,
|
l2_component: Vec<u8>,
|
||||||
ke2_message: Self::KE2Message,
|
ke2_message: Self::KE2Message,
|
||||||
ke1_state: &Self::KE1State,
|
ke1_state: &Self::KE1State,
|
||||||
server_s_pk: KeyFormat::Repr,
|
server_s_pk: KeyFormat::Repr,
|
||||||
client_s_sk: KeyFormat::Repr,
|
client_s_sk: KeyFormat::Repr,
|
||||||
|
id_u: Vec<u8>,
|
||||||
|
id_s: Vec<u8>,
|
||||||
info: Vec<u8>,
|
info: Vec<u8>,
|
||||||
e_info: Vec<u8>,
|
e_info: Vec<u8>,
|
||||||
) -> Result<(Vec<u8>, Self::KE3Message), ProtocolError> {
|
) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Self::KE3Message), ProtocolError> {
|
||||||
let (session_secret, km2, km3) = derive_3dh_keys::<KeyFormat, D>(
|
let (session_secret, km2, km3) = derive_3dh_keys::<KeyFormat, D>(
|
||||||
TripleDHComponents {
|
TripleDHComponents {
|
||||||
pk1: ke2_message.server_e_pk.clone(),
|
pk1: ke2_message.server_e_pk.clone(),
|
||||||
sk1: ke1_state.client_e_sk.clone(),
|
sk1: ke1_state.client_e_sk.clone(),
|
||||||
pk2: server_s_pk.clone(),
|
pk2: server_s_pk,
|
||||||
sk2: ke1_state.client_e_sk.clone(),
|
sk2: ke1_state.client_e_sk.clone(),
|
||||||
pk3: ke2_message.server_e_pk.clone(),
|
pk3: ke2_message.server_e_pk.clone(),
|
||||||
sk3: client_s_sk.clone(),
|
sk3: client_s_sk,
|
||||||
},
|
},
|
||||||
&ke1_state.client_nonce,
|
&ke1_state.client_nonce,
|
||||||
&ke2_message.server_nonce,
|
&ke2_message.server_nonce,
|
||||||
&KeyFormat::public_from_private(&client_s_sk).to_arr(),
|
&id_u,
|
||||||
&server_s_pk.to_arr(),
|
&id_s,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let transcript: Vec<u8> = [
|
let transcript: Vec<u8> = [
|
||||||
@@ -219,6 +226,8 @@ impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
|||||||
client_mac.update(&transcript_with_ke3);
|
client_mac.update(&transcript_with_ke3);
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
|
ke2_message.info,
|
||||||
|
ke2_message.e_info, // TODO: need to decrypt
|
||||||
session_secret.to_vec(),
|
session_secret.to_vec(),
|
||||||
KE3Message {
|
KE3Message {
|
||||||
info,
|
info,
|
||||||
@@ -228,10 +237,11 @@ impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn finish_ke(
|
fn finish_ke(
|
||||||
ke3_message: Self::KE3Message,
|
ke3_message: Self::KE3Message,
|
||||||
ke2_state: &Self::KE2State,
|
ke2_state: &Self::KE2State,
|
||||||
) -> Result<Vec<u8>, ProtocolError> {
|
) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>), ProtocolError> {
|
||||||
let transcript_with_ke3 = [
|
let transcript_with_ke3 = [
|
||||||
ke2_state.hashed_transcript.to_vec(),
|
ke2_state.hashed_transcript.to_vec(),
|
||||||
ke3_message.to_bytes_without_mac(),
|
ke3_message.to_bytes_without_mac(),
|
||||||
@@ -247,7 +257,11 @@ impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ke2_state.session_secret.to_vec())
|
Ok((
|
||||||
|
ke3_message.info,
|
||||||
|
ke3_message.e_info, // TODO: need to decrypt
|
||||||
|
ke2_state.session_secret.to_vec(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ke1_state_size() -> usize {
|
fn ke1_state_size() -> usize {
|
||||||
|
|||||||
+74
-48
@@ -71,7 +71,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
//! # opaque::ServerRegistration,
|
//! # ServerRegistration,
|
||||||
//! # keypair::{KeyPair, X25519KeyPair},
|
//! # keypair::{KeyPair, X25519KeyPair},
|
||||||
//! # slow_hash::NoOpHash,
|
//! # slow_hash::NoOpHash,
|
||||||
//! # };
|
//! # };
|
||||||
@@ -84,11 +84,12 @@
|
|||||||
//! # type Hash = sha2::Sha256;
|
//! # type Hash = sha2::Sha256;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
//! # }
|
//! # }
|
||||||
//! use opaque_ke::opaque::ClientRegistration;
|
//! use opaque_ke::{ClientRegistration, ClientRegistrationStartParameters};
|
||||||
//! use rand_core::{OsRng, RngCore};
|
//! use rand_core::{OsRng, RngCore};
|
||||||
//! let mut client_rng = OsRng;
|
//! let mut client_rng = OsRng;
|
||||||
//! let (r1, client_state) = ClientRegistration::<Default>::start(
|
//! let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||||
//! b"password",
|
//! b"password",
|
||||||
|
//! ClientRegistrationStartParameters::default(),
|
||||||
//! &mut client_rng,
|
//! &mut client_rng,
|
||||||
//! )?;
|
//! )?;
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
@@ -101,7 +102,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
//! # opaque::ClientRegistration,
|
//! # ClientRegistration, ClientRegistrationStartParameters,
|
||||||
//! # keypair::{KeyPair, X25519KeyPair},
|
//! # keypair::{KeyPair, X25519KeyPair},
|
||||||
//! # slow_hash::NoOpHash,
|
//! # slow_hash::NoOpHash,
|
||||||
//! # };
|
//! # };
|
||||||
@@ -118,11 +119,13 @@
|
|||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
|
//! # ClientRegistrationStartParameters::default(),
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! use opaque_ke::opaque::ServerRegistration;
|
//! use opaque_ke::ServerRegistration;
|
||||||
//! let mut server_rng = OsRng;
|
//! let mut server_rng = OsRng;
|
||||||
//! let (r2, server_state) = ServerRegistration::<Default>::start(r1, &mut server_rng)?;
|
//! let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
||||||
|
//! let (r2, server_state) = ServerRegistration::<Default>::start(r1, server_kp.public(), &mut server_rng)?;
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
//! ```
|
//! ```
|
||||||
//! `r2` is returned to the client, and `server_state` must be persisted on the server for the final step of server
|
//! `r2` is returned to the client, and `server_state` must be persisted on the server for the final step of server
|
||||||
@@ -134,7 +137,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
//! # opaque::{ClientRegistration, ServerRegistration},
|
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration,
|
||||||
//! # keypair::{KeyPair, X25519KeyPair},
|
//! # keypair::{KeyPair, X25519KeyPair},
|
||||||
//! # slow_hash::NoOpHash,
|
//! # slow_hash::NoOpHash,
|
||||||
//! # };
|
//! # };
|
||||||
@@ -151,13 +154,14 @@
|
|||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
|
//! # ClientRegistrationStartParameters::default(),
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # let mut server_rng = OsRng;
|
//! # let mut server_rng = OsRng;
|
||||||
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, &mut server_rng)?;
|
|
||||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
||||||
|
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, server_kp.public(), &mut server_rng)?;
|
||||||
//! let (r3, export_key_registration) =
|
//! let (r3, export_key_registration) =
|
||||||
//! client_state.finish(r2, server_kp.public(), &mut client_rng)?;
|
//! client_state.finish(r2, &mut client_rng)?;
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
//! ```
|
//! ```
|
||||||
//! `r3` is sent to the server, and the client can optionally use `export_key_registration` for applications that choose to
|
//! `r3` is sent to the server, and the client can optionally use `export_key_registration` for applications that choose to
|
||||||
@@ -168,7 +172,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
//! # opaque::{ClientRegistration, ServerRegistration},
|
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration,
|
||||||
//! # keypair::{KeyPair, X25519KeyPair},
|
//! # keypair::{KeyPair, X25519KeyPair},
|
||||||
//! # slow_hash::NoOpHash,
|
//! # slow_hash::NoOpHash,
|
||||||
//! # };
|
//! # };
|
||||||
@@ -185,12 +189,13 @@
|
|||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
|
//! # ClientRegistrationStartParameters::default(),
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # let mut server_rng = OsRng;
|
//! # let mut server_rng = OsRng;
|
||||||
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, &mut server_rng)?;
|
|
||||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
||||||
//! # let (r3, export_key_registration) = client_state.finish(r2, server_kp.public(), &mut client_rng)?;
|
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, server_kp.public(), &mut server_rng)?;
|
||||||
|
//! # let (r3, export_key_registration) = client_state.finish(r2, &mut client_rng)?;
|
||||||
//! let password_file = server_state.finish(r3)?;
|
//! let password_file = server_state.finish(r3)?;
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
//! ```
|
//! ```
|
||||||
@@ -210,7 +215,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
//! # opaque::{ClientRegistration, ServerRegistration, ServerLogin, LoginThirdMessage},
|
//! # ClientRegistration, ServerRegistration, ServerLogin, LoginThirdMessage,
|
||||||
//! # keypair::{KeyPair, X25519KeyPair},
|
//! # keypair::{KeyPair, X25519KeyPair},
|
||||||
//! # slow_hash::NoOpHash,
|
//! # slow_hash::NoOpHash,
|
||||||
//! # };
|
//! # };
|
||||||
@@ -224,23 +229,25 @@
|
|||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand_core::{OsRng, RngCore};
|
//! # use rand_core::{OsRng, RngCore};
|
||||||
//! use opaque_ke::opaque::ClientLogin;
|
//! use opaque_ke::{ClientLogin, ClientLoginStartParameters};
|
||||||
//! let mut client_rng = OsRng;
|
//! let mut client_rng = OsRng;
|
||||||
//! let (l1, client_state) = ClientLogin::<Default>::start(
|
//! let client_login_start_result = ClientLogin::<Default>::start(
|
||||||
//! b"password",
|
//! b"password",
|
||||||
//! &mut client_rng,
|
//! &mut client_rng,
|
||||||
|
//! ClientLoginStartParameters::default(),
|
||||||
//! )?;
|
//! )?;
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
//! ```
|
//! ```
|
||||||
//! `l1` is sent to the server, and `client_state` must be persisted on the client for the final step of client login.
|
//! `client_login_start_result.credential_request` is sent to the server, and `client_login_start_result.client_login_state`
|
||||||
|
//! must be persisted on the client for the final step of client login.
|
||||||
//!
|
//!
|
||||||
//! In the second step (server login start), the server takes as input the `l1` message from the client, the server's
|
//! In the second step (server login start), the server takes as input the `l1` message from the client, the server's
|
||||||
//! private key `server_kp.private()`, along with a serialized version of the password file, `password_file_bytes`, and
|
//! private key `server_kp.private()`, along with a serialized version of the password file, `password_file_bytes`, and
|
||||||
//! runs `ServerLogin::start` to produce `l2`:
|
//! runs `ServerLogin::start` to produce `server_login_start_result`:
|
||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, LoginThirdMessage},
|
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, LoginThirdMessage,
|
||||||
//! # keypair::{KeyPair, X25519KeyPair},
|
//! # keypair::{KeyPair, X25519KeyPair},
|
||||||
//! # slow_hash::NoOpHash,
|
//! # slow_hash::NoOpHash,
|
||||||
//! # };
|
//! # };
|
||||||
@@ -257,26 +264,29 @@
|
|||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
|
//! # ClientRegistrationStartParameters::default(),
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # let mut server_rng = OsRng;
|
//! # let mut server_rng = OsRng;
|
||||||
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, &mut server_rng)?;
|
|
||||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
||||||
//! # let (r3, export_key_registration) = client_state.finish(r2, server_kp.public(), &mut client_rng)?;
|
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, server_kp.public(), &mut server_rng)?;
|
||||||
|
//! # let (r3, export_key_registration) = client_state.finish(r2, &mut client_rng)?;
|
||||||
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
||||||
//! # let (l1, client_state) = ClientLogin::<Default>::start(
|
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
|
//! # ClientLoginStartParameters::default(),
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! use opaque_ke::opaque::ServerLogin;
|
//! use opaque_ke::{ServerLogin, ServerLoginStartParameters};
|
||||||
//! use std::convert::TryFrom;
|
//! use std::convert::TryFrom;
|
||||||
//! let password_file = ServerRegistration::<Default>::try_from(&password_file_bytes[..])?;
|
//! let password_file = ServerRegistration::<Default>::try_from(&password_file_bytes[..])?;
|
||||||
//! let mut server_rng = OsRng;
|
//! let mut server_rng = OsRng;
|
||||||
//! let (l2, server_state) =
|
//! let server_login_start_result =
|
||||||
//! ServerLogin::start(password_file, &server_kp.private(), l1, &mut server_rng)?;
|
//! ServerLogin::start(password_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
//! ```
|
//! ```
|
||||||
//! `l2` is returned to the client, and `server_state` must be persisted on the server for the final step of server login.
|
//! `server_login_start_result.credential_response` is returned to the client, and `server_login_start_result.server_login_state`
|
||||||
|
//! must be persisted on the server for the final step of server login.
|
||||||
//!
|
//!
|
||||||
//! In the third step (client login finish), the client takes as input the `l2` message from the server, along with the
|
//! In the third step (client login finish), the client takes as input the `l2` message from the server, along with the
|
||||||
//! server's static public key `server_kp.public()`, and uses `client_state` from the first step to run `finish` and produce
|
//! server's static public key `server_kp.public()`, and uses `client_state` from the first step to run `finish` and produce
|
||||||
@@ -284,7 +294,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, ServerLogin, LoginThirdMessage},
|
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, LoginThirdMessage,
|
||||||
//! # keypair::{KeyPair, X25519KeyPair},
|
//! # keypair::{KeyPair, X25519KeyPair},
|
||||||
//! # slow_hash::NoOpHash,
|
//! # slow_hash::NoOpHash,
|
||||||
//! # };
|
//! # };
|
||||||
@@ -301,30 +311,31 @@
|
|||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
|
//! # ClientRegistrationStartParameters::default(),
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # let mut server_rng = OsRng;
|
//! # let mut server_rng = OsRng;
|
||||||
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, &mut server_rng)?;
|
|
||||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
||||||
//! # let (r3, export_key_registration) = client_state.finish(r2, server_kp.public(), &mut client_rng)?;
|
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, server_kp.public(), &mut server_rng)?;
|
||||||
|
//! # let (r3, export_key_registration) = client_state.finish(r2, &mut client_rng)?;
|
||||||
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
||||||
//! # let (l1, client_state) = ClientLogin::<Default>::start(
|
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
|
//! # ClientLoginStartParameters::default(),
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # use std::convert::TryFrom;
|
//! # use std::convert::TryFrom;
|
||||||
//! # let password_file =
|
//! # let password_file =
|
||||||
//! # ServerRegistration::<Default>::try_from(
|
//! # ServerRegistration::<Default>::try_from(
|
||||||
//! # &password_file_bytes[..],
|
//! # &password_file_bytes[..],
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # let (l2, server_state) =
|
//! # let server_login_start_result =
|
||||||
//! # ServerLogin::start(password_file, &server_kp.private(), l1, &mut server_rng)?;
|
//! # ServerLogin::start(password_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||||
//! let (l3, client_shared_secret, export_key_login) = client_state.finish(
|
//! let client_login_finish_result = client_login_start_result.client_login_state.finish(
|
||||||
//! l2,
|
//! server_login_start_result.credential_response,
|
||||||
//! &server_kp.public(),
|
//! ClientLoginFinishParameters::default(),
|
||||||
//! &mut client_rng,
|
|
||||||
//! )?;
|
//! )?;
|
||||||
//! assert_eq!(export_key_registration, export_key_login);
|
//! assert_eq!(export_key_registration, client_login_finish_result.export_key);
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
//! ```
|
//! ```
|
||||||
//! Note that if the client supplies a tuple (password, pepper, server public key) that does not match the tuple
|
//! Note that if the client supplies a tuple (password, pepper, server public key) that does not match the tuple
|
||||||
@@ -339,7 +350,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! # use opaque_ke::{
|
//! # use opaque_ke::{
|
||||||
//! # errors::ProtocolError,
|
//! # errors::ProtocolError,
|
||||||
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, ServerLogin, LoginThirdMessage},
|
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, LoginThirdMessage,
|
||||||
//! # keypair::{KeyPair, X25519KeyPair},
|
//! # keypair::{KeyPair, X25519KeyPair},
|
||||||
//! # slow_hash::NoOpHash,
|
//! # slow_hash::NoOpHash,
|
||||||
//! # };
|
//! # };
|
||||||
@@ -356,31 +367,32 @@
|
|||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
|
//! # ClientRegistrationStartParameters::default(),
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # let mut server_rng = OsRng;
|
//! # let mut server_rng = OsRng;
|
||||||
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, &mut server_rng)?;
|
|
||||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?;
|
||||||
//! # let (r3, export_key) = client_state.finish(r2, server_kp.public(), &mut client_rng)?;
|
//! # let (r2, server_state) = ServerRegistration::<Default>::start(r1, server_kp.public(), &mut server_rng)?;
|
||||||
|
//! # let (r3, export_key) = client_state.finish(r2, &mut client_rng)?;
|
||||||
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
||||||
//! # let (l1, client_state) = ClientLogin::<Default>::start(
|
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||||
//! # b"password",
|
//! # b"password",
|
||||||
//! # &mut client_rng,
|
//! # &mut client_rng,
|
||||||
|
//! # ClientLoginStartParameters::default(),
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # use std::convert::TryFrom;
|
//! # use std::convert::TryFrom;
|
||||||
//! # let password_file =
|
//! # let password_file =
|
||||||
//! # ServerRegistration::<Default>::try_from(
|
//! # ServerRegistration::<Default>::try_from(
|
||||||
//! # &password_file_bytes[..],
|
//! # &password_file_bytes[..],
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! # let (l2, server_state) =
|
//! # let server_login_start_result =
|
||||||
//! # ServerLogin::start(password_file, &server_kp.private(), l1, &mut server_rng)?;
|
//! # ServerLogin::start(password_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||||
//! # let (l3, client_shared_secret, export_key) = client_state.finish(
|
//! # let client_login_finish_result = client_login_start_result.client_login_state.finish(
|
||||||
//! # l2,
|
//! # server_login_start_result.credential_response,
|
||||||
//! # &server_kp.public(),
|
//! # ClientLoginFinishParameters::default(),
|
||||||
//! # &mut client_rng,
|
|
||||||
//! # )?;
|
//! # )?;
|
||||||
//! let server_shared_secret = server_state.finish(l3)?;
|
//! let server_login_finish_result = server_login_start_result.server_login_state.finish(client_login_finish_result.key_exchange)?;
|
||||||
//! assert_eq!(client_shared_secret, server_shared_secret);
|
//! assert_eq!(client_login_finish_result.session_secret, server_login_finish_result.session_secret);
|
||||||
//! # Ok::<(), ProtocolError>(())
|
//! # Ok::<(), ProtocolError>(())
|
||||||
//! ```
|
//! ```
|
||||||
//! If the protocol completes successfully, then the server obtains a `server_shared_secret` which is guaranteed to
|
//! If the protocol completes successfully, then the server obtains a `server_shared_secret` which is guaranteed to
|
||||||
@@ -400,7 +412,9 @@ compile_error!(
|
|||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
|
||||||
// High-level API
|
// High-level API
|
||||||
pub mod opaque;
|
mod opaque;
|
||||||
|
|
||||||
|
mod messages;
|
||||||
|
|
||||||
pub mod ciphersuite;
|
pub mod ciphersuite;
|
||||||
mod envelope;
|
mod envelope;
|
||||||
@@ -425,3 +439,15 @@ mod serialization;
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
// Exports
|
||||||
|
|
||||||
|
pub use crate::messages::{
|
||||||
|
LoginFirstMessage, LoginSecondMessage, LoginThirdMessage, RegisterFirstMessage,
|
||||||
|
RegisterSecondMessage, RegisterThirdMessage,
|
||||||
|
};
|
||||||
|
pub use crate::opaque::{ClientLogin, ClientRegistration, ServerLogin, ServerRegistration};
|
||||||
|
pub use crate::opaque::{
|
||||||
|
ClientLoginFinishParameters, ClientLoginStartParameters, ClientRegistrationStartParameters,
|
||||||
|
ServerLoginStartParameters,
|
||||||
|
};
|
||||||
|
|||||||
+471
@@ -0,0 +1,471 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
//! Contains the messages used for OPAQUE
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ciphersuite::CipherSuite,
|
||||||
|
envelope::{Envelope, EnvelopeCredentialsFormat},
|
||||||
|
errors::{
|
||||||
|
utils::{check_slice_size, check_slice_size_atleast},
|
||||||
|
PakeError, ProtocolError,
|
||||||
|
},
|
||||||
|
group::Group,
|
||||||
|
hash::Hash,
|
||||||
|
key_exchange::traits::{KeyExchange, ToBytes},
|
||||||
|
keypair::{KeyPair, SizedBytesExt},
|
||||||
|
serialization::{
|
||||||
|
serialize, tokenize, u8_to_credential_type, CredentialType, ProtocolMessageType,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use generic_array::{typenum::Unsigned, GenericArray};
|
||||||
|
use generic_bytes::SizedBytes;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
// Messages
|
||||||
|
// =========
|
||||||
|
|
||||||
|
/// The message sent by the client to the server, to initiate registration
|
||||||
|
pub struct RegisterFirstMessage<Grp> {
|
||||||
|
/// blinded password information
|
||||||
|
pub(crate) alpha: Grp,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Grp: Group> TryFrom<&[u8]> for RegisterFirstMessage<Grp> {
|
||||||
|
type Error = ProtocolError;
|
||||||
|
fn try_from(first_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||||
|
let elem_len = Grp::ElemLen::to_usize();
|
||||||
|
let checked_slice = check_slice_size(first_message_bytes, 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[checked_slice.len() - elem_len..]);
|
||||||
|
let alpha = Grp::from_element_slice(arr)?;
|
||||||
|
Ok(Self { alpha })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Grp: Group> RegisterFirstMessage<Grp> {
|
||||||
|
/// Byte representation for the registration request
|
||||||
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
self.alpha.to_arr().to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut registration_request: Vec<u8> = Vec::new();
|
||||||
|
registration_request.extend_from_slice(&serialize(&self.alpha.to_arr(), 2));
|
||||||
|
|
||||||
|
let mut output: Vec<u8> = Vec::new();
|
||||||
|
output.push(ProtocolMessageType::from(self) as u8 + 1);
|
||||||
|
output.extend_from_slice(&serialize(®istration_request, 3));
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||||
|
if input.is_empty()
|
||||||
|
|| input.is_empty()
|
||||||
|
|| input[0] != ProtocolMessageType::RegistrationRequest as u8 + 1
|
||||||
|
{
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (data, remainder) = tokenize(&input[1..], 3)?;
|
||||||
|
if !remainder.is_empty() {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
let (alpha_bytes, remainder) = tokenize(&data, 2)?;
|
||||||
|
|
||||||
|
if !remainder.is_empty() {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let checked_slice = check_slice_size(
|
||||||
|
&alpha_bytes,
|
||||||
|
Grp::ElemLen::to_usize(),
|
||||||
|
"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 = Grp::from_element_slice(arr)?;
|
||||||
|
Ok(Self { alpha })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The answer sent by the server to the user, upon reception of the
|
||||||
|
/// registration attempt
|
||||||
|
pub struct RegisterSecondMessage<Grp> {
|
||||||
|
/// The server's oprf output
|
||||||
|
pub(crate) beta: Grp,
|
||||||
|
/// Server's static public key
|
||||||
|
pub(crate) server_s_pk: Vec<u8>,
|
||||||
|
/// Envelope credentials format
|
||||||
|
pub(crate) ecf: EnvelopeCredentialsFormat,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Grp> TryFrom<&[u8]> for RegisterSecondMessage<Grp>
|
||||||
|
where
|
||||||
|
Grp: Group,
|
||||||
|
{
|
||||||
|
type Error = ProtocolError;
|
||||||
|
|
||||||
|
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||||
|
let elem_len = Grp::ElemLen::to_usize();
|
||||||
|
let checked_slice = check_slice_size_atleast(bytes, elem_len, "second_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 beta = Grp::from_element_slice(arr)?;
|
||||||
|
|
||||||
|
let server_s_pk = checked_slice[elem_len..].to_vec();
|
||||||
|
|
||||||
|
// Note that we use a default envelope credentials format here, since it
|
||||||
|
// is not included in the byte representation
|
||||||
|
let ecf = EnvelopeCredentialsFormat::default()?;
|
||||||
|
Ok(Self {
|
||||||
|
beta,
|
||||||
|
server_s_pk,
|
||||||
|
ecf,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Grp> RegisterSecondMessage<Grp>
|
||||||
|
where
|
||||||
|
Grp: Group,
|
||||||
|
{
|
||||||
|
/// Byte representation for the registration response message. This does not
|
||||||
|
/// include the envelope credentials format
|
||||||
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
[&self.beta.to_arr().to_vec()[..], &self.server_s_pk[..]].concat()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut registration_response: Vec<u8> = Vec::new();
|
||||||
|
registration_response.extend_from_slice(&serialize(&self.beta.to_arr(), 2));
|
||||||
|
registration_response.extend_from_slice(&serialize(&self.server_s_pk, 2));
|
||||||
|
|
||||||
|
// Handle ecf serialization
|
||||||
|
let secret_credentials: Vec<u8> = self
|
||||||
|
.ecf
|
||||||
|
.secret_credentials
|
||||||
|
.iter()
|
||||||
|
.map(|&x| x as u8 + 1)
|
||||||
|
.collect();
|
||||||
|
let cleartext_credentials: Vec<u8> = self
|
||||||
|
.ecf
|
||||||
|
.cleartext_credentials
|
||||||
|
.iter()
|
||||||
|
.map(|&x| x as u8 + 1)
|
||||||
|
.collect();
|
||||||
|
let ecf_serialized = [
|
||||||
|
serialize(&secret_credentials, 1),
|
||||||
|
serialize(&cleartext_credentials, 1),
|
||||||
|
]
|
||||||
|
.concat();
|
||||||
|
registration_response.extend_from_slice(&ecf_serialized);
|
||||||
|
|
||||||
|
let mut output: Vec<u8> = Vec::new();
|
||||||
|
output.push(ProtocolMessageType::from(self) as u8 + 1);
|
||||||
|
output.extend_from_slice(&serialize(®istration_response, 3));
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||||
|
if input.is_empty() || input[0] != ProtocolMessageType::RegistrationResponse as u8 + 1 {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (data, remainder) = tokenize(&input[1..], 3)?;
|
||||||
|
if !remainder.is_empty() {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (beta_bytes, remainder) = tokenize(&data, 2)?;
|
||||||
|
let (server_s_pk, remainder) = tokenize(&remainder, 2)?;
|
||||||
|
|
||||||
|
// Handle ecf deserialization
|
||||||
|
let (secret_credentials, remainder) = tokenize(&remainder, 1)?;
|
||||||
|
let (cleartext_credentials, remainder) = tokenize(&remainder, 1)?;
|
||||||
|
let sc = secret_credentials
|
||||||
|
.iter()
|
||||||
|
.map(|x| u8_to_credential_type(*x).ok_or(PakeError::SerializationError))
|
||||||
|
.collect::<Result<Vec<CredentialType>, _>>()?;
|
||||||
|
let cc = cleartext_credentials
|
||||||
|
.iter()
|
||||||
|
.map(|x| u8_to_credential_type(*x).ok_or(PakeError::SerializationError))
|
||||||
|
.collect::<Result<Vec<CredentialType>, _>>()?;
|
||||||
|
let ecf = EnvelopeCredentialsFormat::new(sc, cc)?;
|
||||||
|
|
||||||
|
if !remainder.is_empty() {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let checked_slice = check_slice_size(
|
||||||
|
&beta_bytes,
|
||||||
|
Grp::ElemLen::to_usize(),
|
||||||
|
"second_message_bytes",
|
||||||
|
)?;
|
||||||
|
// Check that the message is actually containing an element of the
|
||||||
|
// correct subgroup
|
||||||
|
let arr = GenericArray::from_slice(&checked_slice);
|
||||||
|
let beta = Grp::from_element_slice(arr)?;
|
||||||
|
Ok(Self {
|
||||||
|
ecf,
|
||||||
|
server_s_pk,
|
||||||
|
beta,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The final message from the client, containing sealed cryptographic
|
||||||
|
/// identifiers
|
||||||
|
pub struct RegisterThirdMessage<KeyFormat: KeyPair, D: Hash> {
|
||||||
|
/// The "envelope" generated by the user, containing sealed
|
||||||
|
/// cryptographic identifiers
|
||||||
|
pub(crate) envelope: Envelope<D>,
|
||||||
|
/// The user's public key
|
||||||
|
pub(crate) client_s_pk: KeyFormat::Repr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<KeyFormat, D> TryFrom<&[u8]> for RegisterThirdMessage<KeyFormat, D>
|
||||||
|
where
|
||||||
|
KeyFormat: KeyPair,
|
||||||
|
D: Hash,
|
||||||
|
{
|
||||||
|
type Error = ProtocolError;
|
||||||
|
|
||||||
|
fn try_from(third_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||||
|
let key_len = <KeyFormat::Repr as SizedBytes>::Len::to_usize();
|
||||||
|
let envelope_size = key_len + Envelope::<D>::additional_size();
|
||||||
|
let checked_bytes = check_slice_size(
|
||||||
|
third_message_bytes,
|
||||||
|
envelope_size + key_len,
|
||||||
|
"third_message",
|
||||||
|
)?;
|
||||||
|
let unchecked_client_s_pk = KeyFormat::Repr::from_bytes(&checked_bytes[envelope_size..])?;
|
||||||
|
let client_s_pk = KeyFormat::check_public_key(unchecked_client_s_pk)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
envelope: Envelope::<D>::from_bytes(&checked_bytes[..envelope_size])?,
|
||||||
|
client_s_pk,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<KeyFormat, D> RegisterThirdMessage<KeyFormat, D>
|
||||||
|
where
|
||||||
|
KeyFormat: KeyPair,
|
||||||
|
D: Hash,
|
||||||
|
{
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut registration_upload: Vec<u8> = Vec::new();
|
||||||
|
registration_upload.extend_from_slice(&self.envelope.serialize());
|
||||||
|
registration_upload.extend_from_slice(&serialize(&self.client_s_pk.to_arr(), 2));
|
||||||
|
|
||||||
|
let mut output: Vec<u8> = Vec::new();
|
||||||
|
output.push(ProtocolMessageType::from(self) as u8 + 1);
|
||||||
|
output.extend_from_slice(&serialize(®istration_upload, 3));
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||||
|
if input.is_empty() || input[0] != ProtocolMessageType::RegistrationUpload as u8 + 1 {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (data, remainder) = tokenize(&input[1..], 3)?;
|
||||||
|
if !remainder.is_empty() {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (envelope, remainder) = Envelope::<D>::deserialize(&data)?;
|
||||||
|
let (client_s_pk, remainder) = tokenize(&remainder, 2)?;
|
||||||
|
|
||||||
|
if !remainder.is_empty() {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
envelope,
|
||||||
|
client_s_pk: KeyFormat::check_public_key(KeyFormat::Repr::from_bytes(&client_s_pk)?)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The message sent by the user to the server, to initiate registration
|
||||||
|
pub struct LoginFirstMessage<CS: CipherSuite> {
|
||||||
|
/// blinded password information
|
||||||
|
pub(crate) alpha: CS::Group,
|
||||||
|
pub(crate) ke1_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::KE1Message,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> TryFrom<&[u8]> for LoginFirstMessage<CS> {
|
||||||
|
type Error = ProtocolError;
|
||||||
|
fn try_from(first_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||||
|
Self::deserialize(first_message_bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> LoginFirstMessage<CS> {
|
||||||
|
/// byte representation for the login request
|
||||||
|
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
[&self.alpha.to_arr()[..], &self.ke1_message.to_bytes()].concat()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut credential_request: Vec<u8> = Vec::new();
|
||||||
|
credential_request.extend_from_slice(&serialize(&self.alpha.to_arr(), 2));
|
||||||
|
|
||||||
|
let mut output: Vec<u8> = Vec::new();
|
||||||
|
output.push(ProtocolMessageType::from(self) as u8 + 1);
|
||||||
|
output.extend_from_slice(&serialize(&credential_request, 3));
|
||||||
|
output.extend_from_slice(&self.ke1_message.to_bytes());
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||||
|
if input.is_empty() || input[0] != ProtocolMessageType::CredentialRequest as u8 + 1 {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (data, ke1m) = tokenize(&input[1..], 3)?;
|
||||||
|
let (alpha_bytes, remainder) = tokenize(&data, 2)?;
|
||||||
|
|
||||||
|
if !remainder.is_empty() {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||||
|
let checked_slice = check_slice_size(&alpha_bytes, elem_len, "login_first_message_bytes")?;
|
||||||
|
let arr = GenericArray::from_slice(&checked_slice[..elem_len]);
|
||||||
|
let alpha = <CS::Group as Group>::from_element_slice(arr)?;
|
||||||
|
|
||||||
|
let ke1_message =
|
||||||
|
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::KE1Message::try_from(
|
||||||
|
&ke1m[..],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(Self { alpha, ke1_message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The answer sent by the server to the user, upon reception of the
|
||||||
|
/// login attempt.
|
||||||
|
pub struct LoginSecondMessage<CS: CipherSuite> {
|
||||||
|
/// the server's oprf output
|
||||||
|
pub(crate) beta: CS::Group,
|
||||||
|
/// the user's sealed information,
|
||||||
|
pub(crate) envelope: Envelope<CS::Hash>,
|
||||||
|
pub(crate) ke2_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::KE2Message,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> LoginSecondMessage<CS> {
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut credential_response: Vec<u8> = Vec::new();
|
||||||
|
credential_response.extend_from_slice(&serialize(&self.beta.to_arr(), 2));
|
||||||
|
credential_response.extend_from_slice(&self.envelope.to_bytes());
|
||||||
|
|
||||||
|
let mut output: Vec<u8> = Vec::new();
|
||||||
|
output.push(ProtocolMessageType::from(self) as u8 + 1);
|
||||||
|
output.extend_from_slice(&serialize(&credential_response, 3));
|
||||||
|
output.extend_from_slice(&self.ke2_message.to_bytes());
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||||
|
if input.is_empty() || input[0] != ProtocolMessageType::CredentialResponse as u8 + 1 {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (data, ke2m) = tokenize(&input[1..], 3)?;
|
||||||
|
let (beta_bytes, envelope_bytes) = tokenize(&data, 2)?;
|
||||||
|
|
||||||
|
let concatenated = [&beta_bytes[..], &envelope_bytes[..], &ke2m[..]].concat();
|
||||||
|
Self::try_from(&concatenated[..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> TryFrom<&[u8]> for LoginSecondMessage<CS> {
|
||||||
|
type Error = ProtocolError;
|
||||||
|
fn try_from(second_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||||
|
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||||
|
let checked_slice =
|
||||||
|
check_slice_size_atleast(second_message_bytes, elem_len, "login_second_message_bytes")?;
|
||||||
|
|
||||||
|
// Check that the message is actually containing an element of the
|
||||||
|
// 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 (envelope, remainder) = Envelope::<CS::Hash>::deserialize(&checked_slice[elem_len..])?;
|
||||||
|
|
||||||
|
let ke2_message_size = CS::KeyExchange::ke2_message_size();
|
||||||
|
let checked_remainder =
|
||||||
|
check_slice_size_atleast(&remainder, ke2_message_size, "login_second_message_bytes")?;
|
||||||
|
let ke2_message =
|
||||||
|
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::KE2Message::try_from(
|
||||||
|
&checked_remainder,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
beta,
|
||||||
|
envelope,
|
||||||
|
ke2_message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The answer sent by the client to the server, upon reception of the
|
||||||
|
/// sealed envelope
|
||||||
|
pub struct LoginThirdMessage<CS: CipherSuite> {
|
||||||
|
pub(crate) ke3_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::KE3Message,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> TryFrom<&[u8]> for LoginThirdMessage<CS> {
|
||||||
|
type Error = ProtocolError;
|
||||||
|
|
||||||
|
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||||
|
let ke3_message =
|
||||||
|
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::KE3Message::try_from(bytes)?;
|
||||||
|
Ok(Self { ke3_message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> LoginThirdMessage<CS> {
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut output: Vec<u8> = Vec::new();
|
||||||
|
output.push(ProtocolMessageType::from(self) as u8 + 1);
|
||||||
|
output.extend_from_slice(&self.ke3_message.to_bytes());
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||||
|
if input.is_empty() || input[0] != ProtocolMessageType::KeyExchange as u8 + 1 {
|
||||||
|
return Err(PakeError::SerializationError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::try_from(&input[1..])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// byte representation for the login finalization
|
||||||
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
self.ke3_message.to_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
+262
-634
File diff suppressed because it is too large
Load Diff
@@ -6,13 +6,8 @@
|
|||||||
use crate::errors::PakeError;
|
use crate::errors::PakeError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ciphersuite::CipherSuite,
|
ciphersuite::CipherSuite, hash::Hash, keypair::KeyPair, LoginFirstMessage, LoginSecondMessage,
|
||||||
hash::Hash,
|
LoginThirdMessage, RegisterFirstMessage, RegisterSecondMessage, RegisterThirdMessage,
|
||||||
keypair::KeyPair,
|
|
||||||
opaque::{
|
|
||||||
LoginFirstMessage, LoginSecondMessage, LoginThirdMessage, RegisterFirstMessage,
|
|
||||||
RegisterSecondMessage, RegisterThirdMessage,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum ProtocolMessageType {
|
pub enum ProtocolMessageType {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use crate::{
|
|||||||
keypair::{KeyPair, X25519KeyPair},
|
keypair::{KeyPair, X25519KeyPair},
|
||||||
opaque::*,
|
opaque::*,
|
||||||
serialization::{i2osp, os2ip, serialize, ProtocolMessageType},
|
serialization::{i2osp, os2ip, serialize, ProtocolMessageType},
|
||||||
|
*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||||
|
|||||||
+112
-67
@@ -12,6 +12,7 @@ use crate::{
|
|||||||
opaque::*,
|
opaque::*,
|
||||||
slow_hash::NoOpHash,
|
slow_hash::NoOpHash,
|
||||||
tests::mock_rng::CycleRng,
|
tests::mock_rng::CycleRng,
|
||||||
|
*,
|
||||||
};
|
};
|
||||||
use curve25519_dalek::edwards::EdwardsPoint;
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
use generic_array::GenericArray;
|
use generic_array::GenericArray;
|
||||||
@@ -83,7 +84,7 @@ static TEST_VECTOR: &str = r#"
|
|||||||
"client_nonce": "8bdd8689f4ea9486aaa3bac182d31f31e3c62d76b3869ae1dd05d5c708b13e86",
|
"client_nonce": "8bdd8689f4ea9486aaa3bac182d31f31e3c62d76b3869ae1dd05d5c708b13e86",
|
||||||
"server_nonce": "d529ed9480524236ed6f6cafd92ebab3c6091afde54f47f9079575c090cad7d6",
|
"server_nonce": "d529ed9480524236ed6f6cafd92ebab3c6091afde54f47f9079575c090cad7d6",
|
||||||
"r1": "010000220020ada5910d73be53a8a6c50d32e9efcc0eb3e871103c05fb993fcb8312aff7fc79",
|
"r1": "010000220020ada5910d73be53a8a6c50d32e9efcc0eb3e871103c05fb993fcb8312aff7fc79",
|
||||||
"r2": "02000028002035104271fe25c0074ea715af805c019772a97b6e975376f411e1c37831a56fa7000001010103",
|
"r2": "02000048002035104271fe25c0074ea715af805c019772a97b6e975376f411e1c37831a56fa700209ef0646ad66cf13ce4052294c7325e044853f0c1fd03e91288f8339d812d4a5701010103",
|
||||||
"r3": "030000aeb326061dfc120f5b261b28bbae4262c26ad343a640b5fb4b90ba3f16600e1c89002375ba1dad2970f60479c4ce0fe1e62271f2c5561757557c88941d9278ededbc981de07c00230300209ef0646ad66cf13ce4052294c7325e044853f0c1fd03e91288f8339d812d4a570020c575cad080bafce229c0de9700269d48d8102d3f0f70497a770d9c0bcb5d181e0020aee30cf198cc78b5b1a5ed5a4bda21bceb5e4732fffbddf867e32ee814d67317",
|
"r3": "030000aeb326061dfc120f5b261b28bbae4262c26ad343a640b5fb4b90ba3f16600e1c89002375ba1dad2970f60479c4ce0fe1e62271f2c5561757557c88941d9278ededbc981de07c00230300209ef0646ad66cf13ce4052294c7325e044853f0c1fd03e91288f8339d812d4a570020c575cad080bafce229c0de9700269d48d8102d3f0f70497a770d9c0bcb5d181e0020aee30cf198cc78b5b1a5ed5a4bda21bceb5e4732fffbddf867e32ee814d67317",
|
||||||
"l1": "040000220020ada5910d73be53a8a6c50d32e9efcc0eb3e871103c05fb993fcb8312aff7fc798bdd8689f4ea9486aaa3bac182d31f31e3c62d76b3869ae1dd05d5c708b13e8600001fb90ca40034a0ee0d9d087a2c12743329d792b21e4c4424e561a665a1031b00",
|
"l1": "040000220020ada5910d73be53a8a6c50d32e9efcc0eb3e871103c05fb993fcb8312aff7fc798bdd8689f4ea9486aaa3bac182d31f31e3c62d76b3869ae1dd05d5c708b13e8600001fb90ca40034a0ee0d9d087a2c12743329d792b21e4c4424e561a665a1031b00",
|
||||||
"l2": "050000ae002035104271fe25c0074ea715af805c019772a97b6e975376f411e1c37831a56fa7b326061dfc120f5b261b28bbae4262c26ad343a640b5fb4b90ba3f16600e1c89002375ba1dad2970f60479c4ce0fe1e62271f2c5561757557c88941d9278ededbc981de07c00230300209ef0646ad66cf13ce4052294c7325e044853f0c1fd03e91288f8339d812d4a570020c575cad080bafce229c0de9700269d48d8102d3f0f70497a770d9c0bcb5d181ef021332310d7f6a1c8272d11610e0244cf462efe1a7d9e6657cf12f74d30f2720000b2df778b631c83d1fdd76feb9978d156ad0c1d18fedbe2b15a309f673e3d846400003bc4221316aaad7b6110910bae5a3bc0e498738634916021546f6fce652adc78",
|
"l2": "050000ae002035104271fe25c0074ea715af805c019772a97b6e975376f411e1c37831a56fa7b326061dfc120f5b261b28bbae4262c26ad343a640b5fb4b90ba3f16600e1c89002375ba1dad2970f60479c4ce0fe1e62271f2c5561757557c88941d9278ededbc981de07c00230300209ef0646ad66cf13ce4052294c7325e044853f0c1fd03e91288f8339d812d4a570020c575cad080bafce229c0de9700269d48d8102d3f0f70497a770d9c0bcb5d181ef021332310d7f6a1c8272d11610e0244cf462efe1a7d9e6657cf12f74d30f2720000b2df778b631c83d1fdd76feb9978d156ad0c1d18fedbe2b15a309f673e3d846400003bc4221316aaad7b6110910bae5a3bc0e498738634916021546f6fce652adc78",
|
||||||
@@ -250,10 +251,9 @@ where
|
|||||||
rng.fill_bytes(&mut server_nonce);
|
rng.fill_bytes(&mut server_nonce);
|
||||||
|
|
||||||
let mut blinding_factor_registration_rng = CycleRng::new(blinding_factor_raw.to_vec());
|
let mut blinding_factor_registration_rng = CycleRng::new(blinding_factor_raw.to_vec());
|
||||||
let (r1, client_registration) = ClientRegistration::<CS>::start_with_user_and_server_name(
|
let (r1, client_registration) = ClientRegistration::<CS>::start(
|
||||||
id_u,
|
|
||||||
id_s,
|
|
||||||
password,
|
password,
|
||||||
|
ClientRegistrationStartParameters::WithIdentifiers(id_u.to_vec(), id_s.to_vec()),
|
||||||
&mut blinding_factor_registration_rng,
|
&mut blinding_factor_registration_rng,
|
||||||
std::convert::identity,
|
std::convert::identity,
|
||||||
)
|
)
|
||||||
@@ -264,7 +264,8 @@ where
|
|||||||
let client_registration_state = client_registration.to_bytes().to_vec();
|
let client_registration_state = client_registration.to_bytes().to_vec();
|
||||||
|
|
||||||
let mut oprf_key_rng = CycleRng::new(oprf_key_raw.to_vec());
|
let mut oprf_key_rng = CycleRng::new(oprf_key_raw.to_vec());
|
||||||
let (r2, server_registration) = ServerRegistration::<CS>::start(r1, &mut oprf_key_rng).unwrap();
|
let (r2, server_registration) =
|
||||||
|
ServerRegistration::<CS>::start(r1, server_s_kp.public(), &mut oprf_key_rng).unwrap();
|
||||||
let r2_bytes = r2.serialize().to_vec();
|
let r2_bytes = r2.serialize().to_vec();
|
||||||
let oprf_key_bytes = CS::Group::scalar_as_bytes(&server_registration.oprf_key).clone();
|
let oprf_key_bytes = CS::Group::scalar_as_bytes(&server_registration.oprf_key).clone();
|
||||||
let server_registration_state = server_registration.to_bytes().to_vec();
|
let server_registration_state = server_registration.to_bytes().to_vec();
|
||||||
@@ -275,7 +276,7 @@ where
|
|||||||
|
|
||||||
let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce);
|
let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce);
|
||||||
let (r3, export_key_registration) = client_registration
|
let (r3, export_key_registration) = client_registration
|
||||||
.finish(r2, server_s_kp.public(), &mut finish_registration_rng)
|
.finish(r2, &mut finish_registration_rng)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let r3_bytes = r3.serialize().to_vec();
|
let r3_bytes = r3.serialize().to_vec();
|
||||||
|
|
||||||
@@ -288,33 +289,52 @@ where
|
|||||||
client_login_start.extend_from_slice(&client_nonce);
|
client_login_start.extend_from_slice(&client_nonce);
|
||||||
|
|
||||||
let mut client_login_start_rng = CycleRng::new(client_login_start);
|
let mut client_login_start_rng = CycleRng::new(client_login_start);
|
||||||
let (l1, client_login) = ClientLogin::<CS>::start_with_user_and_server_name(
|
let client_login_start_result = ClientLogin::<CS>::start(
|
||||||
id_u,
|
|
||||||
id_s,
|
|
||||||
password,
|
password,
|
||||||
&mut client_login_start_rng,
|
&mut client_login_start_rng,
|
||||||
|
ClientLoginStartParameters::WithIdentifiersAndInfo(
|
||||||
|
Vec::new(),
|
||||||
|
id_u.to_vec(),
|
||||||
|
id_s.to_vec(),
|
||||||
|
),
|
||||||
std::convert::identity,
|
std::convert::identity,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let l1_bytes = l1.serialize().to_vec();
|
let l1_bytes = client_login_start_result
|
||||||
let client_login_state = client_login.to_bytes().to_vec();
|
.credential_request
|
||||||
|
.serialize()
|
||||||
|
.to_vec();
|
||||||
|
let client_login_state = client_login_start_result
|
||||||
|
.client_login_state
|
||||||
|
.to_bytes()
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
let mut server_e_sk_rng = CycleRng::new(server_e_kp.private().to_arr().to_vec());
|
let mut server_e_sk_rng = CycleRng::new(server_e_kp.private().to_arr().to_vec());
|
||||||
let (l2, server_login) = ServerLogin::<CS>::start(
|
let server_login_start_result = ServerLogin::<CS>::start(
|
||||||
password_file,
|
password_file,
|
||||||
server_s_kp.private(),
|
server_s_kp.private(),
|
||||||
l1,
|
client_login_start_result.credential_request,
|
||||||
&mut server_e_sk_rng,
|
&mut server_e_sk_rng,
|
||||||
|
ServerLoginStartParameters::default(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let l2_bytes = l2.serialize().to_vec();
|
let l2_bytes = server_login_start_result
|
||||||
let server_login_state = server_login.to_bytes().to_vec();
|
.credential_response
|
||||||
|
.serialize()
|
||||||
|
.to_vec();
|
||||||
|
let server_login_state = server_login_start_result
|
||||||
|
.server_login_state
|
||||||
|
.to_bytes()
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
let mut client_e_sk_rng = CycleRng::new(client_e_kp.private().to_arr().to_vec());
|
let client_login_finish_result = client_login_start_result
|
||||||
let (l3, client_shared_secret, _export_key_login) = client_login
|
.client_login_state
|
||||||
.finish(l2, server_s_kp.public(), &mut client_e_sk_rng)
|
.finish(
|
||||||
|
server_login_start_result.credential_response,
|
||||||
|
ClientLoginFinishParameters::default(),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let l3_bytes = l3.to_bytes().to_vec();
|
let l3_bytes = client_login_finish_result.key_exchange.to_bytes().to_vec();
|
||||||
|
|
||||||
TestVectorParameters {
|
TestVectorParameters {
|
||||||
client_s_pk: client_s_kp.public().to_arr().to_vec(),
|
client_s_pk: client_s_kp.public().to_arr().to_vec(),
|
||||||
@@ -344,7 +364,7 @@ where
|
|||||||
server_registration_state,
|
server_registration_state,
|
||||||
client_login_state,
|
client_login_state,
|
||||||
server_login_state,
|
server_login_state,
|
||||||
shared_secret: client_shared_secret,
|
shared_secret: client_login_finish_result.session_secret,
|
||||||
export_key: export_key_registration.to_vec(),
|
export_key: export_key_registration.to_vec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,15 +385,13 @@ fn postprocess_blinding_factor<G: Group>(_: G::Scalar) -> G::Scalar {
|
|||||||
fn test_r1() -> Result<(), PakeError> {
|
fn test_r1() -> Result<(), PakeError> {
|
||||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let (r1, client_registration) =
|
let (r1, client_registration) = ClientRegistration::<X255193dhNoSlowHash>::start(
|
||||||
ClientRegistration::<X255193dhNoSlowHash>::start_with_user_and_server_name(
|
¶meters.password,
|
||||||
¶meters.id_u,
|
ClientRegistrationStartParameters::WithIdentifiers(parameters.id_u, parameters.id_s),
|
||||||
¶meters.id_s,
|
&mut rng,
|
||||||
¶meters.password,
|
postprocess_blinding_factor::<<X255193dhNoSlowHash as CipherSuite>::Group>,
|
||||||
&mut rng,
|
)
|
||||||
postprocess_blinding_factor::<<X255193dhNoSlowHash as CipherSuite>::Group>,
|
.unwrap();
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(hex::encode(¶meters.r1), hex::encode(r1.serialize()));
|
assert_eq!(hex::encode(¶meters.r1), hex::encode(r1.serialize()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(¶meters.client_registration_state),
|
hex::encode(¶meters.client_registration_state),
|
||||||
@@ -388,6 +406,7 @@ fn test_r2() -> Result<(), PakeError> {
|
|||||||
let mut oprf_key_rng = CycleRng::new(parameters.oprf_key);
|
let mut oprf_key_rng = CycleRng::new(parameters.oprf_key);
|
||||||
let (r2, server_registration) = ServerRegistration::<X255193dhNoSlowHash>::start(
|
let (r2, server_registration) = ServerRegistration::<X255193dhNoSlowHash>::start(
|
||||||
RegisterFirstMessage::deserialize(¶meters.r1[..]).unwrap(),
|
RegisterFirstMessage::deserialize(¶meters.r1[..]).unwrap(),
|
||||||
|
&Key::try_from(¶meters.server_s_pk[..]).unwrap(),
|
||||||
&mut oprf_key_rng,
|
&mut oprf_key_rng,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -412,7 +431,6 @@ fn test_r3() -> Result<(), PakeError> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.finish(
|
.finish(
|
||||||
RegisterSecondMessage::deserialize(¶meters.r2[..]).unwrap(),
|
RegisterSecondMessage::deserialize(¶meters.r2[..]).unwrap(),
|
||||||
&Key::try_from(¶meters.server_s_pk[..]).unwrap(),
|
|
||||||
&mut finish_registration_rng,
|
&mut finish_registration_rng,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -456,18 +474,24 @@ fn test_l1() -> Result<(), PakeError> {
|
|||||||
]
|
]
|
||||||
.concat();
|
.concat();
|
||||||
let mut client_login_start_rng = CycleRng::new(client_login_start);
|
let mut client_login_start_rng = CycleRng::new(client_login_start);
|
||||||
let (l1, client_login) = ClientLogin::<X255193dhNoSlowHash>::start_with_user_and_server_name(
|
let client_login_start_result = ClientLogin::<X255193dhNoSlowHash>::start(
|
||||||
¶meters.id_u,
|
|
||||||
¶meters.id_s,
|
|
||||||
¶meters.password,
|
¶meters.password,
|
||||||
&mut client_login_start_rng,
|
&mut client_login_start_rng,
|
||||||
|
ClientLoginStartParameters::WithIdentifiersAndInfo(
|
||||||
|
Vec::new(),
|
||||||
|
parameters.id_u,
|
||||||
|
parameters.id_s,
|
||||||
|
),
|
||||||
postprocess_blinding_factor::<<X255193dhNoSlowHash as CipherSuite>::Group>,
|
postprocess_blinding_factor::<<X255193dhNoSlowHash as CipherSuite>::Group>,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(hex::encode(¶meters.l1), hex::encode(l1.serialize()));
|
assert_eq!(
|
||||||
|
hex::encode(¶meters.l1),
|
||||||
|
hex::encode(client_login_start_result.credential_request.serialize())
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(¶meters.client_login_state),
|
hex::encode(¶meters.client_login_state),
|
||||||
hex::encode(client_login.to_bytes())
|
hex::encode(client_login_start_result.client_login_state.to_bytes())
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -477,18 +501,22 @@ fn test_l2() -> Result<(), PakeError> {
|
|||||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||||
|
|
||||||
let mut server_e_sk_rng = CycleRng::new(parameters.server_e_sk);
|
let mut server_e_sk_rng = CycleRng::new(parameters.server_e_sk);
|
||||||
let (l2, server_login) = ServerLogin::<X255193dhNoSlowHash>::start(
|
let server_login_start_result = ServerLogin::<X255193dhNoSlowHash>::start(
|
||||||
ServerRegistration::try_from(¶meters.password_file[..]).unwrap(),
|
ServerRegistration::try_from(¶meters.password_file[..]).unwrap(),
|
||||||
&Key::try_from(¶meters.server_s_sk[..]).unwrap(),
|
&Key::try_from(¶meters.server_s_sk[..]).unwrap(),
|
||||||
LoginFirstMessage::<X255193dhNoSlowHash>::deserialize(¶meters.l1[..]).unwrap(),
|
LoginFirstMessage::<X255193dhNoSlowHash>::deserialize(¶meters.l1[..]).unwrap(),
|
||||||
&mut server_e_sk_rng,
|
&mut server_e_sk_rng,
|
||||||
|
ServerLoginStartParameters::default(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(hex::encode(¶meters.l2), hex::encode(l2.serialize()));
|
assert_eq!(
|
||||||
|
hex::encode(¶meters.l2),
|
||||||
|
hex::encode(server_login_start_result.credential_response.serialize())
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(¶meters.server_login_state),
|
hex::encode(¶meters.server_login_state),
|
||||||
hex::encode(server_login.to_bytes())
|
hex::encode(server_login_start_result.server_login_state.to_bytes())
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -497,25 +525,26 @@ fn test_l2() -> Result<(), PakeError> {
|
|||||||
fn test_l3() -> Result<(), PakeError> {
|
fn test_l3() -> Result<(), PakeError> {
|
||||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||||
|
|
||||||
let mut client_e_sk_rng = CycleRng::new(parameters.client_e_sk.to_vec());
|
let client_login_finish_result =
|
||||||
let (l3, shared_secret, export_key_login) =
|
|
||||||
ClientLogin::<X255193dhNoSlowHash>::try_from(¶meters.client_login_state[..])
|
ClientLogin::<X255193dhNoSlowHash>::try_from(¶meters.client_login_state[..])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.finish(
|
.finish(
|
||||||
LoginSecondMessage::<X255193dhNoSlowHash>::deserialize(¶meters.l2[..]).unwrap(),
|
LoginSecondMessage::<X255193dhNoSlowHash>::deserialize(¶meters.l2[..]).unwrap(),
|
||||||
&Key::try_from(¶meters.server_s_pk[..])?,
|
ClientLoginFinishParameters::default(),
|
||||||
&mut client_e_sk_rng,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(¶meters.shared_secret),
|
hex::encode(¶meters.shared_secret),
|
||||||
hex::encode(&shared_secret)
|
hex::encode(&client_login_finish_result.session_secret)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
hex::encode(¶meters.l3),
|
||||||
|
hex::encode(client_login_finish_result.key_exchange.to_bytes())
|
||||||
);
|
);
|
||||||
assert_eq!(hex::encode(¶meters.l3), hex::encode(l3.to_bytes()));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(¶meters.export_key),
|
hex::encode(¶meters.export_key),
|
||||||
hex::encode(export_key_login)
|
hex::encode(client_login_finish_result.export_key)
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -525,7 +554,7 @@ fn test_l3() -> Result<(), PakeError> {
|
|||||||
fn test_server_login_finish() -> Result<(), ProtocolError> {
|
fn test_server_login_finish() -> Result<(), ProtocolError> {
|
||||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||||
|
|
||||||
let shared_secret =
|
let server_login_result =
|
||||||
ServerLogin::<X255193dhNoSlowHash>::try_from(¶meters.server_login_state[..])
|
ServerLogin::<X255193dhNoSlowHash>::try_from(¶meters.server_login_state[..])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.finish(LoginThirdMessage::try_from(¶meters.l3[..])?)
|
.finish(LoginThirdMessage::try_from(¶meters.l3[..])?)
|
||||||
@@ -533,7 +562,7 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(parameters.shared_secret),
|
hex::encode(parameters.shared_secret),
|
||||||
hex::encode(shared_secret)
|
hex::encode(server_login_result.session_secret)
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -546,36 +575,52 @@ fn test_complete_flow(
|
|||||||
let mut client_rng = OsRng;
|
let mut client_rng = OsRng;
|
||||||
let mut server_rng = OsRng;
|
let mut server_rng = OsRng;
|
||||||
let server_kp = X255193dhNoSlowHash::generate_random_keypair(&mut server_rng)?;
|
let server_kp = X255193dhNoSlowHash::generate_random_keypair(&mut server_rng)?;
|
||||||
let (register_m1, client_state) =
|
let (register_m1, client_state) = ClientRegistration::<X255193dhNoSlowHash>::start(
|
||||||
ClientRegistration::<X255193dhNoSlowHash>::start(registration_password, &mut client_rng)?;
|
registration_password,
|
||||||
let (register_m2, server_state) =
|
ClientRegistrationStartParameters::default(),
|
||||||
ServerRegistration::<X255193dhNoSlowHash>::start(register_m1, &mut server_rng)?;
|
&mut client_rng,
|
||||||
let (register_m3, registration_export_key) =
|
std::convert::identity,
|
||||||
client_state.finish(register_m2, server_kp.public(), &mut client_rng)?;
|
)?;
|
||||||
let p_file = server_state.finish(register_m3)?;
|
let (register_m2, server_state) = ServerRegistration::<X255193dhNoSlowHash>::start(
|
||||||
let (login_m1, client_login_state) =
|
register_m1,
|
||||||
ClientLogin::<X255193dhNoSlowHash>::start(login_password, &mut client_rng)?;
|
server_kp.public(),
|
||||||
let (login_m2, server_login_state) = ServerLogin::<X255193dhNoSlowHash>::start(
|
|
||||||
p_file,
|
|
||||||
&server_kp.private(),
|
|
||||||
login_m1,
|
|
||||||
&mut server_rng,
|
&mut server_rng,
|
||||||
)?;
|
)?;
|
||||||
|
let (register_m3, registration_export_key) =
|
||||||
|
client_state.finish(register_m2, &mut client_rng)?;
|
||||||
|
let p_file = server_state.finish(register_m3)?;
|
||||||
|
let client_login_start_result = ClientLogin::<X255193dhNoSlowHash>::start(
|
||||||
|
login_password,
|
||||||
|
&mut client_rng,
|
||||||
|
ClientLoginStartParameters::default(),
|
||||||
|
std::convert::identity,
|
||||||
|
)?;
|
||||||
|
let server_login_start_result = ServerLogin::<X255193dhNoSlowHash>::start(
|
||||||
|
p_file,
|
||||||
|
&server_kp.private(),
|
||||||
|
client_login_start_result.credential_request,
|
||||||
|
&mut server_rng,
|
||||||
|
ServerLoginStartParameters::default(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let client_login_result =
|
let client_login_result = client_login_start_result.client_login_state.finish(
|
||||||
client_login_state.finish(login_m2, &server_kp.public(), &mut client_rng);
|
server_login_start_result.credential_response,
|
||||||
|
ClientLoginFinishParameters::default(),
|
||||||
|
);
|
||||||
|
|
||||||
if hex::encode(registration_password) == hex::encode(login_password) {
|
if hex::encode(registration_password) == hex::encode(login_password) {
|
||||||
let (login_m3, client_shared_secret, login_export_key) = client_login_result?;
|
let client_login_finish_result = client_login_result?;
|
||||||
let server_shared_secret = server_login_state.finish(login_m3)?;
|
let server_login_finish_result = server_login_start_result
|
||||||
|
.server_login_state
|
||||||
|
.finish(client_login_finish_result.key_exchange)?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(server_shared_secret),
|
hex::encode(server_login_finish_result.session_secret),
|
||||||
hex::encode(client_shared_secret)
|
hex::encode(client_login_finish_result.session_secret)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(registration_export_key),
|
hex::encode(registration_export_key),
|
||||||
hex::encode(login_export_key)
|
hex::encode(client_login_finish_result.export_key)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let res = matches!(
|
let res = matches!(
|
||||||
|
|||||||
Reference in New Issue
Block a user