From 605d2b639b174087e4620aeb31082a5e2cd970f0 Mon Sep 17 00:00:00 2001 From: Kevin Lewi Date: Sat, 12 Dec 2020 21:53:33 -0800 Subject: [PATCH] Cleaning up docs + README (#98) --- README.md | 5 +- examples/simple_login.rs | 64 ++++---- src/lib.rs | 239 ++++++++++++++------------- src/messages.rs | 46 +++--- src/opaque.rs | 205 +++++++++++++----------- src/serialization/tests.rs | 24 +-- src/tests/opaque_ke_test.rs | 311 +++++++++++++++++++++--------------- 7 files changed, 498 insertions(+), 396 deletions(-) diff --git a/README.md b/README.md index 7320328..39f7ee6 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/examples/simple_login.rs b/examples/simple_login.rs index e724629..10edc97 100644 --- a/examples/simple_login.rs +++ b/examples/simple_login.rs @@ -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 { let mut client_rng = OsRng; - let (r1, client_state) = ClientRegistration::::start( + let client_registration_start_result = ClientRegistration::::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::::start( - RegisterFirstMessage::deserialize(&r1_bytes[..]).unwrap(), - server_kp.public(), + let server_registration_start_result = ServerRegistration::::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::::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::::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 diff --git a/src/lib.rs b/src/lib.rs index 6cbd4a4..9524851 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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::::start( +//! let client_registration_start_result = ClientRegistration::::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::::start( +//! # let client_registration_start_result = ClientRegistration::::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::::start(r1, server_kp.public(), &mut server_rng)?; +//! let server_registration_start_result = ServerRegistration::::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::::start( +//! # let client_registration_start_result = ClientRegistration::::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::::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::::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::::start( +//! # let client_registration_start_result = ClientRegistration::::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::::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::::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::::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::::start( +//! # let client_registration_start_result = ClientRegistration::::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::::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::::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::::start( -//! # b"password", //! # &mut client_rng, +//! # b"password", //! # ClientLoginStartParameters::default(), //! # )?; //! use opaque_ke::{ServerLogin, ServerLoginStartParameters}; //! use std::convert::TryFrom; //! let password_file = ServerRegistration::::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::::start( +//! # let client_registration_start_result = ClientRegistration::::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::::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::::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::::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::::start( +//! # let client_registration_start_result = ClientRegistration::::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::::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::::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::::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::{ diff --git a/src/messages.rs b/src/messages.rs index 5bda26a..543c941 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -26,12 +26,12 @@ use std::convert::TryFrom; // ========= /// The message sent by the client to the server, to initiate registration -pub struct RegisterFirstMessage { +pub struct RegistrationRequest { /// blinded password information pub(crate) alpha: Grp, } -impl TryFrom<&[u8]> for RegisterFirstMessage { +impl TryFrom<&[u8]> for RegistrationRequest { type Error = ProtocolError; fn try_from(first_message_bytes: &[u8]) -> Result { let elem_len = Grp::ElemLen::to_usize(); @@ -45,7 +45,7 @@ impl TryFrom<&[u8]> for RegisterFirstMessage { } } -impl RegisterFirstMessage { +impl RegistrationRequest { /// Byte representation for the registration request pub fn to_bytes(&self) -> Vec { self.alpha.to_arr().to_vec() @@ -79,7 +79,7 @@ impl RegisterFirstMessage { /// The answer sent by the server to the user, upon reception of the /// registration attempt -pub struct RegisterSecondMessage { +pub struct RegistrationResponse { /// The server's oprf output pub(crate) beta: Grp, /// Server's static public key @@ -88,7 +88,7 @@ pub struct RegisterSecondMessage { pub(crate) ecf: EnvelopeCredentialsFormat, } -impl TryFrom<&[u8]> for RegisterSecondMessage +impl TryFrom<&[u8]> for RegistrationResponse where Grp: Group, { @@ -116,7 +116,7 @@ where } } -impl RegisterSecondMessage +impl RegistrationResponse where Grp: Group, { @@ -196,7 +196,7 @@ where /// The final message from the client, containing sealed cryptographic /// identifiers -pub struct RegisterThirdMessage { +pub struct RegistrationUpload { /// The "envelope" generated by the user, containing sealed /// cryptographic identifiers pub(crate) envelope: Envelope, @@ -204,7 +204,7 @@ pub struct RegisterThirdMessage { pub(crate) client_s_pk: KeyFormat::Repr, } -impl TryFrom<&[u8]> for RegisterThirdMessage +impl TryFrom<&[u8]> for RegistrationUpload where KeyFormat: KeyPair, D: Hash, @@ -229,17 +229,17 @@ where } } -impl RegisterThirdMessage +impl RegistrationUpload where KeyFormat: KeyPair, D: Hash, { /// Serialization into bytes pub fn serialize(&self) -> Vec { - let mut registration_upload: Vec = 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 = 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 { +pub struct CredentialRequest { /// blinded password information pub(crate) alpha: CS::Group, pub(crate) ke1_message: >::KE1Message, } -impl TryFrom<&[u8]> for LoginFirstMessage { +impl TryFrom<&[u8]> for CredentialRequest { type Error = ProtocolError; fn try_from(first_message_bytes: &[u8]) -> Result { Self::deserialize(first_message_bytes) } } -impl LoginFirstMessage { +impl CredentialRequest { /// byte representation for the login request pub(crate) fn to_bytes(&self) -> Vec { [&self.alpha.to_arr()[..], &self.ke1_message.to_bytes()].concat() @@ -305,8 +305,8 @@ impl LoginFirstMessage { } /// The answer sent by the server to the user, upon reception of the -/// login attempt. -pub struct LoginSecondMessage { +/// login attempt +pub struct CredentialResponse { /// the server's oprf output pub(crate) beta: CS::Group, /// the user's sealed information, @@ -314,7 +314,7 @@ pub struct LoginSecondMessage { pub(crate) ke2_message: >::KE2Message, } -impl LoginSecondMessage { +impl CredentialResponse { /// Serialization into bytes pub fn serialize(&self) -> Vec { let mut credential_response: Vec = Vec::new(); @@ -332,7 +332,7 @@ impl LoginSecondMessage { } } -impl TryFrom<&[u8]> for LoginSecondMessage { +impl TryFrom<&[u8]> for CredentialResponse { type Error = ProtocolError; fn try_from(second_message_bytes: &[u8]) -> Result { let elem_len = ::ElemLen::to_usize(); @@ -365,11 +365,11 @@ impl TryFrom<&[u8]> for LoginSecondMessage { /// The answer sent by the client to the server, upon reception of the /// sealed envelope -pub struct LoginThirdMessage { +pub struct CredentialFinalization { pub(crate) ke3_message: >::KE3Message, } -impl TryFrom<&[u8]> for LoginThirdMessage { +impl TryFrom<&[u8]> for CredentialFinalization { type Error = ProtocolError; fn try_from(bytes: &[u8]) -> Result { @@ -379,7 +379,7 @@ impl TryFrom<&[u8]> for LoginThirdMessage { } } -impl LoginThirdMessage { +impl CredentialFinalization { /// Serialization into bytes pub fn serialize(&self) -> Vec { self.ke3_message.to_bytes() diff --git a/src/opaque.rs b/src/opaque.rs index 4a89edf..dd932f7 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -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 { + /// The registration request message to be sent to the server + pub message: RegistrationRequest, + /// The client state that must be persisted in order to complete registration + pub state: ClientRegistration, +} + impl ClientRegistration { /// Returns an initial "blinded" request to send to the server, as well as a ClientRegistration /// @@ -124,15 +132,15 @@ impl ClientRegistration { /// type SlowHash = opaque_ke::slow_hash::NoOpHash; /// } /// let mut client_rng = OsRng; - /// let (register_m1, registration_state) = ClientRegistration::::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?; + /// let client_registration_start_result = ClientRegistration::::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn start( + blinding_factor_rng: &mut R, password: &[u8], params: ClientRegistrationStartParameters, - blinding_factor_rng: &mut R, #[cfg(test)] postprocess: fn(::Scalar) -> ::Scalar, - ) -> Result<(RegisterFirstMessage, Self), ProtocolError> { + ) -> Result, ProtocolError> { let (id_u, id_s) = match params { ClientRegistrationStartParameters::WithIdentifiers(id_u, id_s) => (id_u, id_s), }; @@ -144,17 +152,20 @@ impl ClientRegistration { postprocess, )?; - Ok(( - RegisterFirstMessage:: { alpha }, - Self { id_u, id_s, token }, - )) + Ok(ClientRegistrationStartResult { + message: RegistrationRequest:: { alpha }, + state: Self { id_u, id_s, token }, + }) } } -type ClientRegistrationFinishResult = ( - RegisterThirdMessage, - GenericArray, -); +/// Contains the fields that are returned by a client registration finish +pub struct ClientRegistrationFinishResult { + /// The registration upload message to be sent to the server + pub message: RegistrationUpload, + /// The export key output by client registration + pub export_key: GenericArray, +} impl ClientRegistration { /// "Unblinds" the server's answer and returns a final message containing @@ -182,17 +193,17 @@ impl ClientRegistration { /// 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::::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?; - /// let (register_m2, server_state) = - /// ServerRegistration::::start(register_m1, server_kp.public(), &mut server_rng)?; + /// let client_registration_start_result = ClientRegistration::::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?; + /// let server_registration_start_result = + /// ServerRegistration::::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( self, - r2: RegisterSecondMessage, rng: &mut R, + r2: RegistrationResponse, ) -> Result, ProtocolError> { let client_static_keypair = CS::KeyFormat::generate_random(rng)?; @@ -215,13 +226,13 @@ impl ClientRegistration { let (envelope, export_key) = Envelope::::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 Drop for ClientLogin { } } +/// Contains the fields that are returned by a server registration start +pub struct ServerRegistrationStartResult { + /// The registration resposne message to send to the client + pub message: RegistrationResponse, + /// The state that the server must keep in order to complete registration + pub state: ServerRegistration, +} + /// The state elements the server holds to record a registration pub struct ServerRegistration { envelope: Option>, @@ -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::::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?; - /// let (register_m2, server_state) = - /// ServerRegistration::::start(register_m1, server_kp.public(), &mut server_rng)?; + /// let client_registration_start_result = ClientRegistration::::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?; + /// let server_registration_start_result = + /// ServerRegistration::::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn start( - message: RegisterFirstMessage, - server_s_pk: &::Repr, rng: &mut R, - ) -> Result<(RegisterSecondMessage, Self), ProtocolError> { + message: RegistrationRequest, + server_s_pk: &::Repr, + ) -> Result, 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::(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::::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?; - /// let (register_m2, server_state) = - /// ServerRegistration::::start(register_m1, server_kp.public(), &mut server_rng)?; + /// let client_registration_start_result = ClientRegistration::::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?; + /// let server_registration_start_result = + /// ServerRegistration::::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, + message: RegistrationUpload, ) -> Result { 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 { /// The message to send to the server to begin the login protocol - pub credential_request: LoginFirstMessage, + pub message: CredentialRequest, /// The state that the client must keep in order to complete the protocol - pub client_login_state: ClientLogin, + pub state: ClientLogin, } /// 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 { - /// The plaintext info sent by the client - pub plain_info: Vec, - /// The message to send back to the client - pub confidential_info: Vec, /// The message to send to the server to complete the protocol - pub key_exchange: LoginThirdMessage, + pub message: CredentialFinalization, /// The shared session secret - pub session_secret: Vec, + pub shared_secret: Vec, /// The client-side export key pub export_key: GenericArray, /// The server's static public key pub server_s_pk: Vec, - /// An optional id_s if suppleid by the server + /// An optional id_s if supplied by the server pub id_s: Option>, + /// The plaintext info sent by the client + pub plain_info: Vec, + /// The confidential info sent by the client + pub confidential_info: Vec, } impl ClientLogin { @@ -568,12 +587,12 @@ impl ClientLogin { /// type SlowHash = opaque_ke::slow_hash::NoOpHash; /// } /// let mut client_rng = OsRng; - /// let client_login_start_result = ClientLogin::::start(b"hunter2", &mut client_rng, ClientLoginStartParameters::default())?; + /// let client_login_start_result = ClientLogin::::start(&mut client_rng, b"hunter2", ClientLoginStartParameters::default())?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn start( - password: &[u8], rng: &mut R, + password: &[u8], params: ClientLoginStartParameters, #[cfg(test)] postprocess: fn(::Scalar) -> ::Scalar, ) -> Result, ProtocolError> { @@ -594,11 +613,11 @@ impl ClientLogin { 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 ClientLogin { /// } /// let mut client_rng = OsRng; /// # let mut server_rng = OsRng; - /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?; + /// # let client_registration_start_result = ClientRegistration::::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?; /// # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// # let (register_m2, server_state) = ServerRegistration::::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::::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::::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::::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, + l2: CredentialResponse, params: ClientLoginFinishParameters, ) -> Result, ProtocolError> { let (info, e_info) = match params { @@ -683,7 +702,7 @@ impl ClientLogin { 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 ClientLogin { 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 { - /// The plaintext info sent by the client - pub plain_info: Vec, /// The message to send back to the client - pub credential_response: LoginSecondMessage, + pub message: CredentialResponse, /// The state that the server must keep in order to finish the protocl - pub server_login_state: ServerLogin, + pub state: ServerLogin, /// The client's static public key pub client_s_pk: Vec, + /// The plaintext info sent by the client + pub plain_info: Vec, } /// 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, /// The plaintext info sent by the client pub plain_info: Vec, /// The confidential info sent by the client pub confidential_info: Vec, - /// The shared session secret between client and server - pub session_secret: Vec, } +impl ServerLoginFinishResult {} + impl ServerLogin { /// byte representation for the server's login state pub fn to_bytes(&self) -> Vec { @@ -796,20 +817,20 @@ impl ServerLogin { /// 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::::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?; - /// # let (register_m2, server_state) = - /// ServerRegistration::::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::::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::::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?; + /// # let server_registration_start_result = + /// ServerRegistration::::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::::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( + rng: &mut R, password_file: ServerRegistration, server_s_sk: &::Repr, - l1: LoginFirstMessage, - rng: &mut R, + l1: CredentialRequest, params: ServerLoginStartParameters, ) -> Result, ProtocolError> { let client_s_pk = password_file @@ -853,7 +874,7 @@ impl ServerLogin { e_info, )?; - let l2 = LoginSecondMessage { + let l2 = CredentialResponse { beta, envelope, ke2_message, @@ -861,8 +882,8 @@ impl ServerLogin { Ok(ServerLoginStartResult { plain_info, - credential_response: l2, - server_login_state: Self { + message: l2, + state: Self { _cs: PhantomData, ke2_state, }, @@ -896,22 +917,22 @@ impl ServerLogin { /// 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::::start(b"hunter2", ClientRegistrationStartParameters::default(), &mut client_rng)?; - /// # let (register_m2, server_state) = - /// ServerRegistration::::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::::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::::start(&mut client_rng, b"hunter2", ClientRegistrationStartParameters::default())?; + /// # let server_registration_start_result = + /// ServerRegistration::::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::::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, + message: CredentialFinalization, ) -> Result { - let (plain_info, confidential_info, session_secret) = + let (plain_info, confidential_info, shared_secret) = >::finish_ke( message.ke3_message, &self.ke2_state, @@ -926,7 +947,7 @@ impl ServerLogin { Ok(ServerLoginFinishResult { plain_info, confidential_info, - session_secret, + shared_secret, }) } } diff --git a/src/serialization/tests.rs b/src/serialization/tests.rs index fd6e0e1..1bd5ef1 100644 --- a/src/serialization/tests.rs +++ b/src/serialization/tests.rs @@ -121,7 +121,7 @@ fn register_first_message_roundtrip() { input.extend_from_slice(&alpha_length.to_be_bytes()[std::mem::size_of::() - 2..]); input.extend_from_slice(pt_bytes.as_slice()); - let r1 = RegisterFirstMessage::::deserialize(input.as_slice()).unwrap(); + let r1 = RegistrationRequest::::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::::deserialize(input.as_slice()).unwrap(); + let r2 = RegistrationResponse::::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::() - 2..]); input.extend_from_slice(&pubkey_bytes[..]); - let r3 = RegisterThirdMessage::::deserialize(&input[..]).unwrap(); + let r3 = RegistrationUpload::::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::::deserialize(input.as_slice()).unwrap(); + let l1 = CredentialRequest::::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::::deserialize(&input).unwrap(); + let l2 = CredentialResponse::::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::::deserialize(&input).unwrap(); + let l3 = CredentialFinalization::::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::(), 0..std::mem::size_of::())) #[test] fn test_nocrash_register_first_message(bytes in vec(any::(), 0..200)) { - RegisterFirstMessage::::try_from(&bytes[..]).map_or(true, |_| true); + RegistrationRequest::::try_from(&bytes[..]).map_or(true, |_| true); } #[test] fn test_nocrash_register_second_message(bytes in vec(any::(), 0..200)) { - RegisterSecondMessage::::try_from(&bytes[..]).map_or(true, |_| true); + RegistrationResponse::::try_from(&bytes[..]).map_or(true, |_| true); } #[test] fn test_nocrash_register_third_message(bytes in vec(any::(), 0..200)) { - RegisterThirdMessage::::try_from(&bytes[..]).map_or(true, |_| true); + RegistrationUpload::::try_from(&bytes[..]).map_or(true, |_| true); } #[test] fn test_nocrash_login_first_message(bytes in vec(any::(), 0..500)) { - LoginFirstMessage::::try_from(&bytes[..]).map_or(true, |_| true); + CredentialRequest::::try_from(&bytes[..]).map_or(true, |_| true); } #[test] fn test_nocrash_login_second_message(bytes in vec(any::(), 0..500)) { - LoginSecondMessage::::try_from(&bytes[..]).map_or(true, |_| true); + CredentialResponse::::try_from(&bytes[..]).map_or(true, |_| true); } #[test] fn test_nocrash_login_third_message(bytes in vec(any::(), 0..500)) { - LoginThirdMessage::::try_from(&bytes[..]).map_or(true, |_| true); + CredentialFinalization::::try_from(&bytes[..]).map_or(true, |_| true); } #[test] diff --git a/src/tests/opaque_ke_test.rs b/src/tests/opaque_ke_test.rs index 19bf305..9c04eef 100644 --- a/src/tests/opaque_ke_test.rs +++ b/src/tests/opaque_ke_test.rs @@ -55,12 +55,12 @@ pub struct TestVectorParameters { pub einfo2: Vec, pub info3: Vec, pub einfo3: Vec, - pub r1: Vec, - pub r2: Vec, - pub r3: Vec, - pub l1: Vec, - pub l2: Vec, - pub l3: Vec, + pub registration_request: Vec, + pub registration_response: Vec, + pub message: Vec, + pub credential_request: Vec, + pub credential_response: Vec, + pub key_exchange: Vec, client_registration_state: Vec, server_registration_state: Vec, client_login_state: Vec, @@ -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::::start( + let client_registration_start_result = ClientRegistration::::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::::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::::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 = 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 = Vec::new(); @@ -316,8 +361,8 @@ where let mut client_login_start_rng = CycleRng::new(client_login_start); let client_login_start_result = ClientLogin::::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::::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::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::::start( + let client_registration_start_result = ClientRegistration::::start( + &mut rng, ¶meters.password, ClientRegistrationStartParameters::WithIdentifiers(parameters.id_u, parameters.id_s), - &mut rng, postprocess_blinding_factor::<::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::::start( - RegisterFirstMessage::deserialize(¶meters.r1[..]).unwrap(), - &Key::try_from(¶meters.server_s_pk[..]).unwrap(), + let server_registration_start_result = ServerRegistration::::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 = [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::::try_from( + let result = ClientRegistration::::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::::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::<::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::::start( + &mut server_e_sk_rng, ServerRegistration::try_from(¶meters.password_file[..]).unwrap(), &Key::try_from(¶meters.server_s_sk[..]).unwrap(), - LoginFirstMessage::::deserialize(¶meters.l1[..]).unwrap(), - &mut server_e_sk_rng, + CredentialRequest::::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::::try_from(¶meters.client_login_state[..])?.finish( - LoginSecondMessage::::deserialize(¶meters.l2[..]).unwrap(), - ClientLoginFinishParameters::WithInfo( - parameters.info3.to_vec(), - parameters.einfo3.to_vec(), - ), - )?; + ClientLogin::::try_from(¶meters.client_login_state[..]) + .unwrap() + .finish( + CredentialResponse::::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::::try_from(¶meters.server_login_state[..])? - .finish(LoginThirdMessage::try_from(¶meters.l3[..])?)?; + ServerLogin::::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::::start( + let client_registration_start_result = ClientRegistration::::start( + &mut client_rng, registration_password, ClientRegistrationStartParameters::default(), - &mut client_rng, std::convert::identity, )?; - let (register_m2, server_state) = ServerRegistration::::start( - register_m1, - server_kp.public(), + let server_registration_start_result = ServerRegistration::::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::::start( - login_password, &mut client_rng, + login_password, ClientLoginStartParameters::default(), std::convert::identity, )?; let server_login_start_result = ServerLogin::::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 {