Repository: novifinancial/opaque-ke
Pull request #98 (2020-12-08 06:18:30)

Cleaning up docs + README
- README changes, update links to most recent draft cfrg-01
- rename everything from r1/r2/r3 to RFC names
- remove all mentions of pepper, client supplying server_s_pk
- make rng the first argument of every high-level API function
- registration outputs should return tuple types

Omitted all optional parameters from the main documentation for now, but will add a separate section (see issue #97) for describing how to use them once the internet draft settles on these issues


Patch:
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<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(&registration_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(&registration_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
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::<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::{
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<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()
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<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,
         })
     }
 }


Test patch:
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::<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]
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<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,
         &parameters.password,
         ClientRegistrationStartParameters::WithIdentifiers(parameters.id_u, parameters.id_s),
-        &mut rng,
         postprocess_blinding_factor::<<X255193dhNoSlowHash as CipherSuite>::Group>,
     )?;
-    assert_eq!(hex::encode(&parameters.r1), hex::encode(r1.serialize()));
+    assert_eq!(
+        hex::encode(&parameters.registration_request),
+        hex::encode(client_registration_start_result.message.serialize())
+    );
     assert_eq!(
         hex::encode(&parameters.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(&parameters.r1[..]).unwrap(),
-        &Key::try_from(&parameters.server_s_pk[..]).unwrap(),
+    let server_registration_start_result = ServerRegistration::<X255193dhNoSlowHash>::start(
         &mut oprf_key_rng,
+        RegistrationRequest::deserialize(&parameters.registration_request[..]).unwrap(),
+        &Key::try_from(&parameters.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(&parameters.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(
         &parameters.client_registration_state[..],
     )?
     .finish(
-        RegisterSecondMessage::deserialize(&parameters.r2[..]).unwrap(),
         &mut finish_registration_rng,
+        RegistrationResponse::deserialize(&parameters.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> {
         &parameters.server_registration_state[..],
     )?;
     let password_file = server_registration
-        .finish(RegisterThirdMessage::deserialize(&parameters.r3[..]).unwrap())?;
+        .finish(RegistrationUpload::deserialize(&parameters.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(
-        &parameters.password,
         &mut client_login_start_rng,
+        &parameters.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(&parameters.l1),
-        hex::encode(client_login_start_result.credential_request.serialize())
+        hex::encode(&parameters.credential_request),
+        hex::encode(client_login_start_result.message.serialize())
     );
     assert_eq!(
         hex::encode(&parameters.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(&parameters.password_file[..]).unwrap(),
         &Key::try_from(&parameters.server_s_sk[..]).unwrap(),
-        LoginFirstMessage::<X255193dhNoSlowHash>::deserialize(&parameters.l1[..]).unwrap(),
-        &mut server_e_sk_rng,
+        CredentialRequest::<X255193dhNoSlowHash>::deserialize(&parameters.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(&parameters.l2),
-        hex::encode(server_login_start_result.credential_response.serialize())
+        hex::encode(&parameters.credential_response),
+        hex::encode(server_login_start_result.message.serialize())
     );
     assert_eq!(
         hex::encode(&parameters.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(&parameters.client_login_state[..])?.finish(
-            LoginSecondMessage::<X255193dhNoSlowHash>::deserialize(&parameters.l2[..]).unwrap(),
-            ClientLoginFinishParameters::WithInfo(
-                parameters.info3.to_vec(),
-                parameters.einfo3.to_vec(),
-            ),
-        )?;
+        ClientLogin::<X255193dhNoSlowHash>::try_from(&parameters.client_login_state[..])
+            .unwrap()
+            .finish(
+                CredentialResponse::<X255193dhNoSlowHash>::deserialize(
+                    &parameters.credential_response[..],
+                )?,
+                ClientLoginFinishParameters::WithInfo(
+                    parameters.info3.to_vec(),
+                    parameters.einfo3.to_vec(),
+                ),
+            )?;
+
     assert_eq!(
         hex::encode(&parameters.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(&parameters.shared_secret),
-        hex::encode(&client_login_finish_result.session_secret)
+        hex::encode(&client_login_finish_result.shared_secret)
     );
     assert_eq!(
-        hex::encode(&parameters.l3),
-        hex::encode(client_login_finish_result.key_exchange.to_bytes())
+        hex::encode(&parameters.key_exchange),
+        hex::encode(client_login_finish_result.message.to_bytes())
     );
     assert_eq!(
         hex::encode(&parameters.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(&parameters.server_login_state[..])?
-            .finish(LoginThirdMessage::try_from(&parameters.l3[..])?)?;
+        ServerLogin::<X255193dhNoSlowHash>::try_from(&parameters.server_login_state[..])?.finish(
+            CredentialFinalization::try_from(&parameters.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 {