Cleaning up docs + README (#98)
This commit is contained in:
@@ -29,7 +29,8 @@ Resources
|
||||
---------
|
||||
|
||||
- [OPAQUE academic publication](https://eprint.iacr.org/2018/163.pdf), including formal definitions and a proof of security
|
||||
- [draft-krawczyk-cfrg-opaque-05](https://tools.ietf.org/html/draft-krawczyk-cfrg-opaque-06), containing a specification for the OPAQUE protocol
|
||||
- [draft-irtf-cfrg-opaque-01](https://www.ietf.org/archive/id/draft-irtf-cfrg-opaque-01.html), containing a detailed (byte-level) specification for OPAQUE
|
||||
- [draft-krawczyk-cfrg-opaque-06](https://tools.ietf.org/html/draft-krawczyk-cfrg-opaque-06), containing a high-level specification for OPAQUE
|
||||
- ["Let's talk about PAKE"](https://blog.cryptographyengineering.com/2018/10/19/lets-talk-about-pake/), an introductory blog post written by Matthew Green that covers OPAQUE
|
||||
|
||||
Contributors
|
||||
@@ -41,7 +42,7 @@ To learn more about contributing to this project, [see this document](./CONTRIBU
|
||||
|
||||
#### Acknowledgments
|
||||
|
||||
Special thanks go to Hugo Krawczyk for helping to clarify discrepancies and making suggestions for improving
|
||||
Special thanks go to Hugo Krawczyk and Chris Wood for helping to clarify discrepancies and making suggestions for improving
|
||||
this implementation.
|
||||
|
||||
|
||||
|
||||
+33
-31
@@ -30,8 +30,8 @@ use std::process::exit;
|
||||
use opaque_ke::{
|
||||
ciphersuite::CipherSuite, keypair::KeyPair, ClientLogin, ClientLoginFinishParameters,
|
||||
ClientLoginStartParameters, ClientRegistration, ClientRegistrationStartParameters,
|
||||
LoginFirstMessage, LoginSecondMessage, LoginThirdMessage, RegisterFirstMessage,
|
||||
RegisterSecondMessage, RegisterThirdMessage, ServerLogin, ServerLoginStartParameters,
|
||||
CredentialFinalization, CredentialRequest, CredentialResponse, RegistrationRequest,
|
||||
RegistrationResponse, RegistrationUpload, ServerLogin, ServerLoginStartParameters,
|
||||
ServerRegistration,
|
||||
};
|
||||
|
||||
@@ -53,39 +53,41 @@ fn account_registration(
|
||||
password: String,
|
||||
) -> Vec<u8> {
|
||||
let mut client_rng = OsRng;
|
||||
let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||
let client_registration_start_result = ClientRegistration::<Default>::start(
|
||||
&mut client_rng,
|
||||
password.as_bytes(),
|
||||
ClientRegistrationStartParameters::default(),
|
||||
&mut client_rng,
|
||||
)
|
||||
.unwrap();
|
||||
let r1_bytes = r1.serialize();
|
||||
let registration_request_bytes = client_registration_start_result.message.serialize();
|
||||
|
||||
// Client sends r1_bytes to server
|
||||
// Client sends registration_request_bytes to server
|
||||
|
||||
let mut server_rng = OsRng;
|
||||
let (r2, server_state) = ServerRegistration::<Default>::start(
|
||||
RegisterFirstMessage::deserialize(&r1_bytes[..]).unwrap(),
|
||||
server_kp.public(),
|
||||
let server_registration_start_result = ServerRegistration::<Default>::start(
|
||||
&mut server_rng,
|
||||
RegistrationRequest::deserialize(®istration_request_bytes[..]).unwrap(),
|
||||
server_kp.public(),
|
||||
)
|
||||
.unwrap();
|
||||
let r2_bytes = r2.serialize();
|
||||
let registration_response_bytes = server_registration_start_result.message.serialize();
|
||||
|
||||
// Server sends r2_bytes to client
|
||||
// Server sends registration_response_bytes to client
|
||||
|
||||
let (r3, _) = client_state
|
||||
let client_finish_registration_result = client_registration_start_result
|
||||
.state
|
||||
.finish(
|
||||
RegisterSecondMessage::deserialize(&r2_bytes[..]).unwrap(),
|
||||
&mut client_rng,
|
||||
RegistrationResponse::deserialize(®istration_response_bytes[..]).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let r3_bytes = r3.serialize();
|
||||
let message_bytes = client_finish_registration_result.message.serialize();
|
||||
|
||||
// Client sends r3_bytes to server
|
||||
// Client sends message_bytes to server
|
||||
|
||||
let password_file = server_state
|
||||
.finish(RegisterThirdMessage::deserialize(&r3_bytes[..]).unwrap())
|
||||
let password_file = server_registration_start_result
|
||||
.state
|
||||
.finish(RegistrationUpload::deserialize(&message_bytes[..]).unwrap())
|
||||
.unwrap();
|
||||
password_file.to_bytes()
|
||||
}
|
||||
@@ -98,31 +100,31 @@ fn account_login(
|
||||
) -> bool {
|
||||
let mut client_rng = OsRng;
|
||||
let client_login_start_result = ClientLogin::<Default>::start(
|
||||
password.as_bytes(),
|
||||
&mut client_rng,
|
||||
password.as_bytes(),
|
||||
ClientLoginStartParameters::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let l1_bytes = client_login_start_result.credential_request.serialize();
|
||||
let credential_request_bytes = client_login_start_result.message.serialize();
|
||||
|
||||
// Client sends l1_bytes to server
|
||||
// Client sends credential_request_bytes to server
|
||||
|
||||
let password_file = ServerRegistration::<Default>::try_from(password_file_bytes).unwrap();
|
||||
let mut server_rng = OsRng;
|
||||
let server_login_start_result = ServerLogin::start(
|
||||
&mut server_rng,
|
||||
password_file,
|
||||
&server_kp.private(),
|
||||
LoginFirstMessage::deserialize(&l1_bytes[..]).unwrap(),
|
||||
&mut server_rng,
|
||||
CredentialRequest::deserialize(&credential_request_bytes[..]).unwrap(),
|
||||
ServerLoginStartParameters::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let l2_bytes = server_login_start_result.credential_response.serialize();
|
||||
let credential_response_bytes = server_login_start_result.message.serialize();
|
||||
|
||||
// Server sends l2_bytes to client
|
||||
// Server sends credential_response_bytes to client
|
||||
|
||||
let result = client_login_start_result.client_login_state.finish(
|
||||
LoginSecondMessage::deserialize(&l2_bytes[..]).unwrap(),
|
||||
let result = client_login_start_result.state.finish(
|
||||
CredentialResponse::deserialize(&credential_response_bytes[..]).unwrap(),
|
||||
ClientLoginFinishParameters::default(),
|
||||
);
|
||||
|
||||
@@ -131,16 +133,16 @@ fn account_login(
|
||||
return false;
|
||||
}
|
||||
let client_login_finish_result = result.unwrap();
|
||||
let l3_bytes = client_login_finish_result.key_exchange.serialize();
|
||||
let credential_finalization_bytes = client_login_finish_result.message.serialize();
|
||||
|
||||
// Client sends l3_bytes to server
|
||||
// Client sends credential_finalization_bytes to server
|
||||
|
||||
let server_login_finish_result = server_login_start_result
|
||||
.server_login_state
|
||||
.finish(LoginThirdMessage::deserialize(&l3_bytes[..]).unwrap())
|
||||
.state
|
||||
.finish(CredentialFinalization::deserialize(&credential_finalization_bytes[..]).unwrap())
|
||||
.unwrap();
|
||||
|
||||
client_login_finish_result.session_secret == server_login_finish_result.session_secret
|
||||
client_login_finish_result.shared_secret == server_login_finish_result.shared_secret
|
||||
}
|
||||
|
||||
// A function run on the client which extracts a username and password from the CLI
|
||||
|
||||
+131
-108
@@ -5,7 +5,7 @@
|
||||
|
||||
//! An implementation of the OPAQUE asymmetric password authentication key exchange protocol
|
||||
//!
|
||||
//! Note: This implementation is in sync with [draft-krawczyk-cfrg-opaque-06](https://tools.ietf.org/html/draft-krawczyk-cfrg-opaque-06),
|
||||
//! Note: This implementation is in sync with [draft-irtf-cfrg-opaque-01](https://www.ietf.org/archive/id/draft-irtf-cfrg-opaque-01.html),
|
||||
//! but this specification is subject to change, until the final version published by the IETF.
|
||||
//!
|
||||
//! # Overview
|
||||
@@ -32,13 +32,11 @@
|
||||
//! ```
|
||||
//!
|
||||
//! Note that our choice of slow hashing function in this example, `NoOpHash`, is selected only to ensure
|
||||
//! that the tests execute quickly. A real application should use an actual slow hashing function, such as `Scrypt`.
|
||||
//!
|
||||
//! We have included a concrete instantiation of the authenticated key exchange protocol using 3DH. In the future, we plan to
|
||||
//! add support for other KE protocols as well.
|
||||
//! that the tests execute quickly. A real application should use an actual slow hashing function, such as `scrypt`,
|
||||
//! which can be enabled through the `slow-hash` feature.
|
||||
//!
|
||||
//! ## Setup
|
||||
//! To setup the protocol, the server begins by generating a static keypair:
|
||||
//! To set up the protocol, the server begins by generating a static keypair:
|
||||
//! ```
|
||||
//! # use opaque_ke::keypair::{KeyPair, X25519KeyPair};
|
||||
//! # use opaque_ke::errors::ProtocolError;
|
||||
@@ -60,14 +58,15 @@
|
||||
//! used by the client during both registration and login, and the private component will be used by the server during login.
|
||||
//!
|
||||
//! ## Registration
|
||||
//! The registration protocol between the client and server consists of four steps along with three messages, denoted
|
||||
//! as `r1`, `r2`, and `r3`. Before registration begins, it is expected that the server's static public key, `server_kp.public()`,
|
||||
//! has been transmitted to the client in an offline step. A successful execution of the registration protocol results in the
|
||||
//! server producing a password file corresponding to the tuple combination of (password, pepper, server public key) provided by
|
||||
//! The registration protocol between the client and server consists of four steps along with three messages:
|
||||
//! [RegistrationRequest], [RegistrationResponse], and [RegistrationUpload]. A successful execution of the registration protocol results in the
|
||||
//! server producing a password file corresponding to the password provided by
|
||||
//! the client. This password file is typically stored server-side, and retrieved upon future login attempts made by the client.
|
||||
//!
|
||||
//! In the first step (client registration start), the client chooses a registration password and an optional "pepper", and
|
||||
//! runs `ClientRegistration::start` to produce a message `r1`:
|
||||
//! ### Client Registration Start
|
||||
//! In the first step of registration, the client chooses as input a registration password. The client runs [ClientRegistration::start]
|
||||
//! to produce an output consisting of a [RegistrationRequest] to be sent to the server, and
|
||||
//! a [ClientRegistration] which must be persisted on the client for the final step of client registration.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
@@ -87,18 +86,20 @@
|
||||
//! use opaque_ke::{ClientRegistration, ClientRegistrationStartParameters};
|
||||
//! use rand_core::{OsRng, RngCore};
|
||||
//! let mut client_rng = OsRng;
|
||||
//! let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||
//! let client_registration_start_result = ClientRegistration::<Default>::start(
|
||||
//! &mut client_rng,
|
||||
//! b"password",
|
||||
//! ClientRegistrationStartParameters::default(),
|
||||
//! &mut client_rng,
|
||||
//! )?;
|
||||
//! # Ok::<(), ProtocolError>(())
|
||||
//! ```
|
||||
//! `r1` is sent to the server, and `client_state` must be persisted on the client for the final step of client
|
||||
//! registration.
|
||||
//!
|
||||
//! In the second step (server registration start), the server takes as input the `r1` message from the client and runs
|
||||
//! `ServerRegistration::start` to produce `r2`:
|
||||
//! ### Server Registration Start
|
||||
//! In the second step of registration, the server takes as input the instance of [RegistrationRequest] from the client, and
|
||||
//! the server's public key `server_kp.public()`.
|
||||
//! The server runs [ServerRegistration::start] to produce an output consisting of
|
||||
//! a [RegistrationResponse] to be returned to the client, and
|
||||
//! a [ServerRegistration] which must be persisted on the server for the final step of server registration.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
@@ -117,23 +118,28 @@
|
||||
//! # }
|
||||
//! # use rand_core::{OsRng, RngCore};
|
||||
//! # let mut client_rng = OsRng;
|
||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientRegistrationStartParameters::default(),
|
||||
//! # &mut client_rng,
|
||||
//! # )?;
|
||||
//! use opaque_ke::ServerRegistration;
|
||||
//! let mut server_rng = OsRng;
|
||||
//! 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 server_registration_start_result = ServerRegistration::<Default>::start(
|
||||
//! &mut server_rng,
|
||||
//! client_registration_start_result.message,
|
||||
//! server_kp.public(),
|
||||
//! )?;
|
||||
//! # Ok::<(), ProtocolError>(())
|
||||
//! ```
|
||||
//! `r2` is returned to the client, and `server_state` must be persisted on the server for the final step of server
|
||||
//! registration.
|
||||
//!
|
||||
//! In the third step (client registration finish), the client takes as input the `r2` 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 a message `r3` along with the export key `export_key_registration`:
|
||||
//! ### Client Registration Finish
|
||||
//! In the third step of registration, the client takes as input
|
||||
//! a [RegistrationResponse] from the server, and
|
||||
//! a [ClientRegistration] from the first step of registration.
|
||||
//! The client runs [ClientRegistration::finish] to produce an output consisting of a [RegistrationUpload]
|
||||
//! to be sent to the server.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
@@ -152,23 +158,28 @@
|
||||
//! # }
|
||||
//! # use rand_core::{OsRng, RngCore};
|
||||
//! # let mut client_rng = OsRng;
|
||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientRegistrationStartParameters::default(),
|
||||
//! # &mut client_rng,
|
||||
//! # )?;
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! # 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) =
|
||||
//! client_state.finish(r2, &mut client_rng)?;
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! let client_registration_finish_result = client_registration_start_result.state.finish(
|
||||
//! &mut client_rng,
|
||||
//! server_registration_start_result.message,
|
||||
//! )?;
|
||||
//! # Ok::<(), ProtocolError>(())
|
||||
//! ```
|
||||
//! `r3` is sent to the server, and the client can optionally use `export_key_registration` for applications that choose to
|
||||
//! process user information beyond the OPAQUE functionality (e.g., additional secrets or credentials).
|
||||
//!
|
||||
//! In the fourth step of registration, the server takes as input the `r3` message from the client and uses
|
||||
//! `server_state` from the second step to run `finish` and produce `password_file`:
|
||||
//! ### Server Registration Finish
|
||||
//! In the fourth step of registration, the server takes as input
|
||||
//! a [RegistrationUpload] from the client, and
|
||||
//! a [ServerRegistration] from the second step.
|
||||
//! The server runs [ServerRegistration::finish] to produce a finalized [ServerRegistration].
|
||||
//! At this point, the client can be considered as successfully registered, and the server can invoke
|
||||
//! [ServerRegistration::to_bytes] to store the password file for use during the login protocol.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
@@ -187,35 +198,36 @@
|
||||
//! # }
|
||||
//! # use rand_core::{OsRng, RngCore};
|
||||
//! # let mut client_rng = OsRng;
|
||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientRegistrationStartParameters::default(),
|
||||
//! # &mut client_rng,
|
||||
//! # )?;
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! # 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) = client_state.finish(r2, &mut client_rng)?;
|
||||
//! let password_file = server_state.finish(r3)?;
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
//! let password_file = server_registration_start_result.state.finish(
|
||||
//! client_registration_finish_result.message,
|
||||
//! )?;
|
||||
//! # Ok::<(), ProtocolError>(())
|
||||
//! ```
|
||||
//! At this point, the client can be considered as successfully registered, and the server can store
|
||||
//! `password_file.to_bytes()` for use during the login protocol.
|
||||
//!
|
||||
//!
|
||||
//! ## Login
|
||||
//! The login protocol between a client and server also consists of four steps along with three messages, denoted as
|
||||
//! `l1`, `l2`, and `l3`. The server is expected to have access to the a password file corresponding to an output
|
||||
//! of the registration phase. The login protocol will execute successfully only if the same tuple combination of
|
||||
//! (password, pepper, server public key) is presented as was used in the registration phase that produced the
|
||||
//! password file that the server is testing against.
|
||||
//! The login protocol between a client and server also consists of four steps along with three messages:
|
||||
//! [CredentialRequest], [CredentialResponse], [CredentialFinalization]. The server is expected to have access to the password file
|
||||
//! corresponding to an output of the registration phase. The login protocol will execute successfully only if the same password
|
||||
//! was used in the registration phase that produced the password file that the server is testing against.
|
||||
//!
|
||||
//! In the first step (client login start), the client chooses a registration password and an optional "pepper", and runs
|
||||
//! `ClientLogin::start` to produce a message `l1`:
|
||||
//! ### Client Login Start
|
||||
//! In the first step of login, the client chooses as input a login password.
|
||||
//! The client runs [ClientLogin::start] to produce an output consisting of
|
||||
//! a [CredentialRequest] to be sent to the server, and
|
||||
//! a [ClientLogin] which must be persisted on the client for the final step of client login.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # ClientRegistration, ServerRegistration, ServerLogin, LoginThirdMessage,
|
||||
//! # ClientRegistration, ServerRegistration, ServerLogin, CredentialFinalization,
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
@@ -232,22 +244,25 @@
|
||||
//! use opaque_ke::{ClientLogin, ClientLoginStartParameters};
|
||||
//! let mut client_rng = OsRng;
|
||||
//! let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! b"password",
|
||||
//! &mut client_rng,
|
||||
//! b"password",
|
||||
//! ClientLoginStartParameters::default(),
|
||||
//! )?;
|
||||
//! # Ok::<(), ProtocolError>(())
|
||||
//! ```
|
||||
//! `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
|
||||
//! private key `server_kp.private()`, along with a serialized version of the password file, `password_file_bytes`, and
|
||||
//! runs `ServerLogin::start` to produce `server_login_start_result`:
|
||||
//! ### Server Login Start
|
||||
//! In the second step of login, the server takes as input
|
||||
//! a [CredentialRequest] from the client,
|
||||
//! the server's private key `server_kp.private()`, and
|
||||
//! the password file output from registration.
|
||||
//! The server runs [ServerLogin::start] to produce an output consisting of
|
||||
//! a [CredentialResponse] which is returned to the client, and
|
||||
//! a [ServerLogin] which must be persisted on the server for the final step of login.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, LoginThirdMessage,
|
||||
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, CredentialFinalization,
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
@@ -262,39 +277,44 @@
|
||||
//! # }
|
||||
//! # use rand_core::{OsRng, RngCore};
|
||||
//! # let mut client_rng = OsRng;
|
||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientRegistrationStartParameters::default(),
|
||||
//! # &mut client_rng,
|
||||
//! # )?;
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! # 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) = client_state.finish(r2, &mut client_rng)?;
|
||||
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # b"password",
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! use opaque_ke::{ServerLogin, ServerLoginStartParameters};
|
||||
//! use std::convert::TryFrom;
|
||||
//! let password_file = ServerRegistration::<Default>::try_from(&password_file_bytes[..])?;
|
||||
//! let mut server_rng = OsRng;
|
||||
//! let server_login_start_result =
|
||||
//! ServerLogin::start(password_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||
//! let server_login_start_result = ServerLogin::start(
|
||||
//! &mut server_rng,
|
||||
//! password_file,
|
||||
//! &server_kp.private(),
|
||||
//! client_login_start_result.message,
|
||||
//! ServerLoginStartParameters::default(),
|
||||
//! )?;
|
||||
//! # Ok::<(), ProtocolError>(())
|
||||
//! ```
|
||||
//! `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
|
||||
//! server's static public key `server_kp.public()`, and uses `client_state` from the first step to run `finish` and produce
|
||||
//! a message `l3`, the shared secret `client_shared_secret`, and the export key `export_key_login`:
|
||||
//! ### Client Login Finish
|
||||
//! In the third step of login, the client takes as input a [CredentialResponse] from the server.
|
||||
//! The client runs [ClientLogin::finish] and produces an output consisting of
|
||||
//! a [CredentialFinalization] to be sent to the server to complete the protocol,
|
||||
//! the `shared_secret` sequence of bytes which will match the server's shared secret upon a successful login.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, LoginThirdMessage,
|
||||
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization,
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
@@ -309,20 +329,20 @@
|
||||
//! # }
|
||||
//! # use rand_core::{OsRng, RngCore};
|
||||
//! # let mut client_rng = OsRng;
|
||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientRegistrationStartParameters::default(),
|
||||
//! # &mut client_rng,
|
||||
//! # )?;
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! # 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) = client_state.finish(r2, &mut client_rng)?;
|
||||
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # b"password",
|
||||
//! # &mut client_rng,
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! # use std::convert::TryFrom;
|
||||
//! # let password_file =
|
||||
@@ -330,27 +350,25 @@
|
||||
//! # &password_file_bytes[..],
|
||||
//! # )?;
|
||||
//! # let server_login_start_result =
|
||||
//! # ServerLogin::start(password_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||
//! let client_login_finish_result = client_login_start_result.client_login_state.finish(
|
||||
//! server_login_start_result.credential_response,
|
||||
//! # ServerLogin::start(&mut server_rng, password_file, &server_kp.private(), client_login_start_result.message, ServerLoginStartParameters::default())?;
|
||||
//! let client_login_finish_result = client_login_start_result.state.finish(
|
||||
//! server_login_start_result.message,
|
||||
//! ClientLoginFinishParameters::default(),
|
||||
//! )?;
|
||||
//! assert_eq!(export_key_registration, client_login_finish_result.export_key);
|
||||
//! assert_eq!(
|
||||
//! client_registration_finish_result.export_key,
|
||||
//! client_login_finish_result.export_key,
|
||||
//! );
|
||||
//! # Ok::<(), ProtocolError>(())
|
||||
//! ```
|
||||
//! Note that if the client supplies a tuple (password, pepper, server public key) that does not match the tuple
|
||||
//! used to create the password file, then at this point the `finish` algorithm outputs the error `InvalidLoginError`.
|
||||
//!
|
||||
//! If `finish` completes successfully, then `l3` is sent to the server, and (similarly to registration) the client
|
||||
//! can use `export_key_login` for applications that can take advantage of the fact that this key is identical to
|
||||
//! `export_key_registration`.
|
||||
//!
|
||||
//! In the fourth step of login, the server takes as input the `l3` message from the client and uses `server_state` from
|
||||
//! the second step to run `finish`:
|
||||
//! ### Server Login Finish
|
||||
//! In the fourth step of login, the server takes as input a [CredentialFinalization] from the client and runs [ServerLogin::finish] to
|
||||
//! produce an output consisting of the `shared_secret` sequence of bytes which will match the client's shared secret upon a successful login.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, LoginThirdMessage,
|
||||
//! # ClientRegistration, ClientRegistrationStartParameters, ServerRegistration, ClientLogin, ClientLoginStartParameters, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization,
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
@@ -365,19 +383,19 @@
|
||||
//! # }
|
||||
//! # use rand_core::{OsRng, RngCore};
|
||||
//! # let mut client_rng = OsRng;
|
||||
//! # let (r1, client_state) = ClientRegistration::<Default>::start(
|
||||
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientRegistrationStartParameters::default(),
|
||||
//! # &mut client_rng,
|
||||
//! # )?;
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! # 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) = client_state.finish(r2, &mut client_rng)?;
|
||||
//! # let password_file_bytes = server_state.finish(r3)?.to_bytes();
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # b"password",
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! # use std::convert::TryFrom;
|
||||
@@ -386,17 +404,22 @@
|
||||
//! # &password_file_bytes[..],
|
||||
//! # )?;
|
||||
//! # let server_login_start_result =
|
||||
//! # ServerLogin::start(password_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||
//! # let client_login_finish_result = client_login_start_result.client_login_state.finish(
|
||||
//! # server_login_start_result.credential_response,
|
||||
//! # ServerLogin::start(&mut server_rng, password_file, &server_kp.private(), client_login_start_result.message, ServerLoginStartParameters::default())?;
|
||||
//! # let client_login_finish_result = client_login_start_result.state.finish(
|
||||
//! # server_login_start_result.message,
|
||||
//! # ClientLoginFinishParameters::default(),
|
||||
//! # )?;
|
||||
//! let server_login_finish_result = server_login_start_result.server_login_state.finish(client_login_finish_result.key_exchange)?;
|
||||
//! assert_eq!(client_login_finish_result.session_secret, server_login_finish_result.session_secret);
|
||||
//! let server_login_finish_result = server_login_start_result.state.finish(
|
||||
//! client_login_finish_result.message,
|
||||
//! )?;
|
||||
//! assert_eq!(
|
||||
//! client_login_finish_result.shared_secret,
|
||||
//! server_login_finish_result.shared_secret,
|
||||
//! );
|
||||
//! # Ok::<(), ProtocolError>(())
|
||||
//! ```
|
||||
//! If the protocol completes successfully, then the server obtains a `server_shared_secret` which is guaranteed to
|
||||
//! match `client_shared_secret`. Otherwise, on failure, the `finish` algorithm outputs the error `InvalidLoginError`.
|
||||
//! If the protocol completes successfully, then the server obtains a `server_login_finish_result.shared_secret` which is guaranteed to
|
||||
//! match `client_login_finish_result.shared_secret`. Otherwise, on failure, the [ServerLogin::finish] algorithm outputs the error [InvalidLoginError](errors::PakeError::InvalidLoginError).
|
||||
//!
|
||||
|
||||
#![cfg_attr(not(feature = "bench"), deny(missing_docs))]
|
||||
@@ -443,8 +466,8 @@ mod tests;
|
||||
// Exports
|
||||
|
||||
pub use crate::messages::{
|
||||
LoginFirstMessage, LoginSecondMessage, LoginThirdMessage, RegisterFirstMessage,
|
||||
RegisterSecondMessage, RegisterThirdMessage,
|
||||
CredentialFinalization, CredentialRequest, CredentialResponse, RegistrationRequest,
|
||||
RegistrationResponse, RegistrationUpload,
|
||||
};
|
||||
pub use crate::opaque::{ClientLogin, ClientRegistration, ServerLogin, ServerRegistration};
|
||||
pub use crate::opaque::{
|
||||
|
||||
+23
-23
@@ -26,12 +26,12 @@ use std::convert::TryFrom;
|
||||
// =========
|
||||
|
||||
/// The message sent by the client to the server, to initiate registration
|
||||
pub struct RegisterFirstMessage<Grp> {
|
||||
pub struct RegistrationRequest<Grp> {
|
||||
/// blinded password information
|
||||
pub(crate) alpha: Grp,
|
||||
}
|
||||
|
||||
impl<Grp: Group> TryFrom<&[u8]> for RegisterFirstMessage<Grp> {
|
||||
impl<Grp: Group> TryFrom<&[u8]> for RegistrationRequest<Grp> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(first_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
let elem_len = Grp::ElemLen::to_usize();
|
||||
@@ -45,7 +45,7 @@ impl<Grp: Group> TryFrom<&[u8]> for RegisterFirstMessage<Grp> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Grp: Group> RegisterFirstMessage<Grp> {
|
||||
impl<Grp: Group> RegistrationRequest<Grp> {
|
||||
/// Byte representation for the registration request
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
self.alpha.to_arr().to_vec()
|
||||
@@ -79,7 +79,7 @@ impl<Grp: Group> RegisterFirstMessage<Grp> {
|
||||
|
||||
/// The answer sent by the server to the user, upon reception of the
|
||||
/// registration attempt
|
||||
pub struct RegisterSecondMessage<Grp> {
|
||||
pub struct RegistrationResponse<Grp> {
|
||||
/// The server's oprf output
|
||||
pub(crate) beta: Grp,
|
||||
/// Server's static public key
|
||||
@@ -88,7 +88,7 @@ pub struct RegisterSecondMessage<Grp> {
|
||||
pub(crate) ecf: EnvelopeCredentialsFormat,
|
||||
}
|
||||
|
||||
impl<Grp> TryFrom<&[u8]> for RegisterSecondMessage<Grp>
|
||||
impl<Grp> TryFrom<&[u8]> for RegistrationResponse<Grp>
|
||||
where
|
||||
Grp: Group,
|
||||
{
|
||||
@@ -116,7 +116,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Grp> RegisterSecondMessage<Grp>
|
||||
impl<Grp> RegistrationResponse<Grp>
|
||||
where
|
||||
Grp: Group,
|
||||
{
|
||||
@@ -196,7 +196,7 @@ where
|
||||
|
||||
/// The final message from the client, containing sealed cryptographic
|
||||
/// identifiers
|
||||
pub struct RegisterThirdMessage<KeyFormat: KeyPair, D: Hash> {
|
||||
pub struct RegistrationUpload<KeyFormat: KeyPair, D: Hash> {
|
||||
/// The "envelope" generated by the user, containing sealed
|
||||
/// cryptographic identifiers
|
||||
pub(crate) envelope: Envelope<D>,
|
||||
@@ -204,7 +204,7 @@ pub struct RegisterThirdMessage<KeyFormat: KeyPair, D: Hash> {
|
||||
pub(crate) client_s_pk: KeyFormat::Repr,
|
||||
}
|
||||
|
||||
impl<KeyFormat, D> TryFrom<&[u8]> for RegisterThirdMessage<KeyFormat, D>
|
||||
impl<KeyFormat, D> TryFrom<&[u8]> for RegistrationUpload<KeyFormat, D>
|
||||
where
|
||||
KeyFormat: KeyPair,
|
||||
D: Hash,
|
||||
@@ -229,17 +229,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<KeyFormat, D> RegisterThirdMessage<KeyFormat, D>
|
||||
impl<KeyFormat, D> RegistrationUpload<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));
|
||||
registration_upload
|
||||
let mut message: Vec<u8> = Vec::new();
|
||||
message.extend_from_slice(&self.envelope.serialize());
|
||||
message.extend_from_slice(&serialize(&self.client_s_pk.to_arr(), 2));
|
||||
message
|
||||
}
|
||||
|
||||
/// Deserialization from bytes
|
||||
@@ -259,20 +259,20 @@ where
|
||||
}
|
||||
|
||||
/// The message sent by the user to the server, to initiate registration
|
||||
pub struct LoginFirstMessage<CS: CipherSuite> {
|
||||
pub struct CredentialRequest<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> {
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for CredentialRequest<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> {
|
||||
impl<CS: CipherSuite> CredentialRequest<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()
|
||||
@@ -305,8 +305,8 @@ impl<CS: CipherSuite> LoginFirstMessage<CS> {
|
||||
}
|
||||
|
||||
/// The answer sent by the server to the user, upon reception of the
|
||||
/// login attempt.
|
||||
pub struct LoginSecondMessage<CS: CipherSuite> {
|
||||
/// login attempt
|
||||
pub struct CredentialResponse<CS: CipherSuite> {
|
||||
/// the server's oprf output
|
||||
pub(crate) beta: CS::Group,
|
||||
/// the user's sealed information,
|
||||
@@ -314,7 +314,7 @@ pub struct LoginSecondMessage<CS: CipherSuite> {
|
||||
pub(crate) ke2_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::KE2Message,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> LoginSecondMessage<CS> {
|
||||
impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut credential_response: Vec<u8> = Vec::new();
|
||||
@@ -332,7 +332,7 @@ impl<CS: CipherSuite> LoginSecondMessage<CS> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for LoginSecondMessage<CS> {
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for CredentialResponse<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();
|
||||
@@ -365,11 +365,11 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for LoginSecondMessage<CS> {
|
||||
|
||||
/// The answer sent by the client to the server, upon reception of the
|
||||
/// sealed envelope
|
||||
pub struct LoginThirdMessage<CS: CipherSuite> {
|
||||
pub struct CredentialFinalization<CS: CipherSuite> {
|
||||
pub(crate) ke3_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::KE3Message,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for LoginThirdMessage<CS> {
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for CredentialFinalization<CS> {
|
||||
type Error = ProtocolError;
|
||||
|
||||
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
@@ -379,7 +379,7 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for LoginThirdMessage<CS> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> LoginThirdMessage<CS> {
|
||||
impl<CS: CipherSuite> CredentialFinalization<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
self.ke3_message.to_bytes()
|
||||
|
||||
+113
-92
@@ -17,8 +17,8 @@ use crate::{
|
||||
oprf,
|
||||
serialization::{serialize, tokenize, CredentialType},
|
||||
slow_hash::SlowHash,
|
||||
LoginFirstMessage, LoginSecondMessage, LoginThirdMessage, RegisterFirstMessage,
|
||||
RegisterSecondMessage, RegisterThirdMessage,
|
||||
CredentialFinalization, CredentialRequest, CredentialResponse, RegistrationRequest,
|
||||
RegistrationResponse, RegistrationUpload,
|
||||
};
|
||||
use generic_array::{typenum::Unsigned, GenericArray};
|
||||
use generic_bytes::SizedBytes;
|
||||
@@ -102,6 +102,14 @@ impl Default for ClientRegistrationStartParameters {
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a client registration start
|
||||
pub struct ClientRegistrationStartResult<CS: CipherSuite> {
|
||||
/// The registration request message to be sent to the server
|
||||
pub message: RegistrationRequest<CS::Group>,
|
||||
/// The client state that must be persisted in order to complete registration
|
||||
pub state: ClientRegistration<CS>,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// Returns an initial "blinded" request to send to the server, as well as a ClientRegistration
|
||||
///
|
||||
@@ -124,15 +132,15 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
/// }
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let (register_m1, registration_state) = ClientRegistration::<Default>::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?;
|
||||
/// let client_registration_start_result = ClientRegistration::<Default>::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn start<R: RngCore + CryptoRng>(
|
||||
blinding_factor_rng: &mut R,
|
||||
password: &[u8],
|
||||
params: ClientRegistrationStartParameters,
|
||||
blinding_factor_rng: &mut R,
|
||||
#[cfg(test)] postprocess: fn(<CS::Group as Group>::Scalar) -> <CS::Group as Group>::Scalar,
|
||||
) -> Result<(RegisterFirstMessage<CS::Group>, Self), ProtocolError> {
|
||||
) -> Result<ClientRegistrationStartResult<CS>, ProtocolError> {
|
||||
let (id_u, id_s) = match params {
|
||||
ClientRegistrationStartParameters::WithIdentifiers(id_u, id_s) => (id_u, id_s),
|
||||
};
|
||||
@@ -144,17 +152,20 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
postprocess,
|
||||
)?;
|
||||
|
||||
Ok((
|
||||
RegisterFirstMessage::<CS::Group> { alpha },
|
||||
Self { id_u, id_s, token },
|
||||
))
|
||||
Ok(ClientRegistrationStartResult {
|
||||
message: RegistrationRequest::<CS::Group> { alpha },
|
||||
state: Self { id_u, id_s, token },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type ClientRegistrationFinishResult<KeyFormat, D> = (
|
||||
RegisterThirdMessage<KeyFormat, D>,
|
||||
GenericArray<u8, ExportKeySize>,
|
||||
);
|
||||
/// Contains the fields that are returned by a client registration finish
|
||||
pub struct ClientRegistrationFinishResult<KeyFormat: KeyPair, D: Hash> {
|
||||
/// The registration upload message to be sent to the server
|
||||
pub message: RegistrationUpload<KeyFormat, D>,
|
||||
/// The export key output by client registration
|
||||
pub export_key: GenericArray<u8, ExportKeySize>,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// "Unblinds" the server's answer and returns a final message containing
|
||||
@@ -182,17 +193,17 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let mut server_rng = OsRng;
|
||||
/// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?;
|
||||
/// let (register_m1, client_state) = ClientRegistration::<Default>::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?;
|
||||
/// let (register_m2, server_state) =
|
||||
/// ServerRegistration::<Default>::start(register_m1, server_kp.public(), &mut server_rng)?;
|
||||
/// let client_registration_start_result = ClientRegistration::<Default>::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?;
|
||||
/// let server_registration_start_result =
|
||||
/// ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let register_m3 = client_state.finish(register_m2, &mut client_rng)?;
|
||||
/// let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn finish<R: CryptoRng + RngCore>(
|
||||
self,
|
||||
r2: RegisterSecondMessage<CS::Group>,
|
||||
rng: &mut R,
|
||||
r2: RegistrationResponse<CS::Group>,
|
||||
) -> Result<ClientRegistrationFinishResult<CS::KeyFormat, CS::Hash>, ProtocolError> {
|
||||
let client_static_keypair = CS::KeyFormat::generate_random(rng)?;
|
||||
|
||||
@@ -215,13 +226,13 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
let (envelope, export_key) =
|
||||
Envelope::<CS::Hash>::seal(&password_derived_key, r2.ecf, credentials_map, rng)?;
|
||||
|
||||
Ok((
|
||||
RegisterThirdMessage {
|
||||
Ok(ClientRegistrationFinishResult {
|
||||
message: RegistrationUpload {
|
||||
envelope,
|
||||
client_s_pk: client_static_keypair.public().clone(),
|
||||
},
|
||||
export_key,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,6 +264,14 @@ impl<CS: CipherSuite> Drop for ClientLogin<CS> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a server registration start
|
||||
pub struct ServerRegistrationStartResult<CS: CipherSuite> {
|
||||
/// The registration resposne message to send to the client
|
||||
pub message: RegistrationResponse<CS::Group>,
|
||||
/// The state that the server must keep in order to complete registration
|
||||
pub state: ServerRegistration<CS>,
|
||||
}
|
||||
|
||||
/// The state elements the server holds to record a registration
|
||||
pub struct ServerRegistration<CS: CipherSuite> {
|
||||
envelope: Option<Envelope<CS::Hash>>,
|
||||
@@ -351,34 +370,34 @@ where
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let mut server_rng = OsRng;
|
||||
/// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?;
|
||||
/// let (register_m1, client_state) = ClientRegistration::<Default>::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?;
|
||||
/// let (register_m2, server_state) =
|
||||
/// ServerRegistration::<Default>::start(register_m1, server_kp.public(), &mut server_rng)?;
|
||||
/// let client_registration_start_result = ClientRegistration::<Default>::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?;
|
||||
/// let server_registration_start_result =
|
||||
/// ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn start<R: RngCore + CryptoRng>(
|
||||
message: RegisterFirstMessage<CS::Group>,
|
||||
server_s_pk: &<CS::KeyFormat as KeyPair>::Repr,
|
||||
rng: &mut R,
|
||||
) -> Result<(RegisterSecondMessage<CS::Group>, Self), ProtocolError> {
|
||||
message: RegistrationRequest<CS::Group>,
|
||||
server_s_pk: &<CS::KeyFormat as KeyPair>::Repr,
|
||||
) -> Result<ServerRegistrationStartResult<CS>, ProtocolError> {
|
||||
// RFC: generate oprf_key (salt) and v_u = g^oprf_key
|
||||
let oprf_key = CS::Group::random_scalar(rng);
|
||||
|
||||
// Compute beta = alpha^oprf_key
|
||||
let beta = oprf::evaluate::<CS::Group>(message.alpha, &oprf_key);
|
||||
|
||||
Ok((
|
||||
RegisterSecondMessage {
|
||||
Ok(ServerRegistrationStartResult {
|
||||
message: RegistrationResponse {
|
||||
beta,
|
||||
server_s_pk: server_s_pk.to_arr().to_vec(),
|
||||
ecf: EnvelopeCredentialsFormat::default()?,
|
||||
},
|
||||
Self {
|
||||
state: Self {
|
||||
envelope: None,
|
||||
client_s_pk: None,
|
||||
oprf_key,
|
||||
},
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
/// From the client's cryptographic identifiers, fully populates and
|
||||
@@ -405,17 +424,17 @@ where
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let mut server_rng = OsRng;
|
||||
/// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?;
|
||||
/// let (register_m1, client_state) = ClientRegistration::<Default>::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?;
|
||||
/// let (register_m2, server_state) =
|
||||
/// ServerRegistration::<Default>::start(register_m1, server_kp.public(), &mut server_rng)?;
|
||||
/// let client_registration_start_result = ClientRegistration::<Default>::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?;
|
||||
/// let server_registration_start_result =
|
||||
/// ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let (register_m3, _export_key) = client_state.finish(register_m2, &mut client_rng)?;
|
||||
/// let client_record = server_state.finish(register_m3)?;
|
||||
/// let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
/// let client_record = server_registration_start_result.state.finish(client_registration_finish_result.message)?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn finish(
|
||||
self,
|
||||
message: RegisterThirdMessage<CS::KeyFormat, CS::Hash>,
|
||||
message: RegistrationUpload<CS::KeyFormat, CS::Hash>,
|
||||
) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
envelope: Some(message.envelope),
|
||||
@@ -511,9 +530,9 @@ impl Default for ClientLoginStartParameters {
|
||||
/// Contains the fields that are returned by a client login start
|
||||
pub struct ClientLoginStartResult<CS: CipherSuite> {
|
||||
/// The message to send to the server to begin the login protocol
|
||||
pub credential_request: LoginFirstMessage<CS>,
|
||||
pub message: CredentialRequest<CS>,
|
||||
/// The state that the client must keep in order to complete the protocol
|
||||
pub client_login_state: ClientLogin<CS>,
|
||||
pub state: ClientLogin<CS>,
|
||||
}
|
||||
|
||||
/// Optional parameters for client login finish
|
||||
@@ -530,20 +549,20 @@ impl Default for ClientLoginFinishParameters {
|
||||
|
||||
/// Contains the fields that are returned by a client login finish
|
||||
pub struct ClientLoginFinishResult<CS: CipherSuite> {
|
||||
/// The plaintext info sent by the client
|
||||
pub plain_info: Vec<u8>,
|
||||
/// The message to send back to the client
|
||||
pub confidential_info: Vec<u8>,
|
||||
/// The message to send to the server to complete the protocol
|
||||
pub key_exchange: LoginThirdMessage<CS>,
|
||||
pub message: CredentialFinalization<CS>,
|
||||
/// The shared session secret
|
||||
pub session_secret: Vec<u8>,
|
||||
pub shared_secret: Vec<u8>,
|
||||
/// The client-side export key
|
||||
pub export_key: GenericArray<u8, ExportKeySize>,
|
||||
/// The server's static public key
|
||||
pub server_s_pk: Vec<u8>,
|
||||
/// An optional id_s if suppleid by the server
|
||||
/// An optional id_s if supplied by the server
|
||||
pub id_s: Option<Vec<u8>>,
|
||||
/// The plaintext info sent by the client
|
||||
pub plain_info: Vec<u8>,
|
||||
/// The confidential info sent by the client
|
||||
pub confidential_info: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
@@ -568,12 +587,12 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
/// type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||
/// }
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let client_login_start_result = ClientLogin::<Default>::start(b"hunter2", &mut client_rng, ClientLoginStartParameters::default())?;
|
||||
/// let client_login_start_result = ClientLogin::<Default>::start(&mut client_rng, b"hunter2", ClientLoginStartParameters::default())?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn start<R: RngCore + CryptoRng>(
|
||||
password: &[u8],
|
||||
rng: &mut R,
|
||||
password: &[u8],
|
||||
params: ClientLoginStartParameters,
|
||||
#[cfg(test)] postprocess: fn(<CS::Group as Group>::Scalar) -> <CS::Group as Group>::Scalar,
|
||||
) -> Result<ClientLoginStartResult<CS>, ProtocolError> {
|
||||
@@ -594,11 +613,11 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
let (ke1_state, ke1_message) =
|
||||
CS::KeyExchange::generate_ke1(alpha.to_arr().to_vec(), info, rng)?;
|
||||
|
||||
let l1 = LoginFirstMessage { alpha, ke1_message };
|
||||
let l1 = CredentialRequest { alpha, ke1_message };
|
||||
|
||||
Ok(ClientLoginStartResult {
|
||||
credential_request: l1,
|
||||
client_login_state: Self {
|
||||
message: l1,
|
||||
state: Self {
|
||||
id_u,
|
||||
id_s,
|
||||
token,
|
||||
@@ -632,19 +651,19 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
/// }
|
||||
/// let mut client_rng = OsRng;
|
||||
/// # let mut server_rng = OsRng;
|
||||
/// # let (register_m1, client_state) = ClientRegistration::<Default>::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?;
|
||||
/// # let client_registration_start_result = ClientRegistration::<Default>::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?;
|
||||
/// # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?;
|
||||
/// # let (register_m2, server_state) = ServerRegistration::<Default>::start(register_m1, server_kp.public(), &mut server_rng)?;
|
||||
/// # let (register_m3, _export_key) = client_state.finish(register_m2, &mut client_rng)?;
|
||||
/// # let p_file = server_state.finish(register_m3)?;
|
||||
/// let client_login_start_result = ClientLogin::<Default>::start(b"hunter2", &mut client_rng, ClientLoginStartParameters::default())?;
|
||||
/// let server_login_start_result = ServerLogin::start(p_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||
/// let client_login_finish_result = client_login_start_result.client_login_state.finish(server_login_start_result.credential_response, ClientLoginFinishParameters::default())?;
|
||||
/// # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
/// # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
/// # let p_file = server_registration_start_result.state.finish(client_registration_finish_result.message)?;
|
||||
/// let client_login_start_result = ClientLogin::<Default>::start(&mut client_rng, b"hunter2", ClientLoginStartParameters::default())?;
|
||||
/// let server_login_start_result = ServerLogin::start(&mut server_rng, p_file, &server_kp.private(), client_login_start_result.message, ServerLoginStartParameters::default())?;
|
||||
/// let client_login_finish_result = client_login_start_result.state.finish(server_login_start_result.message, ClientLoginFinishParameters::default())?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn finish(
|
||||
self,
|
||||
l2: LoginSecondMessage<CS>,
|
||||
l2: CredentialResponse<CS>,
|
||||
params: ClientLoginFinishParameters,
|
||||
) -> Result<ClientLoginFinishResult<CS>, ProtocolError> {
|
||||
let (info, e_info) = match params {
|
||||
@@ -683,7 +702,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
None => (server_s_pk.to_arr().to_vec(), None),
|
||||
};
|
||||
|
||||
let (plain_info, confidential_info, session_secret, ke3_message) =
|
||||
let (plain_info, confidential_info, shared_secret, ke3_message) =
|
||||
CS::KeyExchange::generate_ke3(
|
||||
l2_bytes,
|
||||
l2.ke2_message,
|
||||
@@ -699,8 +718,8 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
Ok(ClientLoginFinishResult {
|
||||
plain_info,
|
||||
confidential_info,
|
||||
key_exchange: LoginThirdMessage { ke3_message },
|
||||
session_secret,
|
||||
message: CredentialFinalization { ke3_message },
|
||||
shared_secret,
|
||||
export_key: opened_envelope.export_key,
|
||||
server_s_pk: server_s_pk.to_arr().to_vec(),
|
||||
id_s: ret_id_s,
|
||||
@@ -744,26 +763,28 @@ impl Default for ServerLoginStartParameters {
|
||||
|
||||
/// Contains the fields that are returned by a server login start
|
||||
pub struct ServerLoginStartResult<CS: CipherSuite> {
|
||||
/// The plaintext info sent by the client
|
||||
pub plain_info: Vec<u8>,
|
||||
/// The message to send back to the client
|
||||
pub credential_response: LoginSecondMessage<CS>,
|
||||
pub message: CredentialResponse<CS>,
|
||||
/// The state that the server must keep in order to finish the protocl
|
||||
pub server_login_state: ServerLogin<CS>,
|
||||
pub state: ServerLogin<CS>,
|
||||
/// The client's static public key
|
||||
pub client_s_pk: Vec<u8>,
|
||||
/// The plaintext info sent by the client
|
||||
pub plain_info: Vec<u8>,
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a server login finish
|
||||
pub struct ServerLoginFinishResult {
|
||||
/// The shared session secret between client and server
|
||||
pub shared_secret: Vec<u8>,
|
||||
/// The plaintext info sent by the client
|
||||
pub plain_info: Vec<u8>,
|
||||
/// The confidential info sent by the client
|
||||
pub confidential_info: Vec<u8>,
|
||||
/// The shared session secret between client and server
|
||||
pub session_secret: Vec<u8>,
|
||||
}
|
||||
|
||||
impl ServerLoginFinishResult {}
|
||||
|
||||
impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
/// byte representation for the server's login state
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
@@ -796,20 +817,20 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let mut server_rng = OsRng;
|
||||
/// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?;
|
||||
/// # let (register_m1, client_state) = ClientRegistration::<Default>::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?;
|
||||
/// # let (register_m2, server_state) =
|
||||
/// ServerRegistration::<Default>::start(register_m1, server_kp.public(), &mut server_rng)?;
|
||||
/// # let (register_m3, _export_key) = client_state.finish(register_m2, &mut client_rng)?;
|
||||
/// # let p_file = server_state.finish(register_m3)?;
|
||||
/// let client_login_start_result = ClientLogin::<Default>::start(b"hunter2", &mut client_rng, ClientLoginStartParameters::default())?;
|
||||
/// let server_login_start_result = ServerLogin::start(p_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||
/// # let client_registration_start_result = ClientRegistration::<Default>::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?;
|
||||
/// # let server_registration_start_result =
|
||||
/// ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
/// # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
/// # let p_file = server_registration_start_result.state.finish(client_registration_finish_result.message)?;
|
||||
/// let client_login_start_result = ClientLogin::<Default>::start(&mut client_rng, b"hunter2", ClientLoginStartParameters::default())?;
|
||||
/// let server_login_start_result = ServerLogin::start(&mut server_rng, p_file, &server_kp.private(), client_login_start_result.message, ServerLoginStartParameters::default())?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn start<R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
password_file: ServerRegistration<CS>,
|
||||
server_s_sk: &<CS::KeyFormat as KeyPair>::Repr,
|
||||
l1: LoginFirstMessage<CS>,
|
||||
rng: &mut R,
|
||||
l1: CredentialRequest<CS>,
|
||||
params: ServerLoginStartParameters,
|
||||
) -> Result<ServerLoginStartResult<CS>, ProtocolError> {
|
||||
let client_s_pk = password_file
|
||||
@@ -853,7 +874,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
e_info,
|
||||
)?;
|
||||
|
||||
let l2 = LoginSecondMessage {
|
||||
let l2 = CredentialResponse {
|
||||
beta,
|
||||
envelope,
|
||||
ke2_message,
|
||||
@@ -861,8 +882,8 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
|
||||
Ok(ServerLoginStartResult {
|
||||
plain_info,
|
||||
credential_response: l2,
|
||||
server_login_state: Self {
|
||||
message: l2,
|
||||
state: Self {
|
||||
_cs: PhantomData,
|
||||
ke2_state,
|
||||
},
|
||||
@@ -896,22 +917,22 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
/// let mut client_rng = OsRng;
|
||||
/// let mut server_rng = OsRng;
|
||||
/// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?;
|
||||
/// # let (register_m1, client_state) = ClientRegistration::<Default>::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?;
|
||||
/// # let (register_m2, server_state) =
|
||||
/// ServerRegistration::<Default>::start(register_m1, server_kp.public(), &mut server_rng)?;
|
||||
/// # let (register_m3, _export_key) = client_state.finish(register_m2, &mut client_rng)?;
|
||||
/// # let p_file = server_state.finish(register_m3)?;
|
||||
/// let client_login_start_result = ClientLogin::<Default>::start(b"hunter2", &mut client_rng, ClientLoginStartParameters::default())?;
|
||||
/// let server_login_start_result = ServerLogin::start(p_file, &server_kp.private(), client_login_start_result.credential_request, &mut server_rng, ServerLoginStartParameters::default())?;
|
||||
/// let client_login_finish_result = client_login_start_result.client_login_state.finish(server_login_start_result.credential_response, ClientLoginFinishParameters::default())?;
|
||||
/// let mut server_transport = server_login_start_result.server_login_state.finish(client_login_finish_result.key_exchange)?;
|
||||
/// # let client_registration_start_result = ClientRegistration::<Default>::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?;
|
||||
/// # let server_registration_start_result =
|
||||
/// ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
/// # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
/// # let p_file = server_registration_start_result.state.finish(client_registration_finish_result.message)?;
|
||||
/// let client_login_start_result = ClientLogin::<Default>::start(&mut client_rng, b"hunter2", ClientLoginStartParameters::default())?;
|
||||
/// let server_login_start_result = ServerLogin::start(&mut server_rng, p_file, &server_kp.private(), client_login_start_result.message, ServerLoginStartParameters::default())?;
|
||||
/// let client_login_finish_result = client_login_start_result.state.finish(server_login_start_result.message, ClientLoginFinishParameters::default())?;
|
||||
/// let mut server_transport = server_login_start_result.state.finish(client_login_finish_result.message)?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn finish(
|
||||
&self,
|
||||
message: LoginThirdMessage<CS>,
|
||||
message: CredentialFinalization<CS>,
|
||||
) -> Result<ServerLoginFinishResult, ProtocolError> {
|
||||
let (plain_info, confidential_info, session_secret) =
|
||||
let (plain_info, confidential_info, shared_secret) =
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::KeyFormat>>::finish_ke(
|
||||
message.ke3_message,
|
||||
&self.ke2_state,
|
||||
@@ -926,7 +947,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
Ok(ServerLoginFinishResult {
|
||||
plain_info,
|
||||
confidential_info,
|
||||
session_secret,
|
||||
shared_secret,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -121,7 +121,7 @@ fn register_first_message_roundtrip() {
|
||||
input.extend_from_slice(&alpha_length.to_be_bytes()[std::mem::size_of::<usize>() - 2..]);
|
||||
input.extend_from_slice(pt_bytes.as_slice());
|
||||
|
||||
let r1 = RegisterFirstMessage::<RistrettoPoint>::deserialize(input.as_slice()).unwrap();
|
||||
let r1 = RegistrationRequest::<RistrettoPoint>::deserialize(input.as_slice()).unwrap();
|
||||
let r1_bytes = r1.serialize();
|
||||
assert_eq!(input, r1_bytes);
|
||||
}
|
||||
@@ -145,7 +145,7 @@ fn register_second_message_roundtrip() {
|
||||
input.extend_from_slice(&pubkey_bytes.as_slice());
|
||||
input.extend_from_slice(&credential_types);
|
||||
|
||||
let r2 = RegisterSecondMessage::<RistrettoPoint>::deserialize(input.as_slice()).unwrap();
|
||||
let r2 = RegistrationResponse::<RistrettoPoint>::deserialize(input.as_slice()).unwrap();
|
||||
let r2_bytes = r2.serialize();
|
||||
assert_eq!(input, r2_bytes);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ fn register_third_message_roundtrip() {
|
||||
input.extend_from_slice(&pubkey_length.to_be_bytes()[std::mem::size_of::<usize>() - 2..]);
|
||||
input.extend_from_slice(&pubkey_bytes[..]);
|
||||
|
||||
let r3 = RegisterThirdMessage::<X25519KeyPair, sha2::Sha256>::deserialize(&input[..]).unwrap();
|
||||
let r3 = RegistrationUpload::<X25519KeyPair, sha2::Sha256>::deserialize(&input[..]).unwrap();
|
||||
let r3_bytes = r3.serialize();
|
||||
assert_eq!(input, r3_bytes);
|
||||
}
|
||||
@@ -205,7 +205,7 @@ fn login_first_message_roundtrip() {
|
||||
input.extend_from_slice(&alpha_bytes);
|
||||
input.extend_from_slice(&ke1m[..]);
|
||||
|
||||
let l1 = LoginFirstMessage::<Default>::deserialize(input.as_slice()).unwrap();
|
||||
let l1 = CredentialRequest::<Default>::deserialize(input.as_slice()).unwrap();
|
||||
let l1_bytes = l1.serialize();
|
||||
assert_eq!(input, l1_bytes);
|
||||
}
|
||||
@@ -254,7 +254,7 @@ fn login_second_message_roundtrip() {
|
||||
input.extend_from_slice(&envelope.serialize());
|
||||
input.extend_from_slice(&ke2m[..]);
|
||||
|
||||
let l2 = LoginSecondMessage::<Default>::deserialize(&input).unwrap();
|
||||
let l2 = CredentialResponse::<Default>::deserialize(&input).unwrap();
|
||||
let l2_bytes = l2.serialize();
|
||||
assert_eq!(input, l2_bytes);
|
||||
}
|
||||
@@ -276,7 +276,7 @@ fn login_third_message_roundtrip() {
|
||||
]
|
||||
.concat();
|
||||
|
||||
let l3 = LoginThirdMessage::<Default>::deserialize(&input).unwrap();
|
||||
let l3 = CredentialFinalization::<Default>::deserialize(&input).unwrap();
|
||||
let l3_bytes = l3.serialize();
|
||||
assert_eq!(input, l3_bytes);
|
||||
}
|
||||
@@ -403,32 +403,32 @@ fn test_i2osp_os2ip(bytes in vec(any::<u8>(), 0..std::mem::size_of::<usize>()))
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_register_first_message(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegisterFirstMessage::<RistrettoPoint>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
RegistrationRequest::<RistrettoPoint>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_register_second_message(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegisterSecondMessage::<RistrettoPoint>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
RegistrationResponse::<RistrettoPoint>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_register_third_message(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegisterThirdMessage::<crate::keypair::X25519KeyPair, sha2::Sha512>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
RegistrationUpload::<crate::keypair::X25519KeyPair, sha2::Sha512>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_login_first_message(bytes in vec(any::<u8>(), 0..500)) {
|
||||
LoginFirstMessage::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
CredentialRequest::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_login_second_message(bytes in vec(any::<u8>(), 0..500)) {
|
||||
LoginSecondMessage::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
CredentialResponse::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_login_third_message(bytes in vec(any::<u8>(), 0..500)) {
|
||||
LoginThirdMessage::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
CredentialFinalization::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+183
-128
@@ -55,12 +55,12 @@ pub struct TestVectorParameters {
|
||||
pub einfo2: Vec<u8>,
|
||||
pub info3: Vec<u8>,
|
||||
pub einfo3: Vec<u8>,
|
||||
pub r1: Vec<u8>,
|
||||
pub r2: Vec<u8>,
|
||||
pub r3: Vec<u8>,
|
||||
pub l1: Vec<u8>,
|
||||
pub l2: Vec<u8>,
|
||||
pub l3: Vec<u8>,
|
||||
pub registration_request: Vec<u8>,
|
||||
pub registration_response: Vec<u8>,
|
||||
pub message: Vec<u8>,
|
||||
pub credential_request: Vec<u8>,
|
||||
pub credential_response: Vec<u8>,
|
||||
pub key_exchange: Vec<u8>,
|
||||
client_registration_state: Vec<u8>,
|
||||
server_registration_state: Vec<u8>,
|
||||
client_login_state: Vec<u8>,
|
||||
@@ -93,12 +93,12 @@ static TEST_VECTOR: &str = r#"
|
||||
"einfo2": "65696e666f32",
|
||||
"info3": "696e666f33",
|
||||
"einfo3": "65696e666f33",
|
||||
"r1": "0020c4ad91692b704470e0613850b9bfcc5b265d43f9ba03dd6ff028f0fb6b365957",
|
||||
"r2": "00205cbfd7b74c7fe6088f8117e7e63000675762920b75e0f4630ed67d4d960c7aa80020b8c5defc933aaf3640d13f217c392e06fe5fd41fae8571204fcbb804a566cd2e01010103",
|
||||
"r3": "abb706633ac7092e2aa63dedd4b456d7d99870f099c4f2c51ba75da0f20db8e80023e76da9b9fbf400fea214ecdab24966e4d3fea9d0c3d5d672597e1e702eb30547495ada0023030020b8c5defc933aaf3640d13f217c392e06fe5fd41fae8571204fcbb804a566cd2e00204e0e5754fbbd48efcdab43cee37f6455f357f3edc54316cb69da8f8e92f5ed8900205320b55752ad2061c1804050f8a225a4ab1184bc17d8fa6b3c86470c33d9ce42",
|
||||
"l1": "0020c4ad91692b704470e0613850b9bfcc5b265d43f9ba03dd6ff028f0fb6b3659571a92d39b2f9acdbef96dcc586b35ae056a085ede41b05f9f81801f69558d44c70005696e666f3177fc3fefb8178ae08461756b54364c4f2d1363d5ce3187af128a3f84a6c5722a",
|
||||
"l2": "00205cbfd7b74c7fe6088f8117e7e63000675762920b75e0f4630ed67d4d960c7aa8abb706633ac7092e2aa63dedd4b456d7d99870f099c4f2c51ba75da0f20db8e80023e76da9b9fbf400fea214ecdab24966e4d3fea9d0c3d5d672597e1e702eb30547495ada0023030020b8c5defc933aaf3640d13f217c392e06fe5fd41fae8571204fcbb804a566cd2e00204e0e5754fbbd48efcdab43cee37f6455f357f3edc54316cb69da8f8e92f5ed89606034b9be54759ea5802a2dd71e4413e98d52c46e60f2d0868642ad9e6a9b460005696e666f325a314dc389c12bf041b14e131fadebcc98e0fc33d3cd996ad9392c7ae6bff468000665696e666f32661aa1d3e579032df30a78312d38a4c3d8d8a0f1b9bb7bbdbff040e0881a248e",
|
||||
"l3": "0005696e666f33000665696e666f3317090781af5a220941ddd6db7d4f2af33d9b316a48aee163647131970bae50ba",
|
||||
"registration_request": "0020c4ad91692b704470e0613850b9bfcc5b265d43f9ba03dd6ff028f0fb6b365957",
|
||||
"registration_response": "00205cbfd7b74c7fe6088f8117e7e63000675762920b75e0f4630ed67d4d960c7aa80020b8c5defc933aaf3640d13f217c392e06fe5fd41fae8571204fcbb804a566cd2e01010103",
|
||||
"message": "abb706633ac7092e2aa63dedd4b456d7d99870f099c4f2c51ba75da0f20db8e80023e76da9b9fbf400fea214ecdab24966e4d3fea9d0c3d5d672597e1e702eb30547495ada0023030020b8c5defc933aaf3640d13f217c392e06fe5fd41fae8571204fcbb804a566cd2e00204e0e5754fbbd48efcdab43cee37f6455f357f3edc54316cb69da8f8e92f5ed8900205320b55752ad2061c1804050f8a225a4ab1184bc17d8fa6b3c86470c33d9ce42",
|
||||
"credential_request": "0020c4ad91692b704470e0613850b9bfcc5b265d43f9ba03dd6ff028f0fb6b3659571a92d39b2f9acdbef96dcc586b35ae056a085ede41b05f9f81801f69558d44c70005696e666f3177fc3fefb8178ae08461756b54364c4f2d1363d5ce3187af128a3f84a6c5722a",
|
||||
"credential_response": "00205cbfd7b74c7fe6088f8117e7e63000675762920b75e0f4630ed67d4d960c7aa8abb706633ac7092e2aa63dedd4b456d7d99870f099c4f2c51ba75da0f20db8e80023e76da9b9fbf400fea214ecdab24966e4d3fea9d0c3d5d672597e1e702eb30547495ada0023030020b8c5defc933aaf3640d13f217c392e06fe5fd41fae8571204fcbb804a566cd2e00204e0e5754fbbd48efcdab43cee37f6455f357f3edc54316cb69da8f8e92f5ed89606034b9be54759ea5802a2dd71e4413e98d52c46e60f2d0868642ad9e6a9b460005696e666f325a314dc389c12bf041b14e131fadebcc98e0fc33d3cd996ad9392c7ae6bff468000665696e666f32661aa1d3e579032df30a78312d38a4c3d8d8a0f1b9bb7bbdbff040e0881a248e",
|
||||
"key_exchange": "0005696e666f33000665696e666f3317090781af5a220941ddd6db7d4f2af33d9b316a48aee163647131970bae50ba",
|
||||
"client_registration_state": "00036964550003696453c0accb2010d728cfce827d4cb3769000c8b42ac341db8ba196fbe75809d9130070617373776f7264",
|
||||
"client_login_state": "00036964550003696453c0accb2010d728cfce827d4cb3769000c8b42ac341db8ba196fbe75809d9130048b452f6d0b28387cfa98245bda9230b6df215ed5b820bffb8511ec6802d80751a92d39b2f9acdbef96dcc586b35ae056a085ede41b05f9f81801f69558d44c7288b735853d9e1d8ab699b7c4aef54680f036c56140dc0a4991f6d02a95babc970617373776f7264",
|
||||
"server_registration_state": "7f1d2a048a7aad9d1cf2b96473e3adbb1e0626eafe0abdfd09f1f700beda9d0f",
|
||||
@@ -138,12 +138,12 @@ fn populate_test_vectors(values: &Value) -> TestVectorParameters {
|
||||
einfo2: decode(&values, "einfo2").unwrap(),
|
||||
info3: decode(&values, "info3").unwrap(),
|
||||
einfo3: decode(&values, "einfo3").unwrap(),
|
||||
r1: decode(&values, "r1").unwrap(),
|
||||
r2: decode(&values, "r2").unwrap(),
|
||||
r3: decode(&values, "r3").unwrap(),
|
||||
l1: decode(&values, "l1").unwrap(),
|
||||
l2: decode(&values, "l2").unwrap(),
|
||||
l3: decode(&values, "l3").unwrap(),
|
||||
registration_request: decode(&values, "registration_request").unwrap(),
|
||||
registration_response: decode(&values, "registration_response").unwrap(),
|
||||
message: decode(&values, "message").unwrap(),
|
||||
credential_request: decode(&values, "credential_request").unwrap(),
|
||||
credential_response: decode(&values, "credential_response").unwrap(),
|
||||
key_exchange: decode(&values, "key_exchange").unwrap(),
|
||||
client_registration_state: decode(&values, "client_registration_state").unwrap(),
|
||||
client_login_state: decode(&values, "client_login_state").unwrap(),
|
||||
server_registration_state: decode(&values, "server_registration_state").unwrap(),
|
||||
@@ -190,12 +190,36 @@ fn stringify_test_vectors(p: &TestVectorParameters) -> String {
|
||||
s.push_str(format!("\"einfo2\": \"{}\",\n", hex::encode(&p.einfo2)).as_str());
|
||||
s.push_str(format!("\"info3\": \"{}\",\n", hex::encode(&p.info3)).as_str());
|
||||
s.push_str(format!("\"einfo3\": \"{}\",\n", hex::encode(&p.einfo3)).as_str());
|
||||
s.push_str(format!("\"r1\": \"{}\",\n", hex::encode(&p.r1)).as_str());
|
||||
s.push_str(format!("\"r2\": \"{}\",\n", hex::encode(&p.r2)).as_str());
|
||||
s.push_str(format!("\"r3\": \"{}\",\n", hex::encode(&p.r3)).as_str());
|
||||
s.push_str(format!("\"l1\": \"{}\",\n", hex::encode(&p.l1)).as_str());
|
||||
s.push_str(format!("\"l2\": \"{}\",\n", hex::encode(&p.l2)).as_str());
|
||||
s.push_str(format!("\"l3\": \"{}\",\n", hex::encode(&p.l3)).as_str());
|
||||
s.push_str(
|
||||
format!(
|
||||
"\"registration_request\": \"{}\",\n",
|
||||
hex::encode(&p.registration_request)
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
s.push_str(
|
||||
format!(
|
||||
"\"registration_response\": \"{}\",\n",
|
||||
hex::encode(&p.registration_response)
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
s.push_str(format!("\"message\": \"{}\",\n", hex::encode(&p.message)).as_str());
|
||||
s.push_str(
|
||||
format!(
|
||||
"\"credential_request\": \"{}\",\n",
|
||||
hex::encode(&p.credential_request)
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
s.push_str(
|
||||
format!(
|
||||
"\"credential_response\": \"{}\",\n",
|
||||
hex::encode(&p.credential_response)
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
s.push_str(format!("\"key_exchange\": \"{}\",\n", hex::encode(&p.key_exchange)).as_str());
|
||||
s.push_str(
|
||||
format!(
|
||||
"\"client_registration_state\": \"{}\",\n",
|
||||
@@ -277,36 +301,57 @@ where
|
||||
let einfo3 = b"einfo3";
|
||||
|
||||
let mut blinding_factor_registration_rng = CycleRng::new(blinding_factor_raw.to_vec());
|
||||
let (r1, client_registration) = ClientRegistration::<CS>::start(
|
||||
let client_registration_start_result = ClientRegistration::<CS>::start(
|
||||
&mut blinding_factor_registration_rng,
|
||||
password,
|
||||
ClientRegistrationStartParameters::WithIdentifiers(id_u.to_vec(), id_s.to_vec()),
|
||||
&mut blinding_factor_registration_rng,
|
||||
std::convert::identity,
|
||||
)
|
||||
.unwrap();
|
||||
let r1_bytes = r1.serialize().to_vec();
|
||||
let registration_request_bytes = client_registration_start_result
|
||||
.message
|
||||
.serialize()
|
||||
.to_vec();
|
||||
let blinding_factor_bytes =
|
||||
CS::Group::scalar_as_bytes(&client_registration.token.blind).clone();
|
||||
let client_registration_state = client_registration.to_bytes().to_vec();
|
||||
CS::Group::scalar_as_bytes(&client_registration_start_result.state.token.blind).clone();
|
||||
let client_registration_state = client_registration_start_result.state.to_bytes().to_vec();
|
||||
|
||||
let mut oprf_key_rng = CycleRng::new(oprf_key_raw.to_vec());
|
||||
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 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_start_result = ServerRegistration::<CS>::start(
|
||||
&mut oprf_key_rng,
|
||||
client_registration_start_result.message,
|
||||
server_s_kp.public(),
|
||||
)
|
||||
.unwrap();
|
||||
let registration_response_bytes = server_registration_start_result
|
||||
.message
|
||||
.serialize()
|
||||
.to_vec();
|
||||
let oprf_key_bytes =
|
||||
CS::Group::scalar_as_bytes(&server_registration_start_result.state.oprf_key).clone();
|
||||
let server_registration_state = server_registration_start_result.state.to_bytes().to_vec();
|
||||
|
||||
let mut client_s_sk_and_nonce: Vec<u8> = Vec::new();
|
||||
client_s_sk_and_nonce.extend_from_slice(&client_s_kp.private().to_arr());
|
||||
client_s_sk_and_nonce.extend_from_slice(&envelope_nonce);
|
||||
|
||||
let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce);
|
||||
let (r3, export_key_registration) = client_registration
|
||||
.finish(r2, &mut finish_registration_rng)
|
||||
let client_registration_finish_result = client_registration_start_result
|
||||
.state
|
||||
.finish(
|
||||
&mut finish_registration_rng,
|
||||
server_registration_start_result.message,
|
||||
)
|
||||
.unwrap();
|
||||
let r3_bytes = r3.serialize().to_vec();
|
||||
let message_bytes = client_registration_finish_result
|
||||
.message
|
||||
.serialize()
|
||||
.to_vec();
|
||||
|
||||
let password_file = server_registration.finish(r3).unwrap();
|
||||
let password_file = server_registration_start_result
|
||||
.state
|
||||
.finish(client_registration_finish_result.message)
|
||||
.unwrap();
|
||||
let password_file_bytes = password_file.to_bytes();
|
||||
|
||||
let mut client_login_start: Vec<u8> = Vec::new();
|
||||
@@ -316,8 +361,8 @@ where
|
||||
|
||||
let mut client_login_start_rng = CycleRng::new(client_login_start);
|
||||
let client_login_start_result = ClientLogin::<CS>::start(
|
||||
password,
|
||||
&mut client_login_start_rng,
|
||||
password,
|
||||
ClientLoginStartParameters::WithInfoAndIdentifiers(
|
||||
info1.to_vec(),
|
||||
id_u.to_vec(),
|
||||
@@ -326,41 +371,29 @@ where
|
||||
std::convert::identity,
|
||||
)
|
||||
.unwrap();
|
||||
let l1_bytes = client_login_start_result
|
||||
.credential_request
|
||||
.serialize()
|
||||
.to_vec();
|
||||
let client_login_state = client_login_start_result
|
||||
.client_login_state
|
||||
.to_bytes()
|
||||
.to_vec();
|
||||
let credential_request_bytes = client_login_start_result.message.serialize().to_vec();
|
||||
let client_login_state = client_login_start_result.state.to_bytes().to_vec();
|
||||
|
||||
let mut server_e_sk_rng = CycleRng::new(server_e_kp.private().to_arr().to_vec());
|
||||
let server_login_start_result = ServerLogin::<CS>::start(
|
||||
&mut server_e_sk_rng,
|
||||
password_file,
|
||||
server_s_kp.private(),
|
||||
client_login_start_result.credential_request,
|
||||
&mut server_e_sk_rng,
|
||||
client_login_start_result.message,
|
||||
ServerLoginStartParameters::WithInfo(info2.to_vec(), einfo2.to_vec()),
|
||||
)
|
||||
.unwrap();
|
||||
let l2_bytes = server_login_start_result
|
||||
.credential_response
|
||||
.serialize()
|
||||
.to_vec();
|
||||
let server_login_state = server_login_start_result
|
||||
.server_login_state
|
||||
.to_bytes()
|
||||
.to_vec();
|
||||
let credential_response_bytes = server_login_start_result.message.serialize().to_vec();
|
||||
let server_login_state = server_login_start_result.state.to_bytes().to_vec();
|
||||
|
||||
let client_login_finish_result = client_login_start_result
|
||||
.client_login_state
|
||||
.state
|
||||
.finish(
|
||||
server_login_start_result.credential_response,
|
||||
server_login_start_result.message,
|
||||
ClientLoginFinishParameters::WithInfo(info3.to_vec(), einfo3.to_vec()),
|
||||
)
|
||||
.unwrap();
|
||||
let l3_bytes = client_login_finish_result.key_exchange.to_bytes().to_vec();
|
||||
let key_exchange_bytes = client_login_finish_result.message.to_bytes().to_vec();
|
||||
|
||||
TestVectorParameters {
|
||||
client_s_pk: client_s_kp.public().to_arr().to_vec(),
|
||||
@@ -384,19 +417,19 @@ where
|
||||
einfo2: einfo2.to_vec(),
|
||||
info3: info3.to_vec(),
|
||||
einfo3: einfo3.to_vec(),
|
||||
r1: r1_bytes,
|
||||
r2: r2_bytes,
|
||||
r3: r3_bytes,
|
||||
l1: l1_bytes,
|
||||
l2: l2_bytes,
|
||||
l3: l3_bytes,
|
||||
registration_request: registration_request_bytes,
|
||||
registration_response: registration_response_bytes,
|
||||
message: message_bytes,
|
||||
credential_request: credential_request_bytes,
|
||||
credential_response: credential_response_bytes,
|
||||
key_exchange: key_exchange_bytes,
|
||||
password_file: password_file_bytes,
|
||||
client_registration_state,
|
||||
server_registration_state,
|
||||
client_login_state,
|
||||
server_login_state,
|
||||
shared_secret: client_login_finish_result.session_secret,
|
||||
export_key: export_key_registration.to_vec(),
|
||||
shared_secret: client_login_finish_result.shared_secret,
|
||||
export_key: client_registration_finish_result.export_key.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,58 +446,68 @@ fn postprocess_blinding_factor<G: Group>(_: G::Scalar) -> G::Scalar {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_r1() -> Result<(), ProtocolError> {
|
||||
fn test_registration_request() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
let mut rng = OsRng;
|
||||
let (r1, client_registration) = ClientRegistration::<X255193dhNoSlowHash>::start(
|
||||
let client_registration_start_result = ClientRegistration::<X255193dhNoSlowHash>::start(
|
||||
&mut rng,
|
||||
¶meters.password,
|
||||
ClientRegistrationStartParameters::WithIdentifiers(parameters.id_u, parameters.id_s),
|
||||
&mut rng,
|
||||
postprocess_blinding_factor::<<X255193dhNoSlowHash as CipherSuite>::Group>,
|
||||
)?;
|
||||
assert_eq!(hex::encode(¶meters.r1), hex::encode(r1.serialize()));
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.registration_request),
|
||||
hex::encode(client_registration_start_result.message.serialize())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.client_registration_state),
|
||||
hex::encode(client_registration.to_bytes())
|
||||
hex::encode(client_registration_start_result.state.to_bytes())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_r2() -> Result<(), ProtocolError> {
|
||||
fn test_registration_response() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
let mut oprf_key_rng = CycleRng::new(parameters.oprf_key);
|
||||
let (r2, server_registration) = ServerRegistration::<X255193dhNoSlowHash>::start(
|
||||
RegisterFirstMessage::deserialize(¶meters.r1[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_s_pk[..]).unwrap(),
|
||||
let server_registration_start_result = ServerRegistration::<X255193dhNoSlowHash>::start(
|
||||
&mut oprf_key_rng,
|
||||
RegistrationRequest::deserialize(¶meters.registration_request[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_s_pk[..]).unwrap(),
|
||||
)?;
|
||||
assert_eq!(hex::encode(parameters.r2), hex::encode(r2.serialize()));
|
||||
assert_eq!(
|
||||
hex::encode(parameters.registration_response),
|
||||
hex::encode(server_registration_start_result.message.serialize())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.server_registration_state),
|
||||
hex::encode(server_registration.to_bytes())
|
||||
hex::encode(server_registration_start_result.state.to_bytes())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_r3() -> Result<(), ProtocolError> {
|
||||
fn test_message() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let client_s_sk_and_nonce: Vec<u8> =
|
||||
[parameters.client_s_sk, parameters.envelope_nonce].concat();
|
||||
let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce);
|
||||
let (r3, export_key_registration) = ClientRegistration::<X255193dhNoSlowHash>::try_from(
|
||||
let result = ClientRegistration::<X255193dhNoSlowHash>::try_from(
|
||||
¶meters.client_registration_state[..],
|
||||
)?
|
||||
.finish(
|
||||
RegisterSecondMessage::deserialize(¶meters.r2[..]).unwrap(),
|
||||
&mut finish_registration_rng,
|
||||
RegistrationResponse::deserialize(¶meters.registration_response[..]).unwrap(),
|
||||
)?;
|
||||
assert_eq!(hex::encode(parameters.r3), hex::encode(r3.serialize()));
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parameters.message),
|
||||
hex::encode(result.message.serialize())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(parameters.export_key),
|
||||
hex::encode(export_key_registration.to_vec())
|
||||
hex::encode(result.export_key.to_vec())
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -478,7 +521,8 @@ fn test_password_file() -> Result<(), ProtocolError> {
|
||||
¶meters.server_registration_state[..],
|
||||
)?;
|
||||
let password_file = server_registration
|
||||
.finish(RegisterThirdMessage::deserialize(¶meters.r3[..]).unwrap())?;
|
||||
.finish(RegistrationUpload::deserialize(¶meters.message[..]).unwrap())?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parameters.password_file),
|
||||
hex::encode(password_file.to_bytes())
|
||||
@@ -487,7 +531,7 @@ fn test_password_file() -> Result<(), ProtocolError> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_l1() -> Result<(), ProtocolError> {
|
||||
fn test_credential_request() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let client_login_start = [
|
||||
@@ -498,8 +542,8 @@ fn test_l1() -> Result<(), ProtocolError> {
|
||||
.concat();
|
||||
let mut client_login_start_rng = CycleRng::new(client_login_start);
|
||||
let client_login_start_result = ClientLogin::<X255193dhNoSlowHash>::start(
|
||||
¶meters.password,
|
||||
&mut client_login_start_rng,
|
||||
¶meters.password,
|
||||
ClientLoginStartParameters::WithInfoAndIdentifiers(
|
||||
parameters.info1,
|
||||
parameters.id_u,
|
||||
@@ -508,26 +552,27 @@ fn test_l1() -> Result<(), ProtocolError> {
|
||||
postprocess_blinding_factor::<<X255193dhNoSlowHash as CipherSuite>::Group>,
|
||||
)?;
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.l1),
|
||||
hex::encode(client_login_start_result.credential_request.serialize())
|
||||
hex::encode(¶meters.credential_request),
|
||||
hex::encode(client_login_start_result.message.serialize())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.client_login_state),
|
||||
hex::encode(client_login_start_result.client_login_state.to_bytes())
|
||||
hex::encode(client_login_start_result.state.to_bytes())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_l2() -> Result<(), ProtocolError> {
|
||||
fn test_credential_response() -> Result<(), ProtocolError> {
|
||||
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 server_login_start_result = ServerLogin::<X255193dhNoSlowHash>::start(
|
||||
&mut server_e_sk_rng,
|
||||
ServerRegistration::try_from(¶meters.password_file[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_s_sk[..]).unwrap(),
|
||||
LoginFirstMessage::<X255193dhNoSlowHash>::deserialize(¶meters.l1[..]).unwrap(),
|
||||
&mut server_e_sk_rng,
|
||||
CredentialRequest::<X255193dhNoSlowHash>::deserialize(¶meters.credential_request[..])
|
||||
.unwrap(),
|
||||
ServerLoginStartParameters::WithInfo(parameters.info2.to_vec(), parameters.einfo2.to_vec()),
|
||||
)?;
|
||||
assert_eq!(
|
||||
@@ -539,28 +584,33 @@ fn test_l2() -> Result<(), ProtocolError> {
|
||||
hex::encode(server_login_start_result.client_s_pk),
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.l2),
|
||||
hex::encode(server_login_start_result.credential_response.serialize())
|
||||
hex::encode(¶meters.credential_response),
|
||||
hex::encode(server_login_start_result.message.serialize())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.server_login_state),
|
||||
hex::encode(server_login_start_result.server_login_state.to_bytes())
|
||||
hex::encode(server_login_start_result.state.to_bytes())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_l3() -> Result<(), ProtocolError> {
|
||||
fn test_key_exchange() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let client_login_finish_result =
|
||||
ClientLogin::<X255193dhNoSlowHash>::try_from(¶meters.client_login_state[..])?.finish(
|
||||
LoginSecondMessage::<X255193dhNoSlowHash>::deserialize(¶meters.l2[..]).unwrap(),
|
||||
ClientLoginFinishParameters::WithInfo(
|
||||
parameters.info3.to_vec(),
|
||||
parameters.einfo3.to_vec(),
|
||||
),
|
||||
)?;
|
||||
ClientLogin::<X255193dhNoSlowHash>::try_from(¶meters.client_login_state[..])
|
||||
.unwrap()
|
||||
.finish(
|
||||
CredentialResponse::<X255193dhNoSlowHash>::deserialize(
|
||||
¶meters.credential_response[..],
|
||||
)?,
|
||||
ClientLoginFinishParameters::WithInfo(
|
||||
parameters.info3.to_vec(),
|
||||
parameters.einfo3.to_vec(),
|
||||
),
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.info2),
|
||||
hex::encode(&client_login_finish_result.plain_info)
|
||||
@@ -576,11 +626,11 @@ fn test_l3() -> Result<(), ProtocolError> {
|
||||
assert_eq!(None, client_login_finish_result.id_s);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.shared_secret),
|
||||
hex::encode(&client_login_finish_result.session_secret)
|
||||
hex::encode(&client_login_finish_result.shared_secret)
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.l3),
|
||||
hex::encode(client_login_finish_result.key_exchange.to_bytes())
|
||||
hex::encode(¶meters.key_exchange),
|
||||
hex::encode(client_login_finish_result.message.to_bytes())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.export_key),
|
||||
@@ -595,8 +645,10 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let server_login_result =
|
||||
ServerLogin::<X255193dhNoSlowHash>::try_from(¶meters.server_login_state[..])?
|
||||
.finish(LoginThirdMessage::try_from(¶meters.l3[..])?)?;
|
||||
ServerLogin::<X255193dhNoSlowHash>::try_from(¶meters.server_login_state[..])?.finish(
|
||||
CredentialFinalization::try_from(¶meters.key_exchange[..])?,
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parameters.info3),
|
||||
hex::encode(server_login_result.plain_info)
|
||||
@@ -607,7 +659,7 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(parameters.shared_secret),
|
||||
hex::encode(server_login_result.session_secret)
|
||||
hex::encode(server_login_result.shared_secret)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -620,51 +672,54 @@ fn test_complete_flow(
|
||||
let mut client_rng = OsRng;
|
||||
let mut server_rng = OsRng;
|
||||
let server_kp = X255193dhNoSlowHash::generate_random_keypair(&mut server_rng)?;
|
||||
let (register_m1, client_state) = ClientRegistration::<X255193dhNoSlowHash>::start(
|
||||
let client_registration_start_result = ClientRegistration::<X255193dhNoSlowHash>::start(
|
||||
&mut client_rng,
|
||||
registration_password,
|
||||
ClientRegistrationStartParameters::default(),
|
||||
&mut client_rng,
|
||||
std::convert::identity,
|
||||
)?;
|
||||
let (register_m2, server_state) = ServerRegistration::<X255193dhNoSlowHash>::start(
|
||||
register_m1,
|
||||
server_kp.public(),
|
||||
let server_registration_start_result = ServerRegistration::<X255193dhNoSlowHash>::start(
|
||||
&mut server_rng,
|
||||
client_registration_start_result.message,
|
||||
server_kp.public(),
|
||||
)?;
|
||||
let (register_m3, registration_export_key) =
|
||||
client_state.finish(register_m2, &mut client_rng)?;
|
||||
let p_file = server_state.finish(register_m3)?;
|
||||
let client_registration_finish_result = client_registration_start_result
|
||||
.state
|
||||
.finish(&mut client_rng, server_registration_start_result.message)?;
|
||||
let p_file = server_registration_start_result
|
||||
.state
|
||||
.finish(client_registration_finish_result.message)?;
|
||||
let client_login_start_result = ClientLogin::<X255193dhNoSlowHash>::start(
|
||||
login_password,
|
||||
&mut client_rng,
|
||||
login_password,
|
||||
ClientLoginStartParameters::default(),
|
||||
std::convert::identity,
|
||||
)?;
|
||||
let server_login_start_result = ServerLogin::<X255193dhNoSlowHash>::start(
|
||||
&mut server_rng,
|
||||
p_file,
|
||||
&server_kp.private(),
|
||||
client_login_start_result.credential_request,
|
||||
&mut server_rng,
|
||||
client_login_start_result.message,
|
||||
ServerLoginStartParameters::default(),
|
||||
)?;
|
||||
|
||||
let client_login_result = client_login_start_result.client_login_state.finish(
|
||||
server_login_start_result.credential_response,
|
||||
let client_login_result = client_login_start_result.state.finish(
|
||||
server_login_start_result.message,
|
||||
ClientLoginFinishParameters::default(),
|
||||
);
|
||||
|
||||
if hex::encode(registration_password) == hex::encode(login_password) {
|
||||
let client_login_finish_result = client_login_result?;
|
||||
let server_login_finish_result = server_login_start_result
|
||||
.server_login_state
|
||||
.finish(client_login_finish_result.key_exchange)?;
|
||||
.state
|
||||
.finish(client_login_finish_result.message)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(server_login_finish_result.session_secret),
|
||||
hex::encode(client_login_finish_result.session_secret)
|
||||
hex::encode(server_login_finish_result.shared_secret),
|
||||
hex::encode(client_login_finish_result.shared_secret)
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(registration_export_key),
|
||||
hex::encode(client_registration_finish_result.export_key),
|
||||
hex::encode(client_login_finish_result.export_key)
|
||||
);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user