SIGMA-I Key Exchange (#378)

* Move `KeGroup` to `KeyExchange::Group`

- Introduce `KeyExchange::Hash`, which separates the OPRF hash from the one used in `KeyExchange`.
- Remove `De/Serialize` requirement on key exchange messages and states, which forced a lot of where bounds on downstream users.
- Rename `KeGroup` to `Group`.
- Replace `D` generic for hash with `H`.

* Use `voprf::derive_key()` directly

* Implement SIGMA-I key exchange

* Improve `KeyExchange` for SIGMA-I and Ed25519

* Implement EdDSA

* Un-qualify some method calls

* SIGMA-I: only include client identity in client mac

* SIGMA-I: include server mac in client signature

* Expose key exchange types in `crate` & move modules

* Implement Ed25519ph

* Document `ed25519` crate feature

* Remove `ristretto255-voprf` crate feature

* Adjust CI crate feature testing

* Fix Rustdoc

* Remove unnecessary generic parameters from SIGMA-I

* Properly mark to-do's with TODO

* Assorted fixes

* SIGMA-I: include context in signature

* SIGMA-I: include identifiers in signature

* Merge `ServerLoginStart/FinishParameters`

* Re-export more necessary types

* More carefully expose types

* Add ECDSA test

* SIGMA-I: share context hashing

* De-duplicate client static public key storage

* Hide `KeyExchange` better

* Use the correct hash in the root documentation

* Bump `derive-where`

* Format documentation examples a bit further

* Add remote OPRF seed documentation

* Rename `deserialize_key_pair` to `deserialize_take_key_pair`

* Add more key tests

* Remove `SharedSecret` trait

* SIGMA-I refactor message API

* Share more implementation between 3DH and SIGMA-I

* Remove unnecessary zero scalar check for Curve25519

* Use correct hash in test

* Add some more TODOs

* Exclude `tests` folder from Cargo publishing

* Enable missing dependencies

* Use right crate for testing Ed25519

* Remove unnecessary `Sized` constraints

* Remove unnecessary `ecdsa` crate features

* Move signature de/serialization to trait methods

* Nit: move import to appropriate location

* Add warning to SIGMA-I
This commit is contained in:
daxpedda
2025-05-19 13:56:25 -07:00
committed by GitHub
parent 58b4d746c0
commit bebd2c605b
37 changed files with 9402 additions and 3375 deletions
+301 -120
View File
@@ -32,11 +32,12 @@
//! We will use the following choices in this example:
//! ```ignore
//! use opaque_ke::CipherSuite;
//!
//! struct Default;
//!
//! impl CipherSuite for Default {
//! type OprfCs = opaque_ke::Ristretto255;
//! type KeGroup = opaque_ke::Ristretto255;
//! type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! type Ksf = opaque_ke::ksf::Identity;
//! }
//! ```
@@ -60,19 +61,18 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! use rand::rngs::OsRng;
//! use rand::RngCore;
//!
//! let mut rng = OsRng;
//! let server_setup = ServerSetup::<Default>::new(&mut rng);
//! # Ok::<(), ProtocolError>(())
@@ -117,20 +117,19 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! use opaque_ke::ClientRegistration;
//! use rand::rngs::OsRng;
//! use rand::RngCore;
//!
//! let mut client_rng = OsRng;
//! let client_registration_start_result =
//! ClientRegistration::<Default>::start(&mut client_rng, b"password")?;
@@ -156,15 +155,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -174,6 +171,7 @@
//! # b"password",
//! # )?;
//! use opaque_ke::ServerRegistration;
//!
//! # let mut server_rng = OsRng;
//! # let server_setup = ServerSetup::<Default>::new(&mut server_rng);
//! let server_registration_start_result = ServerRegistration::<Default>::start(
@@ -196,7 +194,7 @@
//! ```
//! # use opaque_ke::{
//! # errors::ProtocolError,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ServerSetup,
//! # ClientRegistration, ServerRegistration, ServerSetup,
//! # ksf::Identity,
//! # };
//! # use opaque_ke::CipherSuite;
@@ -204,15 +202,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -224,6 +220,8 @@
//! # let mut server_rng = OsRng;
//! # let server_setup = ServerSetup::<Default>::new(&mut server_rng);
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&server_setup, client_registration_start_result.message, b"[email protected]")?;
//! use opaque_ke::ClientRegistrationFinishParameters;
//!
//! let client_registration_finish_result = client_registration_start_result.state.finish(
//! &mut client_rng,
//! b"password",
@@ -252,15 +250,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -305,19 +301,18 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
//! use opaque_ke::ClientLogin;
//!
//! let mut client_rng = OsRng;
//! let client_login_start_result = ClientLogin::<Default>::start(&mut client_rng, b"password")?;
//! # Ok::<(), ProtocolError>(())
@@ -342,15 +337,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -368,7 +361,8 @@
//! # &mut client_rng,
//! # b"password",
//! # )?;
//! use opaque_ke::{ServerLogin, ServerLoginStartParameters};
//! use opaque_ke::{ServerLogin, ServerLoginParameters};
//!
//! let password_file = ServerRegistration::<Default>::deserialize(&password_file_bytes)?;
//! let mut server_rng = OsRng;
//! let server_login_start_result = ServerLogin::start(
@@ -377,7 +371,7 @@
//! Some(password_file),
//! client_login_start_result.message,
//! b"[email protected]",
//! ServerLoginStartParameters::default(),
//! ServerLoginParameters::default(),
//! )?;
//! # Ok::<(), ProtocolError>(())
//! ```
@@ -405,7 +399,7 @@
//! ```
//! # use opaque_ke::{
//! # errors::ProtocolError,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ServerLogin, ServerLoginParameters, CredentialFinalization, ServerSetup,
//! # ksf::Identity,
//! # };
//! # use opaque_ke::CipherSuite;
@@ -413,15 +407,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -444,8 +436,11 @@
//! # &password_file_bytes,
//! # )?;
//! # let server_login_start_result =
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginStartParameters::default())?;
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginParameters::default())?;
//! use opaque_ke::ClientLoginFinishParameters;
//!
//! let client_login_finish_result = client_login_start_result.state.finish(
//! &mut client_rng,
//! b"password",
//! server_login_start_result.message,
//! ClientLoginFinishParameters::default(),
@@ -461,7 +456,7 @@
//! ```
//! # use opaque_ke::{
//! # errors::ProtocolError,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginParameters, CredentialFinalization, ServerSetup,
//! # ksf::Identity,
//! # };
//! # use opaque_ke::CipherSuite;
@@ -469,15 +464,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -500,14 +493,16 @@
//! # &password_file_bytes,
//! # )?;
//! # let server_login_start_result =
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginStartParameters::default())?;
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginParameters::default())?;
//! # let client_login_finish_result = client_login_start_result.state.finish(
//! # &mut client_rng,
//! # b"password",
//! # server_login_start_result.message,
//! # ClientLoginFinishParameters::default(),
//! # )?;
//! let server_login_finish_result = server_login_start_result.state.finish(
//! client_login_finish_result.message,
//! ServerLoginParameters::default(),
//! )?;
//!
//! assert_eq!(
@@ -558,7 +553,7 @@
//! ```
//! # use opaque_ke::{
//! # errors::ProtocolError,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginParameters, CredentialFinalization, ServerSetup,
//! # ksf::Identity,
//! # };
//! # use opaque_ke::CipherSuite;
@@ -566,15 +561,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -604,10 +597,11 @@
//! # &password_file_bytes,
//! # )?;
//! # let server_login_start_result =
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginStartParameters::default())?;
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginParameters::default())?;
//!
//! // And then later, during login...
//! let client_login_finish_result = client_login_start_result.state.finish(
//! &mut client_rng,
//! b"password",
//! server_login_start_result.message,
//! ClientLoginFinishParameters::default(),
@@ -656,7 +650,7 @@
//! ```
//! # use opaque_ke::{
//! # errors::ProtocolError,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginParameters, CredentialFinalization, ServerSetup,
//! # ksf::Identity,
//! # };
//! # use opaque_ke::CipherSuite;
@@ -664,15 +658,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -701,10 +693,11 @@
//! # &password_file_bytes,
//! # )?;
//! # let server_login_start_result =
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginStartParameters::default())?;
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginParameters::default())?;
//!
//! // And then later, during login...
//! let client_login_finish_result = client_login_start_result.state.finish(
//! &mut client_rng,
//! b"password",
//! server_login_start_result.message,
//! ClientLoginFinishParameters::default(),
@@ -745,15 +738,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -780,8 +771,8 @@
//! # Ok::<(), ProtocolError>(())
//! ```
//!
//! The same identifiers must also be supplied using
//! [`ServerLoginStartParameters`] in [Server Login Start](#server-login-start):
//! The same identifiers must also be supplied using [`ServerLoginParameters`]
//! in [Server Login Start](#server-login-start):
//! ```
//! # use opaque_ke::{
//! # errors::ProtocolError,
@@ -793,15 +784,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -819,7 +808,7 @@
//! # &mut client_rng,
//! # b"password",
//! # )?;
//! # use opaque_ke::{ServerLogin, ServerLoginStartParameters};
//! # use opaque_ke::{ServerLogin, ServerLoginParameters};
//! # let password_file = ServerRegistration::<Default>::deserialize(&password_file_bytes)?;
//! # let mut server_rng = OsRng;
//! let server_login_start_result = ServerLogin::start(
@@ -828,7 +817,7 @@
//! Some(password_file),
//! client_login_start_result.message,
//! b"[email protected]",
//! ServerLoginStartParameters {
//! ServerLoginParameters {
//! context: None,
//! identifiers: Identifiers {
//! client: Some(b"Alice_the_Cryptographer"),
@@ -844,7 +833,7 @@
//! ```
//! # use opaque_ke::{
//! # errors::ProtocolError,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, Identifiers, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, Identifiers, ServerLogin, ServerLoginParameters, CredentialFinalization, ServerSetup,
//! # ksf::Identity,
//! # };
//! # use opaque_ke::CipherSuite;
@@ -852,15 +841,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
@@ -883,8 +870,9 @@
//! # &password_file_bytes,
//! # )?;
//! # let server_login_start_result =
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginStartParameters { context: None, identifiers: Identifiers { client: Some(b"Alice_the_Cryptographer"), server: Some(b"Facebook") } })?;
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginParameters { context: None, identifiers: Identifiers { client: Some(b"Alice_the_Cryptographer"), server: Some(b"Facebook") } })?;
//! let client_login_finish_result = client_login_start_result.state.finish(
//! &mut client_rng,
//! b"password",
//! server_login_start_result.message,
//! ClientLoginFinishParameters::new(
@@ -899,6 +887,62 @@
//!
//! # Ok::<(), ProtocolError>(())
//! ```
//! and in [`ServerLoginParameters`] in [Server Login
//! Finish](#server-login-finish):
//! ```
//! # use opaque_ke::{
//! # errors::ProtocolError,
//! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, Identifiers, ServerLogin, ServerLoginParameters, CredentialFinalization, ServerSetup,
//! # ksf::Identity,
//! # };
//! # use opaque_ke::CipherSuite;
//! # struct Default;
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # use rand::{rngs::OsRng, RngCore};
//! # let mut client_rng = OsRng;
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
//! # &mut client_rng,
//! # b"password",
//! # )?;
//! # let mut server_rng = OsRng;
//! # let server_setup = ServerSetup::<Default>::new(&mut server_rng);
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&server_setup, client_registration_start_result.message, b"[email protected]")?;
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, b"password", server_registration_start_result.message, ClientRegistrationFinishParameters::new(Identifiers { client: Some(b"Alice_the_Cryptographer"), server: Some(b"Facebook") }, None))?;
//! # let password_file_bytes = ServerRegistration::<Default>::finish(client_registration_finish_result.message).serialize();
//! # let client_login_start_result = ClientLogin::<Default>::start(
//! # &mut client_rng,
//! # b"password",
//! # )?;
//! # let password_file =
//! # ServerRegistration::<Default>::deserialize(
//! # &password_file_bytes,
//! # )?;
//! # let server_login_start_result =
//! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"[email protected]", ServerLoginParameters { context: None, identifiers: Identifiers { client: Some(b"Alice_the_Cryptographer"), server: Some(b"Facebook") } })?;
//! # let client_login_finish_result = client_login_start_result.state.finish(
//! # &mut client_rng,
//! # b"password",
//! # server_login_start_result.message,
//! # ClientLoginFinishParameters::new(None, Identifiers { client: Some(b"Alice_the_Cryptographer"), server: Some(b"Facebook") }, None),
//! # )?;
//! let server_login_finish_result = server_login_start_result.state.finish(
//! client_login_finish_result.message,
//! ServerLoginParameters { context: None, identifiers: Identifiers { client: Some(b"Alice_the_Cryptographer"), server: Some(b"Facebook") } },
//! )?;
//!
//! # Ok::<(), ProtocolError>(())
//! ```
//! Failing to supply the same pair of custom identifiers in any of the three
//! steps above will result in an error in attempting to complete the protocol!
//!
@@ -912,16 +956,12 @@
//! complete, so as to bind the integrity of application-specific data or
//! configuration parameters to the security of the key exchange. During the
//! login phase, the client and server can specify this context using:
//! - The second login message, where the server can populate
//! [`ServerLoginStartParameters`], and
//! - The third login message, where the client can populate
//! [`ClientLoginFinishParameters`].
//!
//! For both of these messages, the `WithContextAndIdentifiers` variant can be
//! used to specify these fields in addition to [custom
//! identifiers](#custom-identifiers), with the ordering of the fields as
//! `WithContextAndIdentifiers(context,
//! Identifiers::ClientAndServerIdentifiers(username, server_name))`.
//! - In [Server Login Start](#server-login-start), where the server can
//! populate [`ServerLoginParameters::context`].
//! - In [Client Login Finish](#client-login-finish), where the client can
//! populate [`ClientLoginFinishParameters::context`].
//! - In [Server Login Finish](#server-login-finish), where the server can
//! populate [`ServerLoginParameters::context`].
//!
//! ## Dummy Server Login
//!
@@ -940,59 +980,59 @@
//! exposing the bytes of the private key to this library.
//! ```
//! # use generic_array::{GenericArray, typenum::U0};
//! # use opaque_ke::{CipherSuite, ClientLogin, ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, errors::ProtocolError, keypair::PrivateKey, key_exchange::{group::KeGroup as OKeGroup, tripledh::DiffieHellman}};
//! # use opaque_ke::{CipherSuite, ClientLogin, ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, keypair::{PrivateKey, PublicKey}, key_exchange::{KeyExchange, group::Group, tripledh::DiffieHellman}};
//! # use rand::rngs::OsRng;
//! # type Ristretto255 = <<Default as CipherSuite>::KeyExchange as KeyExchange>::Group;
//! # struct Default;
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # type KeGroup = <Default as CipherSuite>::KeGroup;
//! # #[derive(Debug, thiserror::Error)]
//! # #[error("test error")]
//! # struct YourRemoteKeyError;
//! # #[derive(Clone)]
//! # struct YourRemoteKey(<KeGroup as OKeGroup>::Sk);
//! # struct YourRemoteKey(<Ristretto255 as Group>::Sk);
//! # impl YourRemoteKey {
//! # fn diffie_hellman(&self, pk: &PublicKey<KeGroup>) -> Result<GenericArray<u8, <KeGroup as OKeGroup>::PkLen>, YourRemoteKeyError> {
//! # Ok(<<KeGroup as OKeGroup>::Sk as DiffieHellman<KeGroup>>::diffie_hellman(self.0, KeGroup::deserialize_pk(&pk.serialize()).unwrap()))
//! # fn diffie_hellman(&self, pk: &PublicKey<Ristretto255>) -> Result<GenericArray<u8, <Ristretto255 as Group>::PkLen>, YourRemoteKeyError> {
//! # Ok(<<Ristretto255 as Group>::Sk as DiffieHellman<Ristretto255>>::diffie_hellman(self.0, pk.to_group_type()))
//! # }
//! # }
//! use opaque_ke::{ServerLogin, ServerLoginStartParameters, ServerSetup};
//! use opaque_ke::keypair::{KeyPair, PrivateKeySerialization, PublicKey};
//! use opaque_ke::{ServerLogin, ServerLoginParameters, ServerSetup};
//! use opaque_ke::keypair::{KeyPair, PrivateKeySerialization};
//! use opaque_ke::errors::ProtocolError;
//!
//! // Implement if you intend to use `ServerSetup::de/serialize` instead of `serde`.
//! impl PrivateKeySerialization<KeGroup> for YourRemoteKey {
//! impl PrivateKeySerialization<Ristretto255> for YourRemoteKey {
//! type Error = YourRemoteKeyError;
//! type Len = U0;
//!
//! fn serialize_key_pair(_: &KeyPair<KeGroup, Self>) -> GenericArray<u8, Self::Len> {
//! fn serialize_key_pair(_: &KeyPair<Ristretto255, Self>) -> GenericArray<u8, Self::Len> {
//! unimplemented!()
//! }
//!
//! fn deserialize_key_pair(input: &[u8]) -> Result<KeyPair<KeGroup, Self>, ProtocolError<Self::Error>> {
//! fn deserialize_take_key_pair(input: &mut &[u8]) -> Result<KeyPair<Ristretto255, Self>, ProtocolError<Self::Error>> {
//! unimplemented!()
//! }
//! }
//!
//! # let sk = KeGroup::random_sk(&mut OsRng);
//! # let pk = KeGroup::public_key(sk);
//! # let pk = KeGroup::serialize_pk(pk);
//! # let sk = Ristretto255::random_sk(&mut OsRng);
//! # let pk = Ristretto255::public_key(sk);
//! # let pk = Ristretto255::serialize_pk(pk);
//! # let public_key = PublicKey::deserialize(&pk).unwrap();
//! # let remote_key = YourRemoteKey(sk);
//! # let mut server_rng = OsRng;
//! let keypair = KeyPair::new(remote_key, public_key);
//! let server_setup = ServerSetup::<Default, YourRemoteKey>::new_with_key_pair(&mut server_rng, keypair);
//!
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
//! # &mut OsRng,
//! # b"password",
@@ -1004,17 +1044,152 @@
//! # &mut OsRng,
//! # b"password",
//! # )?;
//! let password_file = ServerRegistration::<Default>::deserialize(&password_file_bytes)?;
//! # let password_file = ServerRegistration::<Default>::deserialize(&password_file_bytes)?;
//! // Use `ServerLogin::builder()` instead of `ServerLogin::start()`.
//! let server_login_builder = ServerLogin::builder(
//! &mut server_rng,
//! &server_setup,
//! Some(password_file),
//! client_login_start_result.message,
//! b"[email protected]",
//! ServerLoginStartParameters::default(),
//! ServerLoginParameters::default(),
//! )?;
//!
//! // Run Diffie-Hellman on your remote key.
//! let client_e_public_key = server_login_builder.data();
//! let shared_secret = server_login_builder.private_key().diffie_hellman(&client_e_public_key)?;
//!
//! // Use the shared secret to build `ServerLogin`.
//! let server_login_start_result = server_login_builder.build(shared_secret)?;
//! # Ok::<(), anyhow::Error>(())
//! ```
//!
//! ## Remote OPRF Seeds
//!
//! In addition, the OPRF seed can be stored in an external location as well, by
//! using [`ServerRegistration::start_with_key_material()`] and
//! [`ServerLogin::builder_with_key_material()`] in combination with
//! [`ServerSetup::key_material_info()`].
//! ```
//! # use digest::Output;
//! # use generic_array::{GenericArray, typenum::U0};
//! # use hkdf::Hkdf;
//! # use opaque_ke::{CipherSuite, ClientLogin, ClientRegistration, ClientRegistrationFinishParameters, keypair::{PrivateKey, PublicKey}, key_exchange::{KeyExchange, group::Group, tripledh::DiffieHellman}};
//! # use rand::rngs::OsRng;
//! # use rand::RngCore;
//! # type Ristretto255 = <<Default as CipherSuite>::KeyExchange as KeyExchange>::Group;
//! # type Hash = <<Default as CipherSuite>::KeyExchange as KeyExchange>::Hash;
//! # type OprfGroup = <<Default as CipherSuite>::OprfCs as voprf::CipherSuite>::Group;
//! # struct Default;
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for Default {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for Default {
//! # type OprfCs = p256::NistP256;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = opaque_ke::ksf::Identity;
//! # }
//! # #[derive(Debug, thiserror::Error)]
//! # #[error("test error")]
//! # struct YourRemoteSecretsError;
//! # #[derive(Clone)]
//! # struct YourRemoteSeed(Output<Hash>);
//! # impl YourRemoteSeed {
//! # fn hkdf(&self, info: &[&[u8]]) -> GenericArray<u8, <OprfGroup as voprf::Group>::ScalarLen> {
//! # let mut ikm = GenericArray::default();
//! # Hkdf::<Hash>::from_prk(&self.0)
//! # .unwrap()
//! # .expand_multi_info(info, &mut ikm)
//! # .unwrap();
//! # ikm
//! # }
//! # }
//! # #[derive(Clone)]
//! # struct YourRemoteKey(<Ristretto255 as Group>::Sk);
//! # impl YourRemoteKey {
//! # fn diffie_hellman(&self, pk: &PublicKey<Ristretto255>) -> Result<GenericArray<u8, <Ristretto255 as Group>::PkLen>, YourRemoteSecretsError> {
//! # Ok(<<Ristretto255 as Group>::Sk as DiffieHellman<Ristretto255>>::diffie_hellman(self.0, pk.to_group_type()))
//! # }
//! # }
//! use opaque_ke::{ServerLogin, ServerLoginParameters, ServerRegistration, ServerSetup};
//! use opaque_ke::keypair::{KeyPair, OprfSeedSerialization};
//! use opaque_ke::errors::ProtocolError;
//!
//! // Implement if you intend to use `ServerSetup::de/serialize` instead of `serde`.
//! impl OprfSeedSerialization<sha2::Sha512, YourRemoteSecretsError> for YourRemoteSeed {
//! type Len = U0;
//!
//! fn serialize(&self) -> GenericArray<u8, Self::Len> {
//! unimplemented!()
//! }
//!
//! fn deserialize_take(input: &mut &[u8]) -> Result<YourRemoteSeed, ProtocolError<YourRemoteSecretsError>> {
//! unimplemented!()
//! }
//! }
//!
//! # let mut oprf_seed = YourRemoteSeed(GenericArray::default());
//! # OsRng.fill_bytes(&mut oprf_seed.0);
//! # let sk = Ristretto255::random_sk(&mut OsRng);
//! # let pk = Ristretto255::public_key(sk);
//! # let pk = Ristretto255::serialize_pk(pk);
//! # let public_key = PublicKey::deserialize(&pk).unwrap();
//! # let remote_key = YourRemoteKey(sk);
//! # let mut server_rng = OsRng;
//! let keypair = KeyPair::new(remote_key, public_key);
//! let server_setup = ServerSetup::<Default, YourRemoteKey, YourRemoteSeed>::new_with_key_pair_and_seed(&mut server_rng, keypair, oprf_seed);
//!
//! // Incoming registration ...
//! # let client_registration_start_result = ClientRegistration::<Default>::start(
//! # &mut OsRng,
//! # b"password",
//! # )?;
//!
//! // Run HKDF on your remote OPRF seed.
//! let info = server_setup.key_material_info(b"[email protected]");
//! let key_material = info.ikm.hkdf(&info.info);
//!
//! // Use `ServerRegistration::start_with_key_material()` instead of `ServerRegistration::start()`.
//! let server_registration_start_result = ServerRegistration::<Default>::start_with_key_material(
//! &server_setup,
//! key_material,
//! client_registration_start_result.message,
//! )?;
//!
//! // Finish registration ...
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut OsRng, b"password", server_registration_start_result.message, ClientRegistrationFinishParameters::default())?;
//!
//! // Incoming login ...
//! # let password_file_bytes = ServerRegistration::<Default>::finish(client_registration_finish_result.message).serialize();
//! # let client_login_start_result = ClientLogin::<Default>::start(
//! # &mut OsRng,
//! # b"password",
//! # )?;
//! # let password_file = ServerRegistration::<Default>::deserialize(&password_file_bytes)?;
//!
//! // Run HKDF on your remote OPRF seed.
//! let info = server_setup.key_material_info(b"[email protected]");
//! let key_material = info.ikm.hkdf(&info.info);
//!
//! // Use `ServerLogin::builder_with_key_material()` instead of `ServerLogin::start()`.
//! let server_login_builder = ServerLogin::builder_with_key_material(
//! &mut server_rng,
//! &server_setup,
//! key_material,
//! Some(password_file),
//! client_login_start_result.message,
//! ServerLoginParameters::default(),
//! )?;
//!
//! // Run Diffie-Hellman on your remote key.
//! let client_e_public_key = server_login_builder.data();
//! let shared_secret = server_login_builder.private_key().diffie_hellman(&client_e_public_key)?;
//!
//! // Use the shared secret to build `ServerLogin`.
//! let server_login_start_result = server_login_builder.build(shared_secret)?;
//! # Ok::<(), anyhow::Error>(())
//! ```
@@ -1028,11 +1203,13 @@
//! can be used.
//! ```
//! # use generic_array::GenericArray;
//! use opaque_ke::ksf::Ksf;
//!
//! #[derive(Default)]
//! struct CustomKsf(scrypt::Params);
//!
//! // The Ksf trait must be implemented to be used in the ciphersuite.
//! impl opaque_ke::ksf::Ksf for CustomKsf {
//! impl Ksf for CustomKsf {
//! fn hash<L: generic_array::ArrayLength<u8>>(
//! &self,
//! input: GenericArray<u8, L>,
@@ -1064,15 +1241,13 @@
//! # #[cfg(feature = "ristretto255")]
//! # impl CipherSuite for DefaultCipherSuite {
//! # type OprfCs = opaque_ke::Ristretto255;
//! # type KeGroup = opaque_ke::Ristretto255;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<opaque_ke::Ristretto255, sha2::Sha512>;
//! # type Ksf = argon2::Argon2<'static>;
//! # }
//! # #[cfg(not(feature = "ristretto255"))]
//! # impl CipherSuite for DefaultCipherSuite {
//! # type OprfCs = p256::NistP256;
//! # type KeGroup = p256::NistP256;
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh;
//! # type KeyExchange = opaque_ke::TripleDh<p256::NistP256, sha2::Sha256>;
//! # type Ksf = argon2::Argon2<'static>;
//! # }
//! #
@@ -1126,7 +1301,7 @@
//! more computationally intensive the `Ksf` function is, the more resistant
//! the server's password file records will be against offline dictionary and precomputation
//! attacks; see [the OPAQUE paper](https://eprint.iacr.org/2018/163.pdf) for
//! more details.
//! more details. The `argon2` feature requires [`alloc`].
//!
//! - The `serde` feature, enabled by default, provides convenience functions for serializing and deserializing with [serde](https://serde.rs/).
//!
@@ -1137,15 +1312,14 @@
//! - The `curve25519` feature enables Curve25519 as a `KeGroup`. To select a
//! specific backend see the [curve25519-dalek] documentation.
//!
//! - The `p256` feature enables the use of [`p256::NistP256`] as a `KeGroup`
//! and a `OprfCs` for `CipherSuite`.
//! - The `ecdsa` feature enables using [`elliptic_curve`]s with [`Ecdsa`] for
//! [`SigmaI`]s signature algorithm.
//!
//! - The `bench` feature is used only for running performance benchmarks for
//! this implementation.
//! - The `ed25519` feature enables using [`Ed25519`]s with [`PureEddsa`] and
//! [`HashEddsa`] for [`SigmaI`]s signature algorithm.
//!
//! [curve25519-dalek]:
//! (https://docs.rs/curve25519-dalek/4.0.0-pre.5/curve25519_dalek/index.html#backends)
//! [`p256::NistP256`]: https://docs.rs/p256/latest/p256/struct.NistP256.html
//! [`alloc`]: https://doc.rust-lang.org/alloc
//! [curve25519-dalek]: https://docs.rs/curve25519-dalek/4/curve25519_dalek/index.html#backends
#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
@@ -1169,7 +1343,6 @@ pub mod ksf;
mod messages;
mod opaque;
mod serialization;
mod util;
#[cfg(test)]
mod tests;
@@ -1181,8 +1354,16 @@ pub use rand;
#[cfg(feature = "curve25519")]
pub use crate::key_exchange::group::curve25519::Curve25519;
#[cfg(feature = "ed25519")]
pub use crate::key_exchange::group::ed25519::Ed25519;
#[cfg(feature = "ristretto255")]
pub use crate::key_exchange::group::ristretto255::Ristretto255;
#[cfg(feature = "ecdsa")]
pub use crate::key_exchange::sigma_i::ecdsa::Ecdsa;
pub use crate::key_exchange::sigma_i::hash_eddsa::HashEddsa;
pub use crate::key_exchange::sigma_i::pure_eddsa::PureEddsa;
pub use crate::key_exchange::sigma_i::SigmaI;
pub use crate::key_exchange::tripledh::TripleDh;
pub use crate::messages::{
CredentialFinalization, CredentialFinalizationLen, CredentialRequest, CredentialRequestLen,
CredentialResponse, CredentialResponseLen, RegistrationRequest, RegistrationRequestLen,
@@ -1193,6 +1374,6 @@ pub use crate::opaque::{
ClientLogin, ClientLoginFinishParameters, ClientLoginFinishResult, ClientLoginStartResult,
ClientRegistration, ClientRegistrationFinishParameters, ClientRegistrationFinishResult,
ClientRegistrationStartResult, Identifiers, KeyMaterialInfo, ServerLogin,
ServerLoginFinishResult, ServerLoginStartParameters, ServerLoginStartResult,
ServerRegistration, ServerRegistrationLen, ServerRegistrationStartResult, ServerSetup,
ServerLoginFinishResult, ServerLoginParameters, ServerLoginStartResult, ServerRegistration,
ServerRegistrationLen, ServerRegistrationStartResult, ServerSetup,
};