diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0da0f99..4ef4112 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,10 +19,7 @@ jobs: - x25519_u64,ristretto255_u64 toolchain: - stable - - 1.51.0 - exclude: - - backend_feature: p256 - toolchain: 1.51.0 + - 1.56.1 name: test steps: - name: Checkout sources @@ -102,7 +99,7 @@ jobs: matrix: toolchain: - stable - - 1.51.0 + - 1.56.1 name: test simple_login command-line example steps: - name: install expect @@ -125,7 +122,7 @@ jobs: matrix: toolchain: - stable - - 1.51.0 + - 1.56.1 name: test digital_locker command-line example steps: - name: install expect diff --git a/Cargo.toml b/Cargo.toml index b56addc..bd0ac18 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,10 +7,9 @@ categories = ["no-std"] description = "An implementation of the OPAQUE password-authenticated key exchange protocol" authors = ["Kevin Lewi ", "François Garillot "] license = "Apache-2.0 OR MIT" -edition = "2018" +edition = "2021" readme = "README.md" -resolver = "2" -rust-version = "1.51" +rust-version = "1.56" [features] default = ["ristretto255_u64", "serde"] @@ -37,17 +36,17 @@ argon2 = { version = "0.3", default-features = false, features = ["alloc"], opti constant_time_eq = "0.1" curve25519-dalek = { version = "3", default-features = false, optional = true } derive-where = { version = "1.0.0-rc.1", features = ["zeroize"] } -digest = "0.9" +digest = "0.10" displaydoc = { version = "0.2", default-features = false } generic-array = "0.14" getrandom = { version = "0.2", optional = true } -hkdf = "0.11" -hmac = "0.11" -p256_ = { package = "p256", version = "0.9", default-features = false, features = ["arithmetic", "zeroize"], optional = true } +hkdf = "0.12" +hmac = "0.12" +p256_ = { package = "p256", version = "0.10", default-features = false, features = ["arithmetic"], optional = true } rand = { version = "0.8", default-features = false } serde_ = { version = "1", package = "serde", default-features = false, features = ["derive"], optional = true } subtle = { version = "2.3", default-features = false } -voprf = { git = "https://github.com/khonsulabs/voprf", rev = "f8c19eab4ecc9e7a2a5ae26c59661ce797229566", default-features = false, features = ["danger"] } +voprf = { git = "https://github.com/novifinancial/voprf", rev = "55ef981a3f9a12eddd8c372ffdf51818011343ee", default-features = false, features = ["danger"] } x25519-dalek = { version = "1", default-features = false, optional = true } zeroize = { version = "1", features = ["zeroize_derive"] } @@ -62,13 +61,11 @@ criterion = "0.3" hex = "0.4" json = "0.12" lazy_static = "1" -opaque-ke = { path = "", default-features = false, features = ["std"] } serde_json = "1" -sha2 = "0.9" +sha2 = "0.10" proptest = "1" regex = "1" -# Version 9.1 requires an MSRV of 1.56 -rustyline = "~9.0" +rustyline = "9" [[bench]] name = "opaque" diff --git a/README.md b/README.md index 0067653..6793ee6 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ opaque-ke = "0.6.0" ### Minimum Supported Rust Version -Rust **1.51** or higher. +Rust **1.56** or higher. Audit ----- diff --git a/benches/opaque.rs b/benches/opaque.rs index 5009498..200a571 100644 --- a/benches/opaque.rs +++ b/benches/opaque.rs @@ -113,6 +113,7 @@ fn client_registration_finish(c: &mut Criterion) { .state .finish( &mut rng, + password, server_registration_start_result.message.clone(), ClientRegistrationFinishParameters::default(), ) @@ -139,6 +140,7 @@ fn server_registration_finish(c: &mut Criterion) { .state .finish( &mut rng, + password, server_registration_start_result.message, ClientRegistrationFinishParameters::default(), ) @@ -182,6 +184,7 @@ fn server_login_start_real(c: &mut Criterion) { .state .finish( &mut rng, + password, server_registration_start_result.message, ClientRegistrationFinishParameters::default(), ) @@ -249,6 +252,7 @@ fn client_login_finish(c: &mut Criterion) { .state .finish( &mut rng, + password, server_registration_start_result.message, ClientRegistrationFinishParameters::default(), ) @@ -271,6 +275,7 @@ fn client_login_finish(c: &mut Criterion) { .clone() .state .finish( + password, server_login_start.clone().message, ClientLoginFinishParameters::default(), ) @@ -296,6 +301,7 @@ fn server_login_finish(c: &mut Criterion) { .state .finish( &mut rng, + password, server_registration_start_result.message, ClientRegistrationFinishParameters::default(), ) @@ -314,6 +320,7 @@ fn server_login_finish(c: &mut Criterion) { let client_login_finish_result = client_login_start_result .state .finish( + password, server_login_start_result.clone().message, ClientLoginFinishParameters::default(), ) diff --git a/examples/digital_locker.rs b/examples/digital_locker.rs index 719a6cb..408f7a0 100644 --- a/examples/digital_locker.rs +++ b/examples/digital_locker.rs @@ -122,6 +122,7 @@ fn register_locker( .state .finish( &mut client_rng, + password.as_bytes(), RegistrationResponse::deserialize(®istration_response_bytes).unwrap(), ClientRegistrationFinishParameters::default(), ) @@ -176,6 +177,7 @@ fn open_locker( // Server sends credential_response_bytes to client let result = client_login_start_result.state.finish( + password.as_bytes(), CredentialResponse::deserialize(&credential_response_bytes).unwrap(), ClientLoginFinishParameters::default(), ); diff --git a/examples/simple_login.rs b/examples/simple_login.rs index 5e2ef3f..9e651fc 100644 --- a/examples/simple_login.rs +++ b/examples/simple_login.rs @@ -86,6 +86,7 @@ fn account_registration( .state .finish( &mut client_rng, + password.as_bytes(), RegistrationResponse::deserialize(®istration_response_bytes).unwrap(), ClientRegistrationFinishParameters::default(), ) @@ -130,6 +131,7 @@ fn account_login( // Server sends credential_response_bytes to client let result = client_login_start_result.state.finish( + password.as_bytes(), CredentialResponse::deserialize(&credential_response_bytes).unwrap(), ClientLoginFinishParameters::default(), ); diff --git a/src/ciphersuite.rs b/src/ciphersuite.rs index e0cece9..4e2f60f 100644 --- a/src/ciphersuite.rs +++ b/src/ciphersuite.rs @@ -7,9 +7,12 @@ //! Defines the CipherSuite trait to specify the underlying primitives for OPAQUE +use crate::hash::ProxyHash; use crate::key_exchange::group::KeGroup; use crate::{hash::Hash, key_exchange::traits::KeyExchange, slow_hash::SlowHash}; -use voprf::group::Group as OprfGroup; +use digest::core_api::{BlockSizeUser, CoreProxy}; +use generic_array::typenum::{IsLess, Le, NonZero, U256}; +use voprf::Group as OprfGroup; /// Configures the underlying primitives used in OPAQUE /// * `OprfGroup`: a finite cyclic group along with a point representation, along @@ -19,7 +22,12 @@ use voprf::group::Group as OprfGroup; /// * `KeyExchange`: The key exchange protocol to use in the login step /// * `Hash`: The main hashing function to use /// * `SlowHash`: A slow hashing function, typically used for password hashing -pub trait CipherSuite { +pub trait CipherSuite +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// A finite cyclic group along with a point representation along with /// an extension trait PasswordToCurve that allows some customization on /// how to hash a password to a curve point. See `group::Group`. diff --git a/src/envelope.rs b/src/envelope.rs index 53073f6..ddcf488 100755 --- a/src/envelope.rs +++ b/src/envelope.rs @@ -8,7 +8,7 @@ use crate::{ ciphersuite::CipherSuite, errors::{utils::check_slice_size, InternalError, ProtocolError}, - hash::Hash, + hash::{Hash, OutputSize, ProxyHash}, key_exchange::group::KeGroup, keypair::{KeyPair, PublicKey}, opaque::{bytestrings_from_identifiers, Identifiers}, @@ -17,16 +17,17 @@ use crate::{ use core::convert::TryFrom; use core::ops::Add; use derive_where::DeriveWhere; -use digest::{Digest, FixedOutput}; +use digest::core_api::{BlockSizeUser, CoreProxy}; +use digest::Output; use generic_array::{ sequence::Concat, - typenum::{Sum, Unsigned, U2, U32}, + typenum::{IsLess, Le, NonZero, Sum, Unsigned, U2, U256, U32}, ArrayLength, GenericArray, }; use hkdf::Hkdf; -use hmac::{Hmac, Mac, NewMac}; +use hmac::{Hmac, Mac}; use rand::{CryptoRng, RngCore}; -use voprf::group::Group; +use voprf::Group; use zeroize::Zeroize; // Constant string used as salt for HKDF computation @@ -65,55 +66,63 @@ impl TryFrom for InnerEnvelopeMode { /// the confusion around the implementation of an RKR-secure encryption. #[derive(DeriveWhere)] #[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize(drop))] -pub(crate) struct Envelope { +pub(crate) struct Envelope +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ mode: InnerEnvelopeMode, nonce: GenericArray, - hmac: GenericArray::OutputSize>, + hmac: Output, } // Note that this struct represents an envelope that has been "opened" with the asssociated // key. This key is also used to derive the export_key parameter, which is technically // unrelated to the envelope's encrypted and authenticated contents. -pub(crate) struct OpenedEnvelope<'a, CS: CipherSuite> { +pub(crate) struct OpenedEnvelope<'a, CS: CipherSuite> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ pub(crate) client_static_keypair: KeyPair, - pub(crate) export_key: GenericArray::OutputSize>, + pub(crate) export_key: Output, pub(crate) id_u: Serialize<'a, U2, ::PkLen>, pub(crate) id_s: Serialize<'a, U2, ::PkLen>, } -pub(crate) struct OpenedInnerEnvelope { - pub(crate) export_key: GenericArray::OutputSize>, +pub(crate) struct OpenedInnerEnvelope +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + pub(crate) export_key: Output, } #[cfg(not(test))] -type SealRawResult = ( - Envelope, - GenericArray::Hash as Digest>::OutputSize>, -); +type SealRawResult = (Envelope, Output); #[cfg(test)] -type SealRawResult = ( - Envelope, - GenericArray::Hash as Digest>::OutputSize>, - GenericArray::Hash as Digest>::OutputSize>, -); +type SealRawResult = (Envelope, Output, Output); #[cfg(not(test))] -type SealResult = ( - Envelope, - PublicKey<::KeGroup>, - GenericArray::Hash as Digest>::OutputSize>, -); +type SealResult = (Envelope, PublicKey, Output); #[cfg(test)] -type SealResult = ( +type SealResult = ( Envelope, - PublicKey<::KeGroup>, - GenericArray::Hash as Digest>::OutputSize>, - GenericArray::Hash as Digest>::OutputSize>, + PublicKey, + Output, + Output, ); -#[allow(type_alias_bounds)] -pub(crate) type EnvelopeLen = Sum::OutputSize>; +pub(crate) type EnvelopeLen = Sum>; -impl Envelope { +impl Envelope +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ #[allow(clippy::type_complexity)] pub(crate) fn seal( rng: &mut R, @@ -155,8 +164,8 @@ impl Envelope { aad: impl Iterator, mode: InnerEnvelopeMode, ) -> Result, InternalError> { - let mut hmac_key = GenericArray::<_, ::OutputSize>::default(); - let mut export_key = GenericArray::<_, ::OutputSize>::default(); + let mut hmac_key = Output::::default(); + let mut export_key = Output::::default(); randomized_pwd_hasher .expand_multi_info(&[&nonce, &STR_AUTH_KEY], &mut hmac_key) @@ -223,8 +232,8 @@ impl Envelope { randomized_pwd_hasher: Hkdf, aad: impl Iterator, ) -> Result, InternalError> { - let mut hmac_key = GenericArray::<_, ::OutputSize>::default(); - let mut export_key = GenericArray::<_, ::OutputSize>::default(); + let mut hmac_key = Output::::default(); + let mut export_key = Output::::default(); randomized_pwd_hasher .expand(&self.nonce.concat(STR_AUTH_KEY.into()), &mut hmac_key) @@ -253,17 +262,17 @@ impl Envelope { } fn hmac_key_size() -> usize { - ::OutputSize::USIZE + OutputSize::::USIZE } pub(crate) fn len() -> usize { - ::OutputSize::USIZE + NonceLen::USIZE + OutputSize::::USIZE + NonceLen::USIZE } pub(crate) fn serialize(&self) -> GenericArray> where // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, { self.nonce.concat(self.hmac.clone()) @@ -300,14 +309,19 @@ impl Envelope { fn build_inner_envelope_internal( randomized_pwd_hasher: Hkdf, nonce: GenericArray, -) -> Result, ProtocolError> { +) -> Result, ProtocolError> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ let mut keypair_seed = GenericArray::<_, ::SkLen>::default(); randomized_pwd_hasher .expand(&nonce.concat(STR_PRIVATE_KEY.into()), &mut keypair_seed) .map_err(|_| InternalError::HkdfError)?; let client_static_keypair = KeyPair::::from_private_key_slice( &CS::OprfGroup::scalar_as_bytes(CS::OprfGroup::hash_to_scalar::( - Some(keypair_seed.as_slice()), + [keypair_seed.as_slice()], GenericArray::from(STR_OPAQUE_DERIVE_AUTH_KEY_PAIR), )?), )?; @@ -318,14 +332,19 @@ fn build_inner_envelope_internal( fn recover_keys_internal( randomized_pwd_hasher: Hkdf, nonce: GenericArray, -) -> Result, ProtocolError> { +) -> Result, ProtocolError> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ let mut keypair_seed = GenericArray::<_, ::SkLen>::default(); randomized_pwd_hasher .expand(&nonce.concat(STR_PRIVATE_KEY.into()), &mut keypair_seed) .map_err(|_| InternalError::HkdfError)?; let client_static_keypair = KeyPair::::from_private_key_slice( &CS::OprfGroup::scalar_as_bytes(CS::OprfGroup::hash_to_scalar::( - Some(keypair_seed.as_slice()), + [keypair_seed.as_slice()], GenericArray::from(STR_OPAQUE_DERIVE_AUTH_KEY_PAIR), )?), )?; @@ -338,5 +357,5 @@ fn construct_aad<'a>( id_s: impl Iterator, server_s_pk: &'a [u8], ) -> impl Iterator { - chain!(Some(server_s_pk).into_iter(), id_s, id_u) + [server_s_pk].into_iter().chain(id_s).chain(id_u) } diff --git a/src/errors.rs b/src/errors.rs index 36810fe..178ec48 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -8,7 +8,7 @@ //! A list of error types which are produced during an execution of the protocol use core::convert::Infallible; use core::fmt::Debug; -#[cfg(feature = "std")] +#[cfg(any(feature = "std", test))] use std::error::Error; use displaydoc::Display; @@ -48,7 +48,7 @@ pub enum InternalError { /// This error occurs when the inner envelope is malformed InvalidInnerEnvelopeError, /// Error from the OPRF evaluation - OprfError(voprf::errors::InternalError), + OprfError(voprf::Error), /// Error encountered when attempting to produce a keypair InvalidKeypairError, } @@ -84,7 +84,7 @@ impl Debug for InternalError { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", test))] impl Error for InternalError {} impl InternalError { @@ -116,14 +116,14 @@ impl InternalError { } } -impl From for InternalError { - fn from(voprf_error: voprf::errors::InternalError) -> Self { +impl From for InternalError { + fn from(voprf_error: voprf::Error) -> Self { Self::OprfError(voprf_error) } } -impl From for ProtocolError { - fn from(voprf_error: voprf::errors::InternalError) -> Self { +impl From for ProtocolError { + fn from(voprf_error: voprf::Error) -> Self { Self::LibraryError(InternalError::OprfError(voprf_error)) } } @@ -158,7 +158,7 @@ impl Debug for ProtocolError { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", test))] impl Error for ProtocolError {} // This is meant to express future(ly) non-trivial ways of converting the diff --git a/src/hash.rs b/src/hash.rs index 87161f2..a33926c 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -7,11 +7,58 @@ //! A convenience trait for digest bounds used throughout the library -use digest::{BlockInput, FixedOutput, Reset, Update}; +use digest::block_buffer::Eager; +use digest::core_api::{BlockSizeUser, BufferKindUser, CoreProxy, FixedOutputCore}; +use digest::{Digest, FixedOutputReset, HashMarker, OutputSizeUser}; +use generic_array::typenum::{IsLess, Le, NonZero, U256}; + +pub(crate) type OutputSize = <::Core as OutputSizeUser>::OutputSize; + +/// Trait to simplify requirements for [`Hash`]. +pub trait ProxyHash: + HashMarker + FixedOutputCore + BufferKindUser + Default + Clone +where + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ +} + +impl + Default + Clone> + ProxyHash for T +where + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ +} /// Trait inheriting the requirements from digest::Digest for compatibility with HKDF and HMAC // Associated types could be simplified when they are made as defaults: // https://github.com/rust-lang/rust/issues/29661 -pub trait Hash: Update + BlockInput + FixedOutput + Reset + Default + Clone {} +pub trait Hash: + Digest + + OutputSizeUser> + + BlockSizeUser + + FixedOutputReset + + CoreProxy + + Clone +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ +} -impl Hash for T {} +impl< + T: Digest + + OutputSizeUser> + + BlockSizeUser + + FixedOutputReset + + CoreProxy + + Clone, + > Hash for T +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ +} diff --git a/src/impls.rs b/src/impls.rs index 6489d5f..a579a76 100755 --- a/src/impls.rs +++ b/src/impls.rs @@ -7,23 +7,29 @@ /// Macro used for deriving `serde`'s `Serialize` and `Deserialize` traits. macro_rules! impl_serialize_and_deserialize_for { - ($item:ident$( where $($path:ty: $bound1:path $(| $bound2:path)*),+$(,)?)?$(; $error:expr)?) => { + ($item:ident$( where $($path:ty: $bound1:path $(| $bound2:path)*),+$(,)?)?) => { #[cfg(feature = "serde")] impl serde_::Serialize for $item - $(where - $($path: $bound1 $(+ $bound2)*),+ - )? + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + $($($path: $bound1 $(+ $bound2)*),+)? { fn serialize(&self, serializer: S) -> Result where S: serde_::Serializer, { - serializer.serialize_bytes(&self.serialize()$(.map_err($error)?)?) + serializer.serialize_bytes(&self.serialize()) } } #[cfg(feature = "serde")] impl<'de, CS: CipherSuite> serde_::Deserialize<'de> for $item + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { fn deserialize(deserializer: D) -> Result where @@ -31,9 +37,17 @@ macro_rules! impl_serialize_and_deserialize_for { { use serde_::de::Error; - struct ByteVisitor(core::marker::PhantomData); + struct ByteVisitor(core::marker::PhantomData) + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero; impl<'de, CS: CipherSuite> serde_::de::Visitor<'de> for ByteVisitor + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { type Value = $item; diff --git a/src/key_exchange/group/p256.rs b/src/key_exchange/group/p256.rs index 9f53e18..92b9d60 100644 --- a/src/key_exchange/group/p256.rs +++ b/src/key_exchange/group/p256.rs @@ -26,11 +26,13 @@ impl KeGroup for PublicKey { } fn random_sk(rng: &mut R) -> GenericArray { - SecretKey::::random(rng).to_bytes() + SecretKey::::random(rng).to_be_bytes() } fn public_key(sk: &GenericArray) -> Self { - SecretKey::::from_bytes(sk).unwrap().public_key() + SecretKey::::from_be_bytes(sk) + .unwrap() + .public_key() } fn to_arr(&self) -> GenericArray { @@ -39,9 +41,9 @@ impl KeGroup for PublicKey { fn diffie_hellman(&self, sk: &GenericArray) -> GenericArray { (self.to_projective() - * SecretKey::::from_bytes(sk) + * SecretKey::::from_be_bytes(sk) .unwrap() - .to_secret_scalar() + .to_nonzero_scalar() .as_ref()) .to_affine() .to_bytes() diff --git a/src/key_exchange/traits.rs b/src/key_exchange/traits.rs index 8fdb669..7f33904 100755 --- a/src/key_exchange/traits.rs +++ b/src/key_exchange/traits.rs @@ -5,6 +5,7 @@ // License, Version 2.0 found in the LICENSE-APACHE file in the root directory // of this source tree. +use crate::hash::ProxyHash; use crate::key_exchange::group::KeGroup; use crate::{ ciphersuite::CipherSuite, @@ -12,7 +13,9 @@ use crate::{ hash::Hash, keypair::{PrivateKey, PublicKey, SecretKey}, }; -use digest::Digest; +use digest::core_api::BlockSizeUser; +use digest::Output; +use generic_array::typenum::{IsLess, Le, NonZero, U256}; use generic_array::{ArrayLength, GenericArray}; use rand::{CryptoRng, RngCore}; use zeroize::Zeroize; @@ -26,23 +29,25 @@ pub type GenerateKe2Result = ( pub type GenerateKe2Result = ( >::KE2State, >::KE2Message, - GenericArray::OutputSize>, - GenericArray::OutputSize>, + Output, + Output, ); #[cfg(not(test))] -pub type GenerateKe3Result = ( - GenericArray::OutputSize>, - >::KE3Message, -); +pub type GenerateKe3Result = (Output, >::KE3Message); #[cfg(test)] pub type GenerateKe3Result = ( - GenericArray::OutputSize>, + Output, >::KE3Message, - GenericArray::OutputSize>, - GenericArray::OutputSize>, + Output, + Output, ); -pub trait KeyExchange { +pub trait KeyExchange +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ type KE1State: FromBytes + ToBytes + Zeroize + Clone; type KE2State: FromBytes + ToBytes + Zeroize + Clone; type KE1Message: FromBytes + ToBytes + Zeroize + Clone; @@ -83,7 +88,7 @@ pub trait KeyExchange { fn finish_ke( ke3_message: Self::KE3Message, ke2_state: &Self::KE2State, - ) -> Result, ProtocolError>; + ) -> Result, ProtocolError>; fn ke2_message_size() -> usize; } @@ -98,19 +103,14 @@ pub trait ToBytes { fn to_bytes(&self) -> GenericArray; } -#[allow(dead_code, type_alias_bounds)] +#[allow(dead_code)] pub type Ke1StateLen = <>::KE1State as ToBytes>::Len; -#[allow(type_alias_bounds)] pub type Ke1MessageLen = <>::KE1Message as ToBytes>::Len; -#[allow(type_alias_bounds)] -#[allow(type_alias_bounds)] pub type Ke2StateLen = <>::KE2State as ToBytes>::Len; -#[allow(type_alias_bounds)] pub type Ke2MessageLen = <>::KE2Message as ToBytes>::Len; -#[allow(type_alias_bounds)] pub type Ke3MessageLen = <>::KE3Message as ToBytes>::Len; diff --git a/src/key_exchange/tripledh.rs b/src/key_exchange/tripledh.rs index bd8f0df..b5e7631 100755 --- a/src/key_exchange/tripledh.rs +++ b/src/key_exchange/tripledh.rs @@ -11,7 +11,7 @@ use crate::{ utils::{check_slice_size, check_slice_size_atleast}, InternalError, ProtocolError, }, - hash::Hash, + hash::{Hash, OutputSize, ProxyHash}, key_exchange::{ group::KeGroup, traits::{FromBytes, GenerateKe2Result, GenerateKe3Result, KeyExchange, ToBytes}, @@ -19,18 +19,19 @@ use crate::{ keypair::{KeyPair, PrivateKey, PublicKey, SecretKey}, serialization::{Serialize, UpdateExt}, }; -use core::array::IntoIter; use core::convert::TryFrom; use core::ops::Add; use derive_where::DeriveWhere; -use digest::{Digest, FixedOutput}; +use digest::core_api::BlockSizeUser; +use digest::{Digest, Output}; use generic_array::sequence::Concat; +use generic_array::typenum::{IsLess, Le, NonZero, U256}; use generic_array::{ typenum::{Sum, Unsigned, U1, U2, U32}, ArrayLength, GenericArray, }; use hkdf::{Hkdf, HkdfExtract}; -use hmac::{Hmac, Mac, NewMac}; +use hmac::{Hmac, Mac}; use rand::{CryptoRng, RngCore}; /////////////// @@ -89,10 +90,15 @@ pub struct Ke1Message { )] #[derive(DeriveWhere)] #[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize(drop))] -pub struct Ke2State { - km3: GenericArray, - hashed_transcript: GenericArray, - session_key: GenericArray, +pub struct Ke2State +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + km3: Output, + hashed_transcript: Output, + session_key: Output, } /// The second key exchange message @@ -103,10 +109,15 @@ pub struct Ke2State { )] #[derive(DeriveWhere)] #[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Ke2Message { +pub struct Ke2Message +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ server_nonce: GenericArray, server_e_pk: PublicKey, - mac: GenericArray, + mac: Output, } /// The third key exchange message @@ -117,8 +128,13 @@ pub struct Ke2Message { )] #[derive(DeriveWhere)] #[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Ke3Message { - mac: GenericArray, +pub struct Ke3Message +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + mac: Output, } //////////////////////////////// @@ -128,6 +144,9 @@ pub struct Ke3Message { impl KeyExchange for TripleDH where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, // Ke1State: KeSk + Nonce KG::SkLen: Add, Sum: ArrayLength, @@ -135,13 +154,13 @@ where NonceLen: Add, Sum: ArrayLength, // Ke2State: (Hash + Hash) + Hash - D::OutputSize: Add, - Sum: ArrayLength + Add, - Sum, D::OutputSize>: ArrayLength, + OutputSize: Add>, + Sum, OutputSize>: ArrayLength + Add>, + Sum, OutputSize>, OutputSize>: ArrayLength, // Ke2Message: (Nonce + KePk) + Hash NonceLen: Add, - Sum: ArrayLength + Add, - Sum, D::OutputSize>: ArrayLength, + Sum: ArrayLength + Add>, + Sum, OutputSize>: ArrayLength, { type KE1State = Ke1State; type KE2State = Ke2State; @@ -215,7 +234,7 @@ where mac_hasher.update(&transcript_hasher.clone().finalize()); let mac = mac_hasher.finalize().into_bytes(); - transcript_hasher.update(&mac); + Digest::update(&mut transcript_hasher, &mac); Ok(( Ke2State { @@ -276,7 +295,7 @@ where .verify(&ke2_message.mac) .map_err(|_| ProtocolError::InvalidLoginError)?; - transcript_hasher.update(&ke2_message.mac); + Digest::update(&mut transcript_hasher, &ke2_message.mac); let mut client_mac = Hmac::::new_from_slice(&result.2).map_err(|_| InternalError::HmacError)?; @@ -294,11 +313,10 @@ where )) } - #[allow(clippy::type_complexity)] fn finish_ke( ke3_message: Self::KE3Message, ke2_state: &Self::KE2State, - ) -> Result, ProtocolError> { + ) -> Result, ProtocolError> { let mut client_mac = Hmac::::new_from_slice(&ke2_state.km3).map_err(|_| InternalError::HmacError)?; client_mac.update(&ke2_state.hashed_transcript); @@ -311,7 +329,7 @@ where } fn ke2_message_size() -> usize { - NonceLen::USIZE + ::PkLen::USIZE + ::OutputSize::USIZE + NonceLen::USIZE + ::PkLen::USIZE + OutputSize::::USIZE } } @@ -334,18 +352,9 @@ struct TripleDHComponents> { // Consists of a session key, followed by two mac keys: (session_key, km2, km3) #[cfg(not(test))] #[allow(clippy::upper_case_acronyms)] -type TripleDHDerivationResult = ( - GenericArray::OutputSize>, - GenericArray::OutputSize>, - GenericArray::OutputSize>, -); +type TripleDHDerivationResult = (Output, Output, Output); #[cfg(test)] -type TripleDHDerivationResult = ( - GenericArray::OutputSize>, - GenericArray::OutputSize>, - GenericArray::OutputSize>, - GenericArray::OutputSize>, -); +type TripleDHDerivationResult = (Output, Output, Output, Output); //////////////////////////////////////////////// // Helper functions and Trait Implementations // @@ -359,7 +368,12 @@ type TripleDHDerivationResult = ( fn derive_3dh_keys>( dh: TripleDHComponents, hashed_derivation_transcript: &[u8], -) -> Result, ProtocolError> { +) -> Result, ProtocolError> +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ let mut hkdf = HkdfExtract::::new(None); hkdf.input_ikm( @@ -406,7 +420,12 @@ fn hkdf_expand_label( secret: &[u8], label: &[u8], context: &[u8], -) -> Result, ProtocolError> { +) -> Result, ProtocolError> +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ let h = Hkdf::::from_prk(secret).map_err(|_| InternalError::HkdfError)?; hkdf_expand_label_extracted(&h, label, context) } @@ -415,11 +434,16 @@ fn hkdf_expand_label_extracted( hkdf: &Hkdf, label: &[u8], context: &[u8], -) -> Result, ProtocolError> { +) -> Result, ProtocolError> +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ let mut okm = GenericArray::default(); let length_u16: u16 = - u16::try_from(D::OutputSize::USIZE).map_err(|_| ProtocolError::SerializationError)?; + u16::try_from(OutputSize::::USIZE).map_err(|_| ProtocolError::SerializationError)?; let label = Serialize::::from_label(STR_OPAQUE, label)?; let label = label.to_array_3(); let context = Serialize::::from(context)?; @@ -443,7 +467,12 @@ fn derive_secrets( hkdf: &Hkdf, label: &[u8], hashed_derivation_transcript: &[u8], -) -> Result, ProtocolError> { +) -> Result, ProtocolError> +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ hkdf_expand_label_extracted::(hkdf, label, hashed_derivation_transcript) } @@ -514,9 +543,14 @@ where } } -impl FromBytes for Ke2State { +impl FromBytes for Ke2State +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ fn from_bytes(input: &[u8]) -> Result { - let hash_len = D::OutputSize::USIZE; + let hash_len = OutputSize::::USIZE; let checked_bytes = check_slice_size(input, 3 * hash_len, "ke2_state")?; Ok(Self { @@ -531,12 +565,15 @@ impl FromBytes for Ke2State { impl ToBytes for Ke2State where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, // Ke2State: (Hash + Hash) + Hash - D::OutputSize: Add, - Sum: ArrayLength + Add, - Sum, D::OutputSize>: ArrayLength, + OutputSize: Add>, + Sum, OutputSize>: ArrayLength + Add>, + Sum, OutputSize>, OutputSize>: ArrayLength, { - type Len = Sum, D::OutputSize>; + type Len = Sum, OutputSize>, OutputSize>; fn to_bytes(&self) -> GenericArray { self.km3 @@ -546,7 +583,12 @@ where } } -impl FromBytes for Ke2Message { +impl FromBytes for Ke2Message +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ fn from_bytes(input: &[u8]) -> Result { let key_len = ::PkLen::USIZE; let nonce_len = NonceLen::USIZE; @@ -559,7 +601,7 @@ impl FromBytes for Ke2Message { )?; let checked_mac = check_slice_size( &unchecked_server_e_pk[key_len..], - D::OutputSize::USIZE, + OutputSize::::USIZE, "ke1_message mac", )?; @@ -578,12 +620,15 @@ impl FromBytes for Ke2Message { impl ToBytes for Ke2Message where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, // Ke2Message: (Nonce + KePk) + Hash NonceLen: Add, - Sum: ArrayLength + Add, - Sum, D::OutputSize>: ArrayLength, + Sum: ArrayLength + Add>, + Sum, OutputSize>: ArrayLength, { - type Len = Sum, D::OutputSize>; + type Len = Sum, OutputSize>; fn to_bytes(&self) -> GenericArray { self.server_nonce @@ -592,17 +637,25 @@ where } } -impl Ke2Message { +impl Ke2Message +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ fn to_bytes_without_info_or_mac(&self) -> impl Iterator { - // MSRV: array `into_iter` isn't available in 1.51 - #[allow(deprecated)] - IntoIter::new([self.server_nonce.as_slice(), self.server_e_pk.as_slice()]) + [self.server_nonce.as_slice(), self.server_e_pk.as_slice()].into_iter() } } -impl FromBytes for Ke3Message { +impl FromBytes for Ke3Message +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ fn from_bytes(bytes: &[u8]) -> Result { - let checked_bytes = check_slice_size(bytes, D::OutputSize::USIZE, "ke3_message")?; + let checked_bytes = check_slice_size(bytes, OutputSize::::USIZE, "ke3_message")?; Ok(Self { mac: GenericArray::clone_from_slice(checked_bytes), @@ -610,8 +663,13 @@ impl FromBytes for Ke3Message { } } -impl ToBytes for Ke3Message { - type Len = D::OutputSize; +impl ToBytes for Ke3Message +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + type Len = OutputSize; fn to_bytes(&self) -> GenericArray { self.mac.clone() diff --git a/src/keypair.rs b/src/keypair.rs index 9f880f1..064e852 100644 --- a/src/keypair.rs +++ b/src/keypair.rs @@ -251,15 +251,13 @@ mod tests { use core::slice::from_raw_parts; use generic_array::typenum::Unsigned; use rand::rngs::OsRng; + use std::vec; #[test] fn test_zeroize_key() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> { let key_len = G::PkLen::USIZE; - let mut key = Key::(GenericArray::clone_from_slice(&alloc::vec![ - 1u8; - key_len - ])); + let mut key = Key::(GenericArray::clone_from_slice(&vec![1u8; key_len])); let ptr = key.as_ptr(); Zeroize::zeroize(&mut key); @@ -308,6 +306,7 @@ mod tests { mod $mod { use super::*; use proptest::prelude::*; + use std::format; proptest! { #[test] @@ -428,6 +427,7 @@ mod tests { let ClientRegistrationFinishResult { message, .. } = client .finish( &mut OsRng, + PASSWORD.as_bytes(), message, ClientRegistrationFinishParameters::default(), ) @@ -452,7 +452,11 @@ mod tests { ) .unwrap(); let ClientLoginFinishResult { message, .. } = client - .finish(message, ClientLoginFinishParameters::default()) + .finish( + PASSWORD.as_bytes(), + message, + ClientLoginFinishParameters::default(), + ) .unwrap(); server.finish(message).unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index 49788b3..8deac88 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ //! //! ### Minimum Supported Rust Version //! -//! Rust **1.51** or higher. +//! Rust **1.56** or higher. //! //! # Overview //! @@ -207,6 +207,7 @@ //! # let server_registration_start_result = ServerRegistration::::start(&server_setup, client_registration_start_result.message, b"alice@example.com")?; //! let client_registration_finish_result = client_registration_start_result.state.finish( //! &mut client_rng, +//! b"password", //! server_registration_start_result.message, //! ClientRegistrationFinishParameters::default(), //! )?; @@ -253,7 +254,7 @@ //! # let mut server_rng = OsRng; //! # let server_setup = ServerSetup::::new(&mut server_rng); //! # let server_registration_start_result = ServerRegistration::::start(&server_setup, client_registration_start_result.message, b"alice@example.com")?; -//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::default())?; +//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, b"password", server_registration_start_result.message, ClientRegistrationFinishParameters::default())?; //! let password_file = ServerRegistration::::finish( //! client_registration_finish_result.message, //! ); @@ -348,7 +349,7 @@ //! # let mut server_rng = OsRng; //! # let server_setup = ServerSetup::::new(&mut server_rng); //! # let server_registration_start_result = ServerRegistration::::start(&server_setup, client_registration_start_result.message, b"alice@example.com")?; -//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::default())?; +//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, b"password", server_registration_start_result.message, ClientRegistrationFinishParameters::default())?; //! # let password_file_bytes = ServerRegistration::::finish(client_registration_finish_result.message).serialize(); //! # let client_login_start_result = ClientLogin::::start( //! # &mut client_rng, @@ -411,7 +412,7 @@ //! # let mut server_rng = OsRng; //! # let server_setup = ServerSetup::::new(&mut server_rng); //! # let server_registration_start_result = ServerRegistration::::start(&server_setup, client_registration_start_result.message, b"alice@example.com")?; -//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::default())?; +//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, b"password", server_registration_start_result.message, ClientRegistrationFinishParameters::default())?; //! # let password_file_bytes = ServerRegistration::::finish(client_registration_finish_result.message).serialize(); //! # let client_login_start_result = ClientLogin::::start( //! # &mut client_rng, @@ -424,6 +425,7 @@ //! # let server_login_start_result = //! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"alice@example.com", ServerLoginStartParameters::default())?; //! let client_login_finish_result = client_login_start_result.state.finish( +//! b"password", //! server_login_start_result.message, //! ClientLoginFinishParameters::default(), //! )?; @@ -466,7 +468,7 @@ //! # let mut server_rng = OsRng; //! # let server_setup = ServerSetup::::new(&mut server_rng); //! # let server_registration_start_result = ServerRegistration::::start(&server_setup, client_registration_start_result.message, b"alice@example.com")?; -//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::default())?; +//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, b"password", server_registration_start_result.message, ClientRegistrationFinishParameters::default())?; //! # let password_file_bytes = ServerRegistration::::finish(client_registration_finish_result.message).serialize(); //! # let client_login_start_result = ClientLogin::::start( //! # &mut client_rng, @@ -479,6 +481,7 @@ //! # let server_login_start_result = //! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"alice@example.com", ServerLoginStartParameters::default())?; //! # let client_login_finish_result = client_login_start_result.state.finish( +//! # b"password", //! # server_login_start_result.message, //! # ClientLoginFinishParameters::default(), //! # )?; @@ -555,6 +558,7 @@ //! // a server_s_pk field //! let client_registration_finish_result = client_registration_start_result.state.finish( //! &mut client_rng, +//! b"password", //! server_registration_start_result.message, //! ClientRegistrationFinishParameters::default(), //! )?; @@ -572,6 +576,7 @@ //! //! // And then later, during login... //! let client_login_finish_result = client_login_start_result.state.finish( +//! b"password", //! server_login_start_result.message, //! ClientLoginFinishParameters::default(), //! )?; @@ -641,6 +646,7 @@ //! // During registration... //! let client_registration_finish_result = client_registration_start_result.state.finish( //! &mut client_rng, +//! b"password", //! server_registration_start_result.message, //! ClientRegistrationFinishParameters::default() //! )?; @@ -658,6 +664,7 @@ //! //! // And then later, during login... //! let client_login_finish_result = client_login_start_result.state.finish( +//! b"password", //! server_login_start_result.message, //! ClientLoginFinishParameters::default(), //! )?; @@ -715,6 +722,7 @@ //! # let server_registration_start_result = ServerRegistration::::start(&server_setup, client_registration_start_result.message, b"alice@example.com")?; //! let client_registration_finish_result = client_registration_start_result.state.finish( //! &mut client_rng, +//! b"password", //! server_registration_start_result.message, //! ClientRegistrationFinishParameters::new( //! Identifiers { @@ -761,7 +769,7 @@ //! # let mut server_rng = OsRng; //! # let server_setup = ServerSetup::::new(&mut server_rng); //! # let server_registration_start_result = ServerRegistration::::start(&server_setup, client_registration_start_result.message, b"alice@example.com")?; -//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::new(Identifiers { client: Some(b"Alice_the_Cryptographer"), server: Some(b"Facebook") }, None))?; +//! # 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::::finish(client_registration_finish_result.message).serialize(); //! # let client_login_start_result = ClientLogin::::start( //! # &mut client_rng, @@ -821,7 +829,7 @@ //! # let mut server_rng = OsRng; //! # let server_setup = ServerSetup::::new(&mut server_rng); //! # let server_registration_start_result = ServerRegistration::::start(&server_setup, client_registration_start_result.message, b"alice@example.com")?; -//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::new(Identifiers { client: Some(b"Alice_the_Cryptographer"), server: Some(b"Facebook") }, None))?; +//! # 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::::finish(client_registration_finish_result.message).serialize(); //! # let client_login_start_result = ClientLogin::::start( //! # &mut client_rng, @@ -834,6 +842,7 @@ //! # let server_login_start_result = //! # ServerLogin::start(&mut server_rng, &server_setup, Some(password_file), client_login_start_result.message, b"alice@example.com", ServerLoginStartParameters { 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( +//! b"password", //! server_login_start_result.message, //! ClientLoginFinishParameters::new( //! None, @@ -975,19 +984,18 @@ //! #![deny(unsafe_code)] -#![cfg_attr(not(feature = "std"), no_std)] +#![no_std] #![warn(clippy::cargo, missing_docs)] -#![allow(clippy::multiple_crate_versions)] +#![allow(clippy::multiple_crate_versions, type_alias_bounds)] -extern crate alloc; +#[cfg(any(feature = "std", test))] +extern crate std; // Error types pub mod errors; #[macro_use] mod impls; -#[macro_use] -mod serialization; pub mod ciphersuite; mod envelope; pub mod hash; @@ -995,6 +1003,7 @@ pub mod key_exchange; pub mod keypair; mod messages; mod opaque; +mod serialization; pub mod slow_hash; #[cfg(test)] diff --git a/src/messages.rs b/src/messages.rs index 468b898..ba58d9f 100755 --- a/src/messages.rs +++ b/src/messages.rs @@ -14,6 +14,7 @@ use crate::{ utils::{check_slice_size, check_slice_size_atleast}, ProtocolError, }, + hash::{OutputSize, ProxyHash}, key_exchange::{ group::KeGroup, traits::{FromBytes, Ke1MessageLen, Ke2MessageLen, Ke3MessageLen, KeyExchange, ToBytes}, @@ -22,17 +23,17 @@ use crate::{ keypair::{KeyPair, PublicKey, SecretKey}, opaque::{MaskedResponse, MaskedResponseLen, ServerSetup}, }; -use core::array::IntoIter; use core::ops::Add; use derive_where::DeriveWhere; -use digest::{Digest, FixedOutput}; +use digest::core_api::{BlockSizeUser, CoreProxy}; +use digest::Output; use generic_array::sequence::Concat; use generic_array::{ - typenum::{Sum, Unsigned}, + typenum::{IsLess, Le, NonZero, Sum, Unsigned, U256}, ArrayLength, GenericArray, }; use rand::{CryptoRng, RngCore}; -use voprf::group::Group; +use voprf::Group; //////////////////////////// // High-level API Structs // @@ -43,7 +44,12 @@ use voprf::group::Group; #[derive(DeriveWhere)] #[derive_where(Clone)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; CS::OprfGroup)] -pub struct RegistrationRequest { +pub struct RegistrationRequest +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// blinded password information pub(crate) blinded_element: voprf::BlindedElement, } @@ -55,7 +61,12 @@ impl_serialize_and_deserialize_for!(RegistrationRequest); #[derive(DeriveWhere)] #[derive_where(Clone)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; CS::OprfGroup)] -pub struct RegistrationResponse { +pub struct RegistrationResponse +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The server's oprf output pub(crate) evaluation_element: voprf::EvaluationElement, /// Server's static public key @@ -74,12 +85,17 @@ impl_serialize_and_deserialize_for!( /// identifiers #[derive(DeriveWhere)] #[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize(drop))] -pub struct RegistrationUpload { +pub struct RegistrationUpload +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The "envelope" generated by the user, containing sealed /// cryptographic identifiers pub(crate) envelope: Envelope, /// The masking key used to mask the envelope - pub(crate) masking_key: GenericArray::OutputSize>, + pub(crate) masking_key: Output, /// The user's public key pub(crate) client_s_pk: PublicKey, } @@ -88,11 +104,11 @@ impl_serialize_and_deserialize_for!( RegistrationUpload where // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength | Add>, RegistrationUploadLen: ArrayLength, ); @@ -105,7 +121,12 @@ impl_serialize_and_deserialize_for!( CS::OprfGroup, >::KE1Message, )] -pub struct CredentialRequest { +pub struct CredentialRequest +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ pub(crate) blinded_element: voprf::BlindedElement, pub(crate) ke1_message: >::KE1Message, } @@ -127,7 +148,12 @@ impl_serialize_and_deserialize_for!( CS::OprfGroup, >::KE2Message, )] -pub struct CredentialResponse { +pub struct CredentialResponse +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// the server's oprf output pub(crate) evaluation_element: voprf::EvaluationElement, pub(crate) masking_nonce: GenericArray, @@ -144,8 +170,8 @@ impl_serialize_and_deserialize_for!( ArrayLength | Add>, CredentialResponseWithoutKeLen: ArrayLength, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: + NonceLen: Add>, + Sum>: ArrayLength | Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message @@ -161,7 +187,12 @@ impl_serialize_and_deserialize_for!( Debug, Eq, Hash, PartialEq; >::KE3Message, )] -pub struct CredentialFinalization { +pub struct CredentialFinalization +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ pub(crate) ke3_message: >::KE3Message, } @@ -173,10 +204,14 @@ impl_serialize_and_deserialize_for!(CredentialFinalization); //////////////////////////////// /// Length of [`RegistrationRequest`] in bytes for serialization. -#[allow(type_alias_bounds)] pub type RegistrationRequestLen = ::ElemLen; -impl RegistrationRequest { +impl RegistrationRequest +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Only used for testing purposes #[cfg(test)] pub fn get_blinded_element_for_testing( @@ -199,11 +234,15 @@ impl RegistrationRequest { } /// Length of [`RegistrationResponse`] in bytes for serialization. -#[allow(type_alias_bounds)] pub type RegistrationResponseLen = Sum<::ElemLen, ::PkLen>; -impl RegistrationResponse { +impl RegistrationResponse +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where @@ -247,22 +286,24 @@ impl RegistrationResponse { } /// Length of [`RegistrationUpload`] in bytes for serialization. -#[allow(type_alias_bounds)] -pub type RegistrationUploadLen = Sum< - Sum<::PkLen, ::OutputSize>, - EnvelopeLen, ->; +pub type RegistrationUploadLen = + Sum::PkLen, OutputSize>, EnvelopeLen>; -impl RegistrationUpload { +impl RegistrationUpload +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, { @@ -275,7 +316,7 @@ impl RegistrationUpload { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { let key_len = ::PkLen::USIZE; - let hash_len = ::OutputSize::USIZE; + let hash_len = OutputSize::::USIZE; let checked_slice = check_slice_size_atleast(input, key_len + hash_len, "registration_upload_bytes")?; let envelope = Envelope::::deserialize(&checked_slice[key_len + hash_len..])?; @@ -295,7 +336,7 @@ impl RegistrationUpload { rng: &mut R, server_setup: &ServerSetup, ) -> Self { - let mut masking_key = GenericArray::<_, ::OutputSize>::default(); + let mut masking_key = Output::::default(); rng.fill_bytes(&mut masking_key); Self { @@ -307,11 +348,15 @@ impl RegistrationUpload { } /// Length of [`CredentialRequest`] in bytes for serialization. -#[allow(type_alias_bounds)] pub type CredentialRequestLen = Sum<::ElemLen, Ke1MessageLen>; -impl CredentialRequest { +impl CredentialRequest +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where @@ -329,9 +374,7 @@ impl CredentialRequest { blinded_element: &'a GenericArray::ElemLen>, ke1_message: &'a GenericArray>, ) -> impl Iterator { - // MSRV: array `into_iter` isn't available in 1.51 - #[allow(deprecated)] - IntoIter::new([blinded_element.as_slice(), ke1_message]) + [blinded_element.as_slice(), ke1_message].into_iter() } /// Deserialization from bytes @@ -372,15 +415,18 @@ impl CredentialRequest { } /// Length of [`CredentialResponse`] in bytes for serialization. -#[allow(type_alias_bounds)] pub type CredentialResponseLen = Sum, Ke2MessageLen>; -#[allow(type_alias_bounds)] pub(crate) type CredentialResponseWithoutKeLen = Sum::ElemLen, NonceLen>, MaskedResponseLen>; -impl CredentialResponse { +impl CredentialResponse +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where @@ -390,9 +436,8 @@ impl CredentialResponse { ArrayLength + Add>, CredentialResponseWithoutKeLen: ArrayLength, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message CredentialResponseWithoutKeLen: Add>, @@ -411,9 +456,7 @@ impl CredentialResponse { masking_nonce: &'a GenericArray, masked_response: &'a MaskedResponse, ) -> impl Iterator { - // MSRV: array `into_iter` isn't available in 1.51 - #[allow(deprecated)] - IntoIter::new([beta.as_slice(), masking_nonce.as_slice()]) + [beta.as_slice(), masking_nonce.as_slice()] .into_iter() .chain(masked_response.iter()) } @@ -476,10 +519,14 @@ impl CredentialResponse { } /// Length of [`CredentialFinalization`] in bytes for serialization. -#[allow(type_alias_bounds)] pub type CredentialFinalizationLen = Ke3MessageLen; -impl CredentialFinalization { +impl CredentialFinalization +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes pub fn serialize(&self) -> GenericArray> { self.ke3_message.to_bytes() diff --git a/src/opaque.rs b/src/opaque.rs index 5811066..82fcbd6 100755 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -11,34 +11,33 @@ use crate::{ ciphersuite::CipherSuite, envelope::{Envelope, EnvelopeLen}, errors::{utils::check_slice_size, InternalError, ProtocolError}, - hash::Hash, + hash::{Hash, OutputSize, ProxyHash}, key_exchange::{ group::KeGroup, - traits::{FromBytes, Ke1MessageLen, Ke2StateLen, KeyExchange, ToBytes}, + traits::{FromBytes, Ke1MessageLen, Ke1StateLen, Ke2StateLen, KeyExchange, ToBytes}, tripledh::NonceLen, }, keypair::{KeyPair, PrivateKey, PublicKey, SecretKey}, messages::{CredentialRequestLen, RegistrationUploadLen}, - serialization::{tokenize, Serialize}, + serialization::Serialize, slow_hash::SlowHash, CredentialFinalization, CredentialRequest, CredentialResponse, RegistrationRequest, RegistrationResponse, RegistrationUpload, }; -use alloc::vec::Vec; -use core::array::IntoIter; use core::marker::PhantomData; use core::ops::Add; use derive_where::DeriveWhere; -use digest::{Digest, FixedOutput}; +use digest::core_api::{BlockSizeUser, CoreProxy}; +use digest::Output; use generic_array::sequence::Concat; use generic_array::{ - typenum::{Sum, Unsigned, U2}, + typenum::{IsLess, Le, NonZero, Sum, Unsigned, U2, U256}, ArrayLength, GenericArray, }; use hkdf::{Hkdf, HkdfExtract}; use rand::{CryptoRng, RngCore}; use subtle::ConstantTimeEq; -use voprf::group::Group; +use voprf::Group; /////////////// // Constants // @@ -73,8 +72,12 @@ const STR_OPAQUE_DERIVE_KEY_PAIR: &[u8; 20] = b"OPAQUE-DeriveKeyPair"; pub struct ServerSetup< CS: CipherSuite, S: SecretKey = PrivateKey<::KeGroup>, -> { - oprf_seed: GenericArray::OutputSize>, +> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ + oprf_seed: Output, keypair: KeyPair, pub(crate) fake_keypair: KeyPair, } @@ -87,27 +90,42 @@ pub struct ServerSetup< voprf::NonVerifiableClient, voprf::BlindedElement, )] -pub struct ClientRegistration { +pub struct ClientRegistration +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ pub(crate) oprf_client: voprf::NonVerifiableClient, pub(crate) blinded_element: voprf::BlindedElement, } -impl_serialize_and_deserialize_for!(ClientRegistration; serde_::ser::Error::custom); +impl_serialize_and_deserialize_for!( + ClientRegistration + where + // ClientRegistration: KgSk + KgPk + ::ScalarLen: Add<::ElemLen>, + ClientRegistrationLen: ArrayLength, +); /// The state elements the server holds to record a registration #[derive(DeriveWhere)] #[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize(drop))] -pub struct ServerRegistration(RegistrationUpload); +pub struct ServerRegistration(RegistrationUpload) +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero; impl_serialize_and_deserialize_for!( ServerRegistration where // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength | Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload @@ -122,7 +140,12 @@ impl_serialize_and_deserialize_for!( >::KE1State, CredentialRequest, )] -pub struct ClientLogin { +pub struct ClientLogin +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ oprf_client: voprf::NonVerifiableClient, ke1_state: >::KE1State, credential_request: CredentialRequest, @@ -133,8 +156,12 @@ impl_serialize_and_deserialize_for!( where // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, - CredentialRequestLen: ArrayLength; - serde_::ser::Error::custom + CredentialRequestLen: ArrayLength, + // ClientLogin: KgSk + CredentialRequest + Ke1State + ::ScalarLen: Add>, + Sum<::ScalarLen, CredentialRequestLen>: + ArrayLength | Add>, + ClientLoginLen: ArrayLength, ); /// The state elements the server holds to record a login @@ -144,7 +171,12 @@ impl_serialize_and_deserialize_for!( Debug, Eq, Hash, PartialEq; >::KE2State, )] -pub struct ServerLogin { +pub struct ServerLogin +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ ke2_state: >::KE2State, #[derive_where(skip(Zeroize))] _cs: PhantomData, @@ -160,7 +192,12 @@ impl_serialize_and_deserialize_for!(ServerLogin); // Server Setup // ============ -impl ServerSetup> { +impl ServerSetup> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Generate a new instance of server setup pub fn new(rng: &mut R) -> Self { let keypair = KeyPair::generate_random(rng); @@ -169,11 +206,15 @@ impl ServerSetup> { } /// Length of [`ServerSetup`] in bytes for serialization. -#[allow(type_alias_bounds)] pub type ServerSetupLen> = - Sum::OutputSize, S::Len>, ::SkLen>; + Sum, S::Len>, ::SkLen>; -impl> ServerSetup { +impl> ServerSetup +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Create [`ServerSetup`] with the given keypair pub fn new_with_key( rng: &mut R, @@ -193,9 +234,8 @@ impl> ServerSetup { pub fn serialize(&self) -> GenericArray> where // ServerSetup: Hash + KeSk + KeSk - ::OutputSize: Add, - Sum<::OutputSize, S::Len>: - ArrayLength + Add<::SkLen>, + OutputSize: Add, + Sum, S::Len>: ArrayLength + Add<::SkLen>, ServerSetupLen: ArrayLength, { self.oprf_seed @@ -206,7 +246,7 @@ impl> ServerSetup { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result> { - let seed_len = ::OutputSize::USIZE; + let seed_len = OutputSize::::USIZE; let key_len = ::SkLen::USIZE; let checked_slice = check_slice_size(input, seed_len + key_len + key_len, "server_setup")?; @@ -227,39 +267,46 @@ impl> ServerSetup { // Registration // ============ -impl ClientRegistration { +pub(crate) type ClientRegistrationLen = + Sum<::ScalarLen, ::ElemLen>; + +impl ClientRegistration +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes - pub fn serialize(&self) -> Result, ProtocolError> { - Ok(chain!( - Serialize::::from(&self.oprf_client.serialize())?.iter(), - Serialize::::from(&self.blinded_element.serialize())?.iter(), - ) - .flatten() - .cloned() - .collect()) + pub fn serialize(&self) -> GenericArray> + where + // ClientRegistration: KgSk + KgPk + ::ScalarLen: Add<::ElemLen>, + ClientRegistrationLen: ArrayLength, + { + self.oprf_client + .serialize() + .concat(self.blinded_element.serialize()) } /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let (serialized_oprf_client, remainder) = tokenize(input, 2)?; - let (serialized_blinded_element, remainder) = tokenize(remainder, 2)?; - - if !remainder.is_empty() { - return Err(ProtocolError::SerializationError); - } + let client_len = ::ScalarLen::USIZE; + let element_len = ::ElemLen::USIZE; + let checked_slice = + check_slice_size(input, client_len + element_len, "client_registration")?; Ok(Self { - oprf_client: voprf::NonVerifiableClient::deserialize(serialized_oprf_client)?, - blinded_element: voprf::BlindedElement::deserialize(serialized_blinded_element)?, + oprf_client: voprf::NonVerifiableClient::deserialize(&checked_slice[..client_len])?, + blinded_element: voprf::BlindedElement::deserialize(&checked_slice[client_len..])?, }) } /// Only used for testing zeroize #[cfg(test)] - pub(crate) fn to_vec(&self) -> Vec { + pub(crate) fn to_vec(&self) -> std::vec::Vec { [ - self.oprf_client.serialize(), - self.blinded_element.serialize(), + self.oprf_client.serialize().to_vec(), + self.blinded_element.serialize().to_vec(), ] .concat() } @@ -287,6 +334,7 @@ impl ClientRegistration { pub fn finish( self, rng: &mut R, + password: &[u8], registration_response: RegistrationResponse, params: ClientRegistrationFinishParameters, ) -> Result, ProtocolError> { @@ -302,12 +350,13 @@ impl ClientRegistration { #[cfg_attr(not(test), allow(unused_variables))] let (randomized_pwd, randomized_pwd_hasher) = get_password_derived_key::( + password, self.oprf_client.clone(), registration_response.evaluation_element, params.slow_hash, )?; - let mut masking_key = GenericArray::<_, ::OutputSize>::default(); + let mut masking_key = Output::::default(); randomized_pwd_hasher .expand(STR_MASKING_KEY, &mut masking_key) .map_err(|_| InternalError::HkdfError)?; @@ -340,16 +389,21 @@ impl ClientRegistration { /// Length of [`ServerRegistration`] in bytes for serialization. pub type ServerRegistrationLen = RegistrationUploadLen; -impl ServerRegistration { +impl ServerRegistration +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes pub fn serialize(&self) -> GenericArray> where // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload @@ -375,7 +429,7 @@ impl ServerRegistration { )?; let server = voprf::NonVerifiableServer::new_with_key(&oprf_key)?; - let evaluate_result = server.evaluate(message.blinded_element, None)?; + let evaluate_result = server.evaluate(&message.blinded_element, None)?; Ok(ServerRegistrationStartResult { message: RegistrationResponse { @@ -405,55 +459,64 @@ impl ServerRegistration { // Login // ===== -impl ClientLogin { +pub(crate) type ClientLoginLen = + Sum::ScalarLen, CredentialRequestLen>, Ke1StateLen>; + +impl ClientLogin +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes - pub fn serialize(&self) -> Result, ProtocolError> + pub fn serialize(&self) -> GenericArray> where // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, CredentialRequestLen: ArrayLength, + // ClientLogin: KgSk + CredentialRequest + Ke1State + ::ScalarLen: Add>, + Sum<::ScalarLen, CredentialRequestLen>: + ArrayLength + Add>, + ClientLoginLen: ArrayLength, { - Ok(chain!( - Serialize::::from(&self.oprf_client.serialize())?.iter(), - Serialize::::from(&self.credential_request.serialize())?.iter(), - Serialize::::from(&self.ke1_state.to_bytes())?.iter(), - ) - .flatten() - .cloned() - .collect()) + self.oprf_client + .serialize() + .concat(self.credential_request.serialize()) + .concat(self.ke1_state.to_bytes()) } /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let (serialized_oprf_client, remainder) = tokenize(input, 2)?; - let (serialized_credential_request, remainder) = tokenize(remainder, 2)?; - let (ke1_state_bytes, remainder) = tokenize(remainder, 2)?; - - if !remainder.is_empty() { - return Err(ProtocolError::SerializationError); - } + let client_len = ::ScalarLen::USIZE; + let request_len = ::ElemLen::USIZE + Ke1MessageLen::::USIZE; + let state_len = Ke1StateLen::::USIZE; + let checked_slice = + check_slice_size(input, client_len + request_len + state_len, "client_login")?; let ke1_state = >::KE1State::from_bytes( - ke1_state_bytes, + &checked_slice[client_len + request_len..], )?; Ok(Self { - oprf_client: voprf::NonVerifiableClient::deserialize(serialized_oprf_client)?, + oprf_client: voprf::NonVerifiableClient::deserialize(&checked_slice[..client_len])?, + credential_request: CredentialRequest::deserialize( + &checked_slice[client_len..client_len + request_len], + )?, ke1_state, - credential_request: CredentialRequest::deserialize(serialized_credential_request)?, }) } /// Only used for testing zeroize #[cfg(test)] - pub(crate) fn to_vec(&self) -> Vec + pub(crate) fn to_vec(&self) -> std::vec::Vec where // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, CredentialRequestLen: ArrayLength, { [ - self.oprf_client.serialize(), + self.oprf_client.serialize().to_vec(), self.credential_request.serialize().to_vec(), self.ke1_state.to_bytes().to_vec(), ] @@ -461,7 +524,12 @@ impl ClientLogin { } } -impl ClientLogin { +impl ClientLogin +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Returns an initial "blinded" password request to send to the server, as well as a ClientLogin pub fn start( rng: &mut R, @@ -489,14 +557,14 @@ impl ClientLogin { /// the server pub fn finish( self, + password: &[u8], credential_response: CredentialResponse, params: ClientLoginFinishParameters, ) -> Result, ProtocolError> where // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { // Check if beta value from server is equal to alpha value from client @@ -511,12 +579,13 @@ impl ClientLogin { } let (_, randomized_pwd_hasher) = get_password_derived_key::( + password, self.oprf_client.clone(), credential_response.evaluation_element.clone(), params.slow_hash, )?; - let mut masking_key = GenericArray::<_, ::OutputSize>::default(); + let mut masking_key = Output::::default(); randomized_pwd_hasher .expand(STR_MASKING_KEY, &mut masking_key) .map_err(|_| InternalError::HkdfError)?; @@ -585,7 +654,12 @@ impl ClientLogin { } } -impl ServerLogin { +impl ServerLogin +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Serialization into bytes pub fn serialize(&self) -> GenericArray> { self.ke2_state.to_bytes() @@ -617,9 +691,8 @@ impl ServerLogin { ) -> Result, ProtocolError> where // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { let record = match password_file { @@ -669,7 +742,7 @@ impl ServerLogin { let server = voprf::NonVerifiableServer::new_with_key(&oprf_key) .map_err(|e| ProtocolError::into_custom(e.into()))?; let evaluate_result = server - .evaluate(credential_request.blinded_element, None) + .evaluate(&credential_request.blinded_element, None) .map_err(|e| ProtocolError::into_custom(e.into()))?; let evaluation_element = evaluate_result.message; @@ -748,14 +821,24 @@ pub struct Identifiers<'a> { /// Optional parameters for client registration finish #[derive(DeriveWhere)] #[derive_where(Clone, Default)] -pub struct ClientRegistrationFinishParameters<'i, 'h, CS: CipherSuite> { +pub struct ClientRegistrationFinishParameters<'i, 'h, CS: CipherSuite> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Specifying the identifiers idU and idS pub identifiers: Identifiers<'i>, /// Specifying a configuration for the slow hash pub slow_hash: Option<&'h CS::SlowHash>, } -impl<'i, 'h, CS: CipherSuite> ClientRegistrationFinishParameters<'i, 'h, CS> { +impl<'i, 'h, CS: CipherSuite> ClientRegistrationFinishParameters<'i, 'h, CS> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Create a new [`ClientRegistrationFinishParameters`] pub fn new(identifiers: Identifiers<'i>, slow_hash: Option<&'h CS::SlowHash>) -> Self { Self { @@ -768,7 +851,12 @@ impl<'i, 'h, CS: CipherSuite> ClientRegistrationFinishParameters<'i, 'h, CS> { /// Contains the fields that are returned by a client registration start #[derive(DeriveWhere)] #[derive_where(Clone)] -pub struct ClientRegistrationStartResult { +pub struct ClientRegistrationStartResult +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The registration request message to be sent to the server pub message: RegistrationRequest, /// The client state that must be persisted in order to complete registration @@ -778,11 +866,16 @@ pub struct ClientRegistrationStartResult { /// Contains the fields that are returned by a client registration finish #[derive(DeriveWhere)] #[derive_where(Clone)] -pub struct ClientRegistrationFinishResult { +pub struct ClientRegistrationFinishResult +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The registration upload message to be sent to the server pub message: RegistrationUpload, /// The export key output by client registration - pub export_key: GenericArray::OutputSize>, + pub export_key: Output, /// The server's static public key pub server_s_pk: PublicKey, /// Instance of the ClientRegistration, only used in tests for checking zeroize @@ -790,17 +883,22 @@ pub struct ClientRegistrationFinishResult { pub state: ClientRegistration, /// AuthKey, only used in tests #[cfg(test)] - pub auth_key: GenericArray::OutputSize>, + pub auth_key: Output, /// Password derived key, only used in tests #[cfg(test)] - pub randomized_pwd: GenericArray::OutputSize>, + pub randomized_pwd: Output, } /// Contains the fields that are returned by a server registration start. /// Note that there is no state output in this step #[derive(DeriveWhere)] #[derive_where(Clone)] -pub struct ServerRegistrationStartResult { +pub struct ServerRegistrationStartResult +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The registration resposne message to send to the client pub message: RegistrationResponse, /// OPRF key, only used in tests @@ -811,7 +909,12 @@ pub struct ServerRegistrationStartResult { /// Contains the fields that are returned by a client login start #[derive(DeriveWhere)] #[derive_where(Clone)] -pub struct ClientLoginStartResult { +pub struct ClientLoginStartResult +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The message to send to the server to begin the login protocol pub message: CredentialRequest, /// The state that the client must keep in order to complete the protocol @@ -821,7 +924,12 @@ pub struct ClientLoginStartResult { /// Optional parameters for client login finish #[derive(DeriveWhere)] #[derive_where(Clone, Default)] -pub struct ClientLoginFinishParameters<'c, 'i, 'h, CS: CipherSuite> { +pub struct ClientLoginFinishParameters<'c, 'i, 'h, CS: CipherSuite> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Specifying a context field that the server must agree on pub context: Option<&'c [u8]>, /// Specifying a user identifier and server identifier that will be matched against the server @@ -830,7 +938,12 @@ pub struct ClientLoginFinishParameters<'c, 'i, 'h, CS: CipherSuite> { pub slow_hash: Option<&'h CS::SlowHash>, } -impl<'c, 'i, 'h, CS: CipherSuite> ClientLoginFinishParameters<'c, 'i, 'h, CS> { +impl<'c, 'i, 'h, CS: CipherSuite> ClientLoginFinishParameters<'c, 'i, 'h, CS> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// Create a new [`ClientLoginFinishParameters`] pub fn new( context: Option<&'c [u8]>, @@ -848,13 +961,18 @@ impl<'c, 'i, 'h, CS: CipherSuite> ClientLoginFinishParameters<'c, 'i, 'h, CS> { /// Contains the fields that are returned by a client login finish #[derive(DeriveWhere)] #[derive_where(Clone)] -pub struct ClientLoginFinishResult { +pub struct ClientLoginFinishResult +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The message to send to the server to complete the protocol pub message: CredentialFinalization, /// The session key - pub session_key: GenericArray::OutputSize>, + pub session_key: Output, /// The client-side export key - pub export_key: GenericArray::OutputSize>, + pub export_key: Output, /// The server's static public key pub server_s_pk: PublicKey, /// Instance of the ClientLogin, only used in tests for checking zeroize @@ -862,10 +980,10 @@ pub struct ClientLoginFinishResult { pub state: ClientLogin, /// Handshake secret, only used in tests #[cfg(test)] - pub handshake_secret: GenericArray::OutputSize>, + pub handshake_secret: Output, /// Client MAC key, only used in tests #[cfg(test)] - pub client_mac_key: GenericArray::OutputSize>, + pub client_mac_key: Output, } /// Contains the fields that are returned by a server login finish @@ -873,9 +991,14 @@ pub struct ClientLoginFinishResult { #[derive_where(Clone)] #[cfg_attr(not(test), derive_where(Debug))] #[cfg_attr(test, derive_where(Debug; ServerLogin))] -pub struct ServerLoginFinishResult { +pub struct ServerLoginFinishResult +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The session key between client and server - pub session_key: GenericArray::OutputSize>, + pub session_key: Output, _cs: PhantomData, /// Instance of the ClientRegistration, only used in tests for checking zeroize #[cfg(test)] @@ -900,17 +1023,22 @@ pub struct ServerLoginStartParameters<'c, 'i> { >::KE2Message, >::KE2State, )] -pub struct ServerLoginStartResult { +pub struct ServerLoginStartResult +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ /// The message to send back to the client pub message: CredentialResponse, /// The state that the server must keep in order to finish the protocl pub state: ServerLogin, /// Handshake secret, only used in tests #[cfg(test)] - pub handshake_secret: GenericArray::OutputSize>, + pub handshake_secret: Output, /// Server MAC key, only used in tests #[cfg(test)] - pub server_mac_key: GenericArray::OutputSize>, + pub server_mac_key: Output, /// OPRF key, only used in tests #[cfg(test)] pub oprf_key: GenericArray::ScalarLen>, @@ -922,20 +1050,19 @@ pub struct ServerLoginStartResult { //////////////////////////////////////////////// // Helper functions - #[allow(clippy::type_complexity)] fn get_password_derived_key( + input: &[u8], oprf_client: voprf::NonVerifiableClient, evaluation_element: voprf::EvaluationElement, slow_hash: Option<&CS::SlowHash>, -) -> Result< - ( - GenericArray::OutputSize>, - Hkdf, - ), - ProtocolError, -> { - let oprf_output = oprf_client.finalize(evaluation_element, None)?; +) -> Result<(Output, Hkdf), ProtocolError> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ + let oprf_output = oprf_client.finalize(input, &evaluation_element, None)?; let hardened_output = if let Some(slow_hash) = slow_hash { slow_hash.hash(oprf_output.clone()) @@ -951,9 +1078,14 @@ fn get_password_derived_key( } fn oprf_key_from_seed( - oprf_seed: &GenericArray, + oprf_seed: &Output, credential_identifier: &[u8], -) -> Result, ProtocolError> { +) -> Result, ProtocolError> +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ let mut ikm = GenericArray::<_, G::ScalarLen>::default(); Hkdf::::from_prk(oprf_seed) .ok() @@ -963,7 +1095,7 @@ fn oprf_key_from_seed( }) .ok_or(InternalError::HkdfError)?; Ok(G::scalar_as_bytes(G::hash_to_scalar::( - Some(ikm.as_slice()), + [ikm.as_slice()], GenericArray::from(*STR_OPAQUE_DERIVE_KEY_PAIR), )?)) } @@ -971,23 +1103,31 @@ fn oprf_key_from_seed( #[derive(DeriveWhere)] #[derive_where(Clone)] #[derive_where(Debug, Eq, Hash, PartialEq)] -pub(crate) struct MaskedResponse { +pub(crate) struct MaskedResponse +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ pub(crate) nonce: GenericArray, - pub(crate) hash: GenericArray::OutputSize>, + pub(crate) hash: Output, pub(crate) pk: GenericArray::PkLen>, } -#[allow(type_alias_bounds)] pub(crate) type MaskedResponseLen = - Sum::OutputSize>, ::PkLen>; + Sum>, ::PkLen>; -impl MaskedResponse { +impl MaskedResponse +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ pub(crate) fn serialize(&self) -> GenericArray> where // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { self.nonce.concat(self.hash.clone()).concat(self.pk.clone()) @@ -995,7 +1135,7 @@ impl MaskedResponse { pub(crate) fn deserialize(bytes: &[u8]) -> Self { let nonce = NonceLen::USIZE; - let hash = nonce + ::OutputSize::USIZE; + let hash = nonce + OutputSize::::USIZE; let pk = hash + ::PkLen::USIZE; Self { @@ -1006,9 +1146,7 @@ impl MaskedResponse { } pub(crate) fn iter(&self) -> impl Iterator { - // MSRV: array `into_iter` isn't available in 1.51 - #[allow(deprecated)] - IntoIter::new([self.nonce.as_slice(), &self.hash, &self.pk]) + [self.nonce.as_slice(), &self.hash, &self.pk].into_iter() } } @@ -1019,10 +1157,13 @@ fn mask_response( envelope: &Envelope, ) -> Result, ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { let mut xor_pad = GenericArray::<_, MaskedResponseLen>::default(); @@ -1051,10 +1192,12 @@ fn unmask_response( masked_response: &MaskedResponse, ) -> Result<(PublicKey, Envelope), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { let mut xor_pad = GenericArray::<_, MaskedResponseLen>::default(); @@ -1086,12 +1229,12 @@ pub(crate) fn bytestrings_from_identifiers( server_s_pk: GenericArray, ) -> Result<(Serialize, Serialize), ProtocolError> { let client_identity = if let Some(client) = ids.client { - Serialize::::from(client)? + Serialize::::from(client)? } else { Serialize::::from_owned(client_s_pk)? }; let server_identity = if let Some(server) = ids.server { - Serialize::::from(server)? + Serialize::::from(server)? } else { Serialize::::from_owned(server_s_pk)? }; @@ -1106,12 +1249,14 @@ pub(crate) fn bytestrings_from_identifiers( fn blind( rng: &mut R, password: &[u8], -) -> Result< - voprf::NonVerifiableClientBlindResult, - voprf::errors::InternalError, -> { +) -> Result, voprf::Error> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ #[cfg(not(test))] - let result = voprf::NonVerifiableClient::blind(password.to_vec(), rng)?; + let result = voprf::NonVerifiableClient::blind(password, rng)?; #[cfg(test)] let result = { @@ -1127,7 +1272,7 @@ fn blind( true => (), } }; - voprf::NonVerifiableClient::deterministic_blind_unchecked(password.to_vec(), blind)? + voprf::NonVerifiableClient::deterministic_blind_unchecked(password, blind)? }; Ok(result) diff --git a/src/serialization/mod.rs b/src/serialization/mod.rs index 4e4af82..1107d58 100644 --- a/src/serialization/mod.rs +++ b/src/serialization/mod.rs @@ -20,23 +20,19 @@ pub(crate) fn i2osp>( ) -> Result, ProtocolError> { const SIZEOF_USIZE: usize = core::mem::size_of::(); - // Check if input >= 256^length + // Make sure input fits in output. if (SIZEOF_USIZE as u32 - input.leading_zeros() / 8) > L::U32 { return Err(ProtocolError::SerializationError); } - if L::USIZE <= SIZEOF_USIZE { - return Ok(GenericArray::clone_from_slice( - &input.to_be_bytes()[SIZEOF_USIZE - L::USIZE..], - )); - } - let mut output = GenericArray::default(); - output[L::USIZE - SIZEOF_USIZE..L::USIZE].copy_from_slice(&input.to_be_bytes()); + output[L::USIZE.saturating_sub(SIZEOF_USIZE)..] + .copy_from_slice(&input.to_be_bytes()[SIZEOF_USIZE.saturating_sub(L::USIZE)..]); Ok(output) } // Corresponds to the OS2IP() function from RFC8017 +#[cfg(test)] pub(crate) fn os2ip(input: &[u8]) -> Result { if input.len() > core::mem::size_of::() { return Err(ProtocolError::SerializationError); @@ -96,17 +92,17 @@ impl<'a, L1: ArrayLength, L2: ArrayLength, L3: ArrayLength> Serializ pub(crate) fn iter(&self) -> impl Iterator { // Some magic to make it output the same type in all branches. - Some(self.octet.as_slice()) + [self.octet.as_slice()] .into_iter() .chain(match &self.input { - Input::Owned(bytes) => Some(bytes.as_slice()), - Input::Borrowed(bytes) => Some(*bytes), - Input::Label(_) => None, + Input::Owned(bytes) => [bytes.as_slice()], + Input::Borrowed(bytes) => [*bytes], + Input::Label((iter, _)) => [iter[0]], }) .chain(if let Input::Label((iter, _)) = &self.input { - Some(iter[0]).into_iter().chain(Some(iter[1]).into_iter()) + Some(iter[1]) } else { - None.into_iter().chain(None) + None }) } } @@ -132,24 +128,6 @@ impl<'a, L1: ArrayLength, L2: ArrayLength> Serialize<'a, L1, L2, U2> { } } -// Tokenizes an input of the format I2OSP(len(input), max_bytes) || input, outputting -// (input, remainder) -pub(crate) fn tokenize(input: &[u8], size_bytes: usize) -> Result<(&[u8], &[u8]), ProtocolError> { - if size_bytes > core::mem::size_of::() || input.len() < size_bytes { - return Err(ProtocolError::SerializationError); - } - - let size = os2ip(&input[..size_bytes])?; - if size_bytes + size > input.len() { - return Err(ProtocolError::SerializationError); - } - - Ok(( - &input[size_bytes..size_bytes + size], - &input[size_bytes + size..], - )) -} - pub(crate) trait UpdateExt { fn chain_iter<'a>(self, iter: impl Iterator) -> Self; } @@ -178,17 +156,6 @@ impl MacExt for T { } } -/// The purpose of this macro is to simplify [`concat`](alloc::slice::Concat::concat)ing -/// slices into an [`Iterator`] to avoid allocation -macro_rules! chain { - ( - $item1:expr, - $($item2:expr),+$(,)? - ) => { - $item1$(.chain($item2))+ - }; -} - #[cfg(test)] mod tests; diff --git a/src/serialization/tests.rs b/src/serialization/tests.rs index 5507703..99fe58f 100755 --- a/src/serialization/tests.rs +++ b/src/serialization/tests.rs @@ -9,9 +9,10 @@ use crate::{ ciphersuite::CipherSuite, envelope::{Envelope, EnvelopeLen, InnerEnvelopeMode}, errors::*, + hash::{OutputSize, ProxyHash}, key_exchange::{ group::KeGroup, - traits::{Ke1MessageLen, Ke2MessageLen}, + traits::{Ke1MessageLen, Ke1StateLen, Ke2MessageLen}, }, key_exchange::{ traits::{FromBytes, KeyExchange, ToBytes}, @@ -19,26 +20,23 @@ use crate::{ }, keypair::KeyPair, messages::CredentialResponseWithoutKeLen, - opaque::MaskedResponseLen, - serialization::{i2osp, os2ip, Serialize}, + opaque::{ClientLoginLen, ClientRegistrationLen, MaskedResponseLen}, + serialization::{i2osp, os2ip}, *, }; -#[cfg(test)] -use alloc::vec; -#[cfg(test)] -use alloc::vec::Vec; use core::ops::Add; +use std::vec; +use std::vec::Vec; -use digest::FixedOutput; +use digest::core_api::{BlockSizeUser, CoreProxy}; +use digest::Output; use generic_array::{ - typenum::{Sum, Unsigned, U2}, - ArrayLength, GenericArray, + typenum::{IsLess, Le, NonZero, Sum, Unsigned, U256}, + ArrayLength, }; use proptest::{collection::vec, prelude::*}; use rand::{rngs::OsRng, RngCore}; -use voprf::group::Group; - -use sha2::Digest; +use voprf::Group; #[cfg(feature = "ristretto255")] struct Ristretto255; @@ -62,7 +60,12 @@ impl CipherSuite for P256 { type SlowHash = crate::slow_hash::NoOpHash; } -fn random_point() -> CS::KeGroup { +fn random_point() -> CS::KeGroup +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ let mut rng = OsRng; let sk = CS::KeGroup::random_sk(&mut rng); CS::KeGroup::public_key(&sk) @@ -70,24 +73,32 @@ fn random_point() -> CS::KeGroup { #[test] fn client_registration_roundtrip() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + // ClientRegistration: KgSk + KgPk + ::ScalarLen: Add<::ElemLen>, + ClientRegistrationLen: ArrayLength, + { let pw = b"hunter2"; let mut rng = OsRng; let blind_result = - &voprf::NonVerifiableClient::::blind(pw.to_vec(), &mut rng)?; + &voprf::NonVerifiableClient::::blind(pw, &mut rng)?; - let bytes: Vec = chain!( - Serialize::::from(&blind_result.state.serialize())?.iter(), - Serialize::::from(&blind_result.message.serialize())?.iter(), - ) - .flatten() - .cloned() - .collect(); + let bytes: Vec = blind_result + .state + .serialize() + .iter() + .chain(blind_result.message.serialize().iter()) + .cloned() + .collect(); let reg = ClientRegistration::::deserialize(&bytes)?; - let reg_bytes = reg.serialize()?; - assert_eq!(reg_bytes, bytes); + let reg_bytes = reg.serialize(); + assert_eq!(*reg_bytes, bytes); Ok(()) } @@ -103,12 +114,15 @@ fn client_registration_roundtrip() -> Result<(), ProtocolError> { fn server_registration_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload @@ -116,15 +130,14 @@ fn server_registration_roundtrip() -> Result<(), ProtocolError> { // If we don't have envelope and client_pk, the server registration just // contains the prf key let mut rng = OsRng; - let mut masking_key = GenericArray::<_, ::OutputSize>::default(); + let mut masking_key = Output::::default(); rng.fill_bytes(&mut masking_key); // Construct a mock envelope let mut mock_envelope_bytes = Vec::new(); mock_envelope_bytes.extend_from_slice(&[0; NonceLen::USIZE]); // empty nonce // mock_envelope_bytes.extend_from_slice(&ciphertext); // ciphertext which is an encrypted private key - mock_envelope_bytes - .extend_from_slice(&GenericArray::<_, ::OutputSize>::default()); // length-MAC_SIZE hmac + mock_envelope_bytes.extend_from_slice(&Output::::default()); // length-MAC_SIZE hmac let mock_client_kp = KeyPair::::generate_random(&mut rng); // serialization order: oprf_key, public key, envelope @@ -148,7 +161,12 @@ fn server_registration_roundtrip() -> Result<(), ProtocolError> { #[test] fn registration_request_roundtrip() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let pt = random_point::(); let pt_bytes = pt.to_arr().to_vec(); @@ -166,7 +184,7 @@ fn registration_request_roundtrip() -> Result<(), ProtocolError> { assert!(matches!( RegistrationRequest::::deserialize(&identity_bytes), Err(ProtocolError::LibraryError(InternalError::OprfError( - voprf::errors::InternalError::PointError, + voprf::Error::PointError, ))) )); @@ -185,6 +203,9 @@ fn registration_request_roundtrip() -> Result<(), ProtocolError> { fn registration_response_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // RegistrationResponse: KgPk + KePk ::ElemLen: Add<::PkLen>, RegistrationResponseLen: ArrayLength, @@ -212,7 +233,7 @@ fn registration_response_roundtrip() -> Result<(), ProtocolError> { &[identity_bytes, pubkey_bytes.to_vec()].concat() ), Err(ProtocolError::LibraryError(InternalError::OprfError( - voprf::errors::InternalError::PointError, + voprf::Error::PointError, ))) )); @@ -231,12 +252,15 @@ fn registration_response_roundtrip() -> Result<(), ProtocolError> { fn registration_upload_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, { @@ -249,7 +273,7 @@ fn registration_upload_roundtrip() -> Result<(), ProtocolError> { let mut nonce = [0u8; NonceLen::USIZE]; rng.fill_bytes(&mut nonce); - let mut masking_key = GenericArray::<_, ::OutputSize>::default(); + let mut masking_key = Output::::default(); rng.fill_bytes(&mut masking_key); let randomized_pwd_hasher = hkdf::Hkdf::new(None, &key); @@ -257,7 +281,7 @@ fn registration_upload_roundtrip() -> Result<(), ProtocolError> { let (envelope, _, _) = Envelope::::seal_raw( randomized_pwd_hasher, nonce.into(), - Some(pubkey_bytes.as_slice()).into_iter(), + [pubkey_bytes.as_slice()].into_iter(), InnerEnvelopeMode::Internal, ) .unwrap(); @@ -287,6 +311,9 @@ fn registration_upload_roundtrip() -> Result<(), ProtocolError> { fn credential_request_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, CredentialRequestLen: ArrayLength, @@ -316,7 +343,7 @@ fn credential_request_roundtrip() -> Result<(), ProtocolError> { assert!(matches!( CredentialRequest::::deserialize(&[identity_bytes, ke1m.to_vec()].concat()), Err(ProtocolError::LibraryError(InternalError::OprfError( - voprf::errors::InternalError::PointError, + voprf::Error::PointError, ))) )); @@ -335,15 +362,17 @@ fn credential_request_roundtrip() -> Result<(), ProtocolError> { fn credential_response_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse ::ElemLen: Add, Sum<::ElemLen, NonceLen>: ArrayLength + Add>, CredentialResponseWithoutKeLen: ArrayLength, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message CredentialResponseWithoutKeLen: Add>, @@ -362,7 +391,7 @@ fn credential_response_roundtrip() -> Result<(), ProtocolError> { rng.fill_bytes(&mut masked_response); let server_e_kp = KeyPair::::generate_random(&mut rng); - let mut mac = GenericArray::<_, ::OutputSize>::default(); + let mut mac = Output::::default(); rng.fill_bytes(&mut mac); let mut server_nonce = [0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); @@ -394,7 +423,7 @@ fn credential_response_roundtrip() -> Result<(), ProtocolError> { .concat() ), Err(ProtocolError::LibraryError(InternalError::OprfError( - voprf::errors::InternalError::PointError, + voprf::Error::PointError, ))) )); @@ -411,9 +440,14 @@ fn credential_response_roundtrip() -> Result<(), ProtocolError> { #[test] fn credential_finalization_roundtrip() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let mut rng = OsRng; - let mut mac = GenericArray::<_, ::OutputSize>::default(); + let mut mac = Output::::default(); rng.fill_bytes(&mut mac); let input = mac; @@ -437,9 +471,17 @@ fn credential_finalization_roundtrip() -> Result<(), ProtocolError> { fn client_login_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, CredentialRequestLen: ArrayLength, + // ClientLogin: KgSk + CredentialRequest + Ke1State + ::ScalarLen: Add>, + Sum<::ScalarLen, CredentialRequestLen>: + ArrayLength + Add>, + ClientLoginLen: ArrayLength, { let pw = b"hunter2"; let mut rng = OsRng; @@ -455,7 +497,7 @@ fn client_login_roundtrip() -> Result<(), ProtocolError> { .concat(); let blind_result = - voprf::NonVerifiableClient::::blind(pw.to_vec(), &mut rng)?; + voprf::NonVerifiableClient::::blind(pw, &mut rng)?; let credential_request = CredentialRequest:: { blinded_element: blind_result.message, @@ -465,17 +507,17 @@ fn client_login_roundtrip() -> Result<(), ProtocolError> { )?, }; - let bytes: Vec = chain!( - Serialize::::from(&blind_result.state.serialize())?.iter(), - Serialize::::from(&credential_request.serialize())?.iter(), - Serialize::::from(&l1_data)?.iter(), - ) - .flatten() - .cloned() - .collect(); + let bytes: Vec = blind_result + .state + .serialize() + .iter() + .chain(credential_request.serialize().iter()) + .chain(l1_data.iter()) + .cloned() + .collect(); let reg = ClientLogin::::deserialize(&bytes)?; - let reg_bytes = reg.serialize()?; - assert_eq!(reg_bytes, bytes); + let reg_bytes = reg.serialize(); + assert_eq!(*reg_bytes, bytes); Ok(()) } @@ -489,7 +531,12 @@ fn client_login_roundtrip() -> Result<(), ProtocolError> { #[test] fn ke1_message_roundtrip() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let mut rng = OsRng; let client_e_kp = KeyPair::::generate_random(&mut rng); @@ -515,11 +562,16 @@ fn ke1_message_roundtrip() -> Result<(), ProtocolError> { #[test] fn ke2_message_roundtrip() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let mut rng = OsRng; let server_e_kp = KeyPair::::generate_random(&mut rng); - let mut mac = GenericArray::<_, ::OutputSize>::default(); + let mut mac = Output::::default(); rng.fill_bytes(&mut mac); let mut server_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); @@ -544,9 +596,14 @@ fn ke2_message_roundtrip() -> Result<(), ProtocolError> { #[test] fn ke3_message_roundtrip() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let mut rng = OsRng; - let mut mac = GenericArray::<_, ::OutputSize>::default(); + let mut mac = Output::::default(); rng.fill_bytes(&mut mac); let ke3m: Vec = [mac].concat(); diff --git a/src/slow_hash.rs b/src/slow_hash.rs index eb8c071..fa9b083 100644 --- a/src/slow_hash.rs +++ b/src/slow_hash.rs @@ -7,39 +7,49 @@ //! Trait specifying a slow hashing function -use crate::{errors::InternalError, hash::Hash}; -use digest::Digest; -use generic_array::GenericArray; +use crate::{ + errors::InternalError, + hash::{Hash, ProxyHash}, +}; +use digest::core_api::BlockSizeUser; +use digest::Output; +use generic_array::typenum::{IsLess, Le, NonZero, U256}; /// Used for the slow hashing function in OPAQUE -pub trait SlowHash: Default { +pub trait SlowHash: Default +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ /// Computes the slow hashing function - fn hash( - &self, - input: GenericArray::OutputSize>, - ) -> Result::OutputSize>, InternalError>; + fn hash(&self, input: Output) -> Result, InternalError>; } /// A no-op hash which simply returns its input #[derive(Default)] pub struct NoOpHash; -impl SlowHash for NoOpHash { - fn hash( - &self, - input: GenericArray::OutputSize>, - ) -> Result::OutputSize>, InternalError> { +impl SlowHash for NoOpHash +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + fn hash(&self, input: Output) -> Result, InternalError> { Ok(input) } } #[cfg(feature = "slow-hash")] -impl SlowHash for argon2::Argon2<'_> { - fn hash( - &self, - input: GenericArray::OutputSize>, - ) -> Result::OutputSize>, InternalError> { - let mut output = GenericArray::default(); +impl SlowHash for argon2::Argon2<'_> +where + D::Core: ProxyHash, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + fn hash(&self, input: Output) -> Result, InternalError> { + let mut output = Output::::default(); self.hash_password_into(&input, &[0; argon2::MIN_SALT_LEN], &mut output) .map_err(|_| InternalError::SlowHashError)?; Ok(output) diff --git a/src/tests/full_test.rs b/src/tests/full_test.rs index fb7ba79..26d03c6 100755 --- a/src/tests/full_test.rs +++ b/src/tests/full_test.rs @@ -11,9 +11,10 @@ use crate::{ ciphersuite::CipherSuite, envelope::EnvelopeLen, errors::*, + hash::{OutputSize, ProxyHash}, key_exchange::{ group::KeGroup, - traits::{Ke1MessageLen, Ke2MessageLen}, + traits::{Ke1MessageLen, Ke1StateLen, Ke2MessageLen}, tripledh::{NonceLen, TripleDH}, }, messages::{ @@ -25,16 +26,18 @@ use crate::{ tests::mock_rng::CycleRng, *, }; -use alloc::string::ToString; -use alloc::vec::Vec; use core::ops::Add; -use digest::{Digest, FixedOutput}; -use generic_array::typenum::{Sum, Unsigned}; -use generic_array::{ArrayLength, GenericArray}; +use digest::core_api::{BlockSizeUser, CoreProxy}; +use digest::Output; +use generic_array::typenum::{IsLess, Le, NonZero, Sum, Unsigned, U256}; +use generic_array::ArrayLength; use rand::rngs::OsRng; use serde_json::Value; +use std::string::{String, ToString}; +use std::vec::Vec; +use std::{format, println, vec}; use subtle::ConstantTimeEq; -use voprf::group::Group; +use voprf::Group; use zeroize::Zeroize; // Tests @@ -126,152 +129,152 @@ static STR_CREDENTIAL_IDENTIFIER: &str = "credential_identifier"; #[cfg(feature = "ristretto255")] static TEST_VECTOR_RISTRETTO255: &str = r#" { - "client_s_pk": "181bbea01a5e444390c4b335f8bcb9a846a1c60042669ce6d731af4587960c06", - "client_s_sk": "2f21529b9fb27c8c12770b765dc36750c4a51c5ccaf2f83d0182504a85a22c0b", - "client_e_pk": "58a16b672e100b18069d0716715a9a8d9a643954bb24c0887e46d542eab9e417", - "client_e_sk": "c1a4db9d650ce1700e05fbd472d30c13e0a4c6926b114e7ca11e2e9f397c5005", - "server_s_pk": "dc8c66b6dcf4731836a0cdb336985c77a6321ffb75db6bb1aef20974c141dd3c", - "server_s_sk": "410ef173f972994eeabb2cb39fd5db907e39a1abd6b36c9f514ab903d9d16305", - "server_e_pk": "68630597c4593cb8158f398ab6ff956a1d87232be4300be1f96a6860663d9461", - "server_e_sk": "155452c6b08b889b31d5a810925136adfb2d363eee4ccaed0ef15b594fb88b04", - "fake_sk": "b009e67b83c418f0ae271b8790d6c5e06ea3874fa5a9e66752b5ebdbec953b04", + "client_s_pk": "8cc7c9eb1d0f5803fd02f13ffc91175bd2a4ea0395913c7d6414431a05dda94c", + "client_s_sk": "b30044efeb2c90127e35389c2d025dccbe90c03c102ea38388e362320c6e570f", + "client_e_pk": "5ac74ef87ac50c960c56fdcd46daf12ef7d88739c8654937e7a4d8996d60ed22", + "client_e_sk": "1d78d5ffe9b3ad5bb467da13232805cbbdff0473ed47da7738f7a05d2f35c603", + "server_s_pk": "34dacc7158463c3d29aa780baab28624b1c71df0468e134bde085cdc8f4e941b", + "server_s_sk": "966ee3f6f3ece48d37ca5394f113dad2fc3afe2923fc20f769a185de1bea9905", + "server_e_pk": "387e1dff8d671ac91665bb0268478ec518d2db28d0cf71041696e65c14c04562", + "server_e_sk": "5f7bed95ef1efd306e3144f30381593a85adb98e632552b0e87644d46cbcc002", + "fake_sk": "a85ac8f4eee6bb688c3ae7d7b6d995da2038645ba34ceadf8467e56d175bc008", "credential_identifier": "637265644964656e746966696572", "id_u": "696455", "id_s": "696453", "password": "70617373776f7264", - "blinding_factor": "544ce97b02dff0201282a44cf73171a62a76e2a113d40dce8950f31bf4339403", - "oprf_seed": "f929fa161a065bec163bea6dbab6d6eccd960666951fc7fd3da7cf2b6baf20a2763598aba89a4e5bcaa57096c66cfded26d683e07ab1a3b37a7c82706dfaee81", - "masking_nonce": "4c0099b7067c7c243ed804def0fd490babd577abcd7b05a1f24a05d2d1cc344e079a75936ed36b89a3056661a2dc981a6628edde6a86da2714cce71659d84f8d", - "envelope_nonce": "9888ba54ffc1e1be5deb23a2efa5432f318f9a17d681d1273e909ca3bf1b2fea", - "client_nonce": "652a39daf155cc9b5a005b67951f19c2ccdf4667cf7bcd39f941a87565ed4c29", - "server_nonce": "5e2f19069ea9791d6b346b676d8d8aaf45536148ca0357a595f330c7aed107d2", + "blinding_factor": "ae7bd2be7bcbeafcf4c26f92e4ab37b174c93126cdb0b6321a511c92f3cecb0f", + "oprf_seed": "4f31cd5f5ddbc39da5d354b0d5bdae1c0f57aa549aaca4eba8138156c387473ed050329b97631d9fca895c60afb1855e30f2426043cd2dd242707bf664082c87", + "masking_nonce": "97a321a4a2946fcacbae9d80d78ac1c06d9f7e39e426b367be57398957938bbc5a18264ee75b6976b2abc8fccc702010196cb1c90fbfcab60363acc3d503c968", + "envelope_nonce": "4745c52d41faa7c697d3fb3374c087966b8e44da7519e0f7c561a0ee0f3a6180", + "client_nonce": "781fbdffc567af01253fb0d53839842a7255fd36371dde1b05979691c0bca067", + "server_nonce": "1f5fc6d4f55c092245bdb150c2db4189ad8fca9c8df5218a0876cb11c8114a39", "context": "636f6e74657874", - "registration_request": "f05048bb39f3f5a3a414f50254c425b36f842162a630bf73456df453351cb33d", - "registration_response": "2c6f5ba3de9af2719529e9a993097e8c0ecd5110a24471414e4225950189cc46dc8c66b6dcf4731836a0cdb336985c77a6321ffb75db6bb1aef20974c141dd3c", - "registration_upload": "08a51d9973140af4f911f235d4910e9536503157bfaffefaeaa11f69d723cc54d35d9ae50d6a0a7ab38614e571a81821cfbfec36ed9fd46e397e173252d02ff623287035e190153e9fb88509da1c225765bb200ed59249cbfd6201656d1672db2f21529b9fb27c8c12770b765dc36750c4a51c5ccaf2f83d0182504a85a22c0b19e07582aea6c5e782b15ff18f6188203f54ea62dfb1efb77d641f030b86062c9f0d1bc3c39b7f824fe81df456c702ea4fa084eba803fea7e5a80d2284c2ff15", - "credential_request": "f05048bb39f3f5a3a414f50254c425b36f842162a630bf73456df453351cb33d652a39daf155cc9b5a005b67951f19c2ccdf4667cf7bcd39f941a87565ed4c2958a16b672e100b18069d0716715a9a8d9a643954bb24c0887e46d542eab9e417", - "credential_response": "2c6f5ba3de9af2719529e9a993097e8c0ecd5110a24471414e4225950189cc464c0099b7067c7c243ed804def0fd490babd577abcd7b05a1f24a05d2d1cc344e4100aea1aa461bed485d0e441c275d0d04388e1b6b739379cd9ebabe6a53ca025375487ea73cc17ea884fb3fd91d05a8970628459ab7996e9e20aacdc613a669a687c95479814b866c43cde2ca225f43a44035ba921b5986877589013acd8eba3f4e00bd4c5e83756651c5faa0319487e4b80bcedfef82b9e46c3cace5b4aa8e155452c6b08b889b31d5a810925136adfb2d363eee4ccaed0ef15b594fb88b04605c82fb3bb14125d8274619e5ceef90151b6309610aa35c2c0a004337c44b50162d27726ed40aca064e88cff1413d7098f81b16567919ca8d9c425b8b3445684e2ad7e7d8d14475c2ca1ace56a5949199fb836f9f343d46994098955bb9f129", - "credential_finalization": "e13284ada3e78eed48047934115ce7e6c2cdff0c3012e9ba2d423759c4000ddf11ecd186dd7f0740ee3413ff0d253e2437eced56f3717e45c071b170d12db1dd", - "client_registration_state": "0028544ce97b02dff0201282a44cf73171a62a76e2a113d40dce8950f31bf433940370617373776f72640020f05048bb39f3f5a3a414f50254c425b36f842162a630bf73456df453351cb33d", - "client_login_state": "0028544ce97b02dff0201282a44cf73171a62a76e2a113d40dce8950f31bf433940370617373776f72640060f05048bb39f3f5a3a414f50254c425b36f842162a630bf73456df453351cb33d652a39daf155cc9b5a005b67951f19c2ccdf4667cf7bcd39f941a87565ed4c2958a16b672e100b18069d0716715a9a8d9a643954bb24c0887e46d542eab9e4170040c1a4db9d650ce1700e05fbd472d30c13e0a4c6926b114e7ca11e2e9f397c5005652a39daf155cc9b5a005b67951f19c2ccdf4667cf7bcd39f941a87565ed4c29", - "server_login_state": "2a009e5881454a2b42fb8c039762f78828c5b4ba7008d2e57b16ffdc937ee846b56461f9cda751b2a1c2b03793d72d5ca8c482adf8009880779323e64e12eb1d4c0cf45ec665be918cb9d655f9eca974494f0f4c0f6e714c6ddcca37b547c122cf7419984e123fa4c7981212e5171b01bfd6f8ac88e7964c8da4a88b5df4f2c85da5318465cef76fbddd389ff36be66c693cfc6feecbcf43bf16a22c97de8430e824b2812449934d13fb666b24de78a007f1fc06064304b0abfae3fc5caba7f6", - "password_file": "08a51d9973140af4f911f235d4910e9536503157bfaffefaeaa11f69d723cc54d35d9ae50d6a0a7ab38614e571a81821cfbfec36ed9fd46e397e173252d02ff623287035e190153e9fb88509da1c225765bb200ed59249cbfd6201656d1672db2f21529b9fb27c8c12770b765dc36750c4a51c5ccaf2f83d0182504a85a22c0b19e07582aea6c5e782b15ff18f6188203f54ea62dfb1efb77d641f030b86062c9f0d1bc3c39b7f824fe81df456c702ea4fa084eba803fea7e5a80d2284c2ff15", - "export_key": "ea8d1f871a3c8ad5d2a7a2d647e020105a33f8b8534055c56ab4bae2b8467d22806968159f918d9c31098602790fcad3e5969f1d8ff0b90b48c26b4132877ed4", - "session_key": "5da5318465cef76fbddd389ff36be66c693cfc6feecbcf43bf16a22c97de8430e824b2812449934d13fb666b24de78a007f1fc06064304b0abfae3fc5caba7f6" + "registration_request": "083b7dfada0e53c78f9d32ddcb88ec50144cf361fd202d73581eeeb944113715", + "registration_response": "760fdf28216493a9a9b9f268c33d7a22f059f16ab6f3b9559f3165874453414834dacc7158463c3d29aa780baab28624b1c71df0468e134bde085cdc8f4e941b", + "registration_upload": "5c60129a5003992493977306a309188b373fb806a9f0668279ca21806081cc7d21a180fba338aa1477038a9b41623dc5feb69445f9f48e342a63eb7a45b6522fa4f1555d1729fcb15fb2d1e761c7583c0b5ce704c032e3804aa3c2ca16e6bd26b30044efeb2c90127e35389c2d025dccbe90c03c102ea38388e362320c6e570f4992b64df766073034f49e77eddf22f6a6418408cc29a11357871e9c41663ee71958443f36fa81c3ff2d487dcfcdd28695e2f0dfbb84201e968a8f9111a68a28", + "credential_request": "083b7dfada0e53c78f9d32ddcb88ec50144cf361fd202d73581eeeb944113715781fbdffc567af01253fb0d53839842a7255fd36371dde1b05979691c0bca0675ac74ef87ac50c960c56fdcd46daf12ef7d88739c8654937e7a4d8996d60ed22", + "credential_response": "760fdf28216493a9a9b9f268c33d7a22f059f16ab6f3b9559f3165874453414897a321a4a2946fcacbae9d80d78ac1c06d9f7e39e426b367be57398957938bbcb095ee31bf57672fab06716b53c69cbfefc2907064a8fbf284cd02adda3add3c43706e059634ea372ecb2718103ca2fc83a7b060194a804dc2b4339ee5d5d228d38d21e16c61424bbc3ff8fd599e5f1e928935983ee3b0226a1beeb182777a0c0053859554b5bde0f9f52f5a8c82831e866891cfa1907f2906b55d0432f0c30b5f7bed95ef1efd306e3144f30381593a85adb98e632552b0e87644d46cbcc002d023f69a86ba2b2ec3d6e75350f2ac1f780a899e6eb658a41dd773c440dc2b4a4f4281f8a049d3ed483db43274d30e89220e693e4027259ab1b037ff543935d973772ca255fc128d114c338100c49a86906c8deed99fd49a9c481beeb689154d", + "credential_finalization": "90861a832ee7aa11c865d37c011443fb0bc66852484d41f7ee712ceb4a61a580b368c08b7a3d1b133f63a54db5368b47e28e59740697336d9855da3b72d26e83", + "client_registration_state": "ae7bd2be7bcbeafcf4c26f92e4ab37b174c93126cdb0b6321a511c92f3cecb0f083b7dfada0e53c78f9d32ddcb88ec50144cf361fd202d73581eeeb944113715", + "client_login_state": "ae7bd2be7bcbeafcf4c26f92e4ab37b174c93126cdb0b6321a511c92f3cecb0f083b7dfada0e53c78f9d32ddcb88ec50144cf361fd202d73581eeeb944113715781fbdffc567af01253fb0d53839842a7255fd36371dde1b05979691c0bca0675ac74ef87ac50c960c56fdcd46daf12ef7d88739c8654937e7a4d8996d60ed221d78d5ffe9b3ad5bb467da13232805cbbdff0473ed47da7738f7a05d2f35c603781fbdffc567af01253fb0d53839842a7255fd36371dde1b05979691c0bca067", + "server_login_state": "877f235cde56f884c971e137dbfec8dc6fbb00656cbf6e20d032f6fba598ed0ad6ff7fc2d52b76e57eb72037c6976491ee045472b35204513b909cafc3ac5e3bac4fab5f4dce3c8de85481d899ee644fd8af2c30b8756746ef97bdfb82d9a081bad64d83fa726404f7af042b49ba79049e6ed825e40180ac08407ff18d44f11d828933d78f17e6360881ec80e8696507892dd1072958b8e1566ea2a68b0ed227593a19f2c5266d5c456338d7142126543bfb38bfe7209e84778eda944774832b", + "password_file": "5c60129a5003992493977306a309188b373fb806a9f0668279ca21806081cc7d21a180fba338aa1477038a9b41623dc5feb69445f9f48e342a63eb7a45b6522fa4f1555d1729fcb15fb2d1e761c7583c0b5ce704c032e3804aa3c2ca16e6bd26b30044efeb2c90127e35389c2d025dccbe90c03c102ea38388e362320c6e570f4992b64df766073034f49e77eddf22f6a6418408cc29a11357871e9c41663ee71958443f36fa81c3ff2d487dcfcdd28695e2f0dfbb84201e968a8f9111a68a28", + "export_key": "c37b2ce98f5822c578236405dba3b17d42e3ae452ec2bb667442bbfc39774827bfeff20ec0c98c4b2d131880425455f0e12cd09b5112dc6e8609eb3be07bb396", + "session_key": "828933d78f17e6360881ec80e8696507892dd1072958b8e1566ea2a68b0ed227593a19f2c5266d5c456338d7142126543bfb38bfe7209e84778eda944774832b" } "#; #[cfg(feature = "p256")] static TEST_VECTOR_P256: &str = r#" { - "client_s_pk": "022bb70342affe88f4f3c5d5fc4991bfc1f4758651d59d50c25815ffc4d13eeae3", - "client_s_sk": "ee7beaaed8110b155efac3af2bb97a7a45262fa5702de4721c90ebcfb098b596", - "client_e_pk": "02faf2a785a7de0d59c240b235ab7559820f682a7930fb546ecabddee2de091043", - "client_e_sk": "755577ce43627c5201af2bd35bc17bb7a4c9945acbadbb08962a0236a860ce80", - "server_s_pk": "025e6c524abf252eadf812d3ef46dd7afbeb2f65d76269d1a1288fb0be82b378cb", - "server_s_sk": "5f044f77db085dd5ebeb0ffbe69166057c586719f5ff277a4488b3202c720258", - "server_e_pk": "039e7fc9dcf8e9f50405d228a70c1d9bf5eb283b7e156774125b876819d0349630", - "server_e_sk": "5158264e39bd1234ab785701b47d697b07db92eb4f5dc0f206607edf69f66476", - "fake_sk": "402eaf9bf6d4b1501a2eae8ebb76d4970060decd43944c4bd601602c23a23093", + "client_s_pk": "02ec5dd688a3aa66022860d4bfed2dcb01a5da07a0b4ff0c84d9f8749bd478c293", + "client_s_sk": "4982f91037e2e498ea3b7fe8f72c35d00a9b952c8ce4fb0563a49071d599390c", + "client_e_pk": "027f8c859ded40011655cd5314f5dc3b42ed95c11da3ad181a70d911fadb818415", + "client_e_sk": "efeb2242f4068b651e29917611a295033e8369ee14c1091678f0327383997289", + "server_s_pk": "0231a120b62158db8b182afba15361f32870c17d09675fb2b751fab99a55b7f29b", + "server_s_sk": "04a0d9eae979c3e0a7be44d723fdabafd4a2c2bd0d2bef4d1134a61358e1d3d6", + "server_e_pk": "022ef1078479c8d69e08d94d682aca2c63a293193ef8d45d0508cc13d64d5dc3b4", + "server_e_sk": "304ada96918e021ec1595981ac41711853bd7a271bf3aa6c01e57ebdd18b50ed", + "fake_sk": "668017c4eb69093ca24e877fb258df8de386a136af9a08fb5c3c52c52267a03c", "credential_identifier": "637265644964656e746966696572", "id_u": "696455", "id_s": "696453", "password": "70617373776f7264", - "blinding_factor": "a383673cc3fc95652d0fd6fdfaaff8c2db97c0cb55706499a7e719a28f93ba49", - "oprf_seed": "84618864bc307f9c178cb5c156865094c8f3737e6ea4e46dc965ddbd4b2332f2", - "masking_nonce": "ec5bb47a34e050136fb97a513ddf182ccc498ffb7d70d94954cc013db934c2716f35c5a1adb5c220194bbb1e8159bbfbcabeb7d94215476bdf29e5dad3919b2c", - "envelope_nonce": "a9a9de9d77fae996ffa597928b12c83ff44e56b2e7d4f79dd561132800d63a2c", - "client_nonce": "51710b892007ef555ffd08452d9f9078165c2e7fd3695ad8020d74a8c20bb8b1", - "server_nonce": "68f4bc84db8af9940f41e8e91a5d39800e1eacdecd124918d24dc5eb8d5ed840", + "blinding_factor": "7c4a996eaac89d9cea984623277a142b52b63c6546ef426227922dec19d00a87", + "oprf_seed": "cdeef0e45c5c592bcc00d9ac8f094d43463165f886c4102f5a293ef8aa319de8", + "masking_nonce": "1d8e692fc6911170cfa00dbe665fa0d5db76a672245d111432b2fe35733d04f86b3d1ba79b08430b7fcad140a0d3067bcb2dd90fb3c3376cfc50660477454ae4", + "envelope_nonce": "18774499e68269ff9cc98e6b74438d00378b11886e93b34dfe61fb0912be6faa", + "client_nonce": "4a66273ed0c375274d59eb5d29f2f579c282dce9853401c9c7bdefe4018ed016", + "server_nonce": "e11586209869eb4ac351ebc8c1e348a7f7bdd4cccf747b8ccd6b7028a57a1692", "context": "636f6e74657874", - "registration_request": "0397d002bed42dfd7a104348c29e82c0bab8a5871846d8c6159e511d3c681fc2be", - "registration_response": "0357c5ca3794429f3111026c79925ffa597c7e518ac787ed49fe152d083d07c846025e6c524abf252eadf812d3ef46dd7afbeb2f65d76269d1a1288fb0be82b378cb", - "registration_upload": "03dd5bbddab150cf7cd793d6702741e529ee13ab4ce4cfad731dd77fc13c2310e5d82ca5e29fa03deff3ed1d8eb1353389b02a78bd48fa256915314dac55cf5e74ee7beaaed8110b155efac3af2bb97a7a45262fa5702de4721c90ebcfb098b5964788cdaf2a92a5a161a819c2aa84985f5a8ea6fbedf01c87ddaa8be23fc16721", - "credential_request": "0397d002bed42dfd7a104348c29e82c0bab8a5871846d8c6159e511d3c681fc2be51710b892007ef555ffd08452d9f9078165c2e7fd3695ad8020d74a8c20bb8b102faf2a785a7de0d59c240b235ab7559820f682a7930fb546ecabddee2de091043", - "credential_response": "0357c5ca3794429f3111026c79925ffa597c7e518ac787ed49fe152d083d07c846ec5bb47a34e050136fb97a513ddf182ccc498ffb7d70d94954cc013db934c27117a3467e180aa4144edd4122e53e2f9fe4d1c1363796e5820d92489e94c5fcabda33f5e886cfee0da967b28cc2a06674cf5d050125ac1136a44284520fcde7f7de6af0ab5f26f57d682c5d389298d5ebd38e7ca7f8bf5456ed0ac9f9ac6f4b7cbe5158264e39bd1234ab785701b47d697b07db92eb4f5dc0f206607edf69f66476039cb032462240ab63f406935a398ef593655ed0617147a952a249ca81bfda7d4ad872b9829967987a74514454b1ee3776debcae819c526ac33f838a81edb234b3", - "credential_finalization": "35395199a2e317c5f08f55f67f9f5565d1d0c856572876b1b4e447925a36eb60", - "client_registration_state": "0028a383673cc3fc95652d0fd6fdfaaff8c2db97c0cb55706499a7e719a28f93ba4970617373776f726400210397d002bed42dfd7a104348c29e82c0bab8a5871846d8c6159e511d3c681fc2be", - "client_login_state": "0028a383673cc3fc95652d0fd6fdfaaff8c2db97c0cb55706499a7e719a28f93ba4970617373776f726400620397d002bed42dfd7a104348c29e82c0bab8a5871846d8c6159e511d3c681fc2be51710b892007ef555ffd08452d9f9078165c2e7fd3695ad8020d74a8c20bb8b102faf2a785a7de0d59c240b235ab7559820f682a7930fb546ecabddee2de0910430040755577ce43627c5201af2bd35bc17bb7a4c9945acbadbb08962a0236a860ce8051710b892007ef555ffd08452d9f9078165c2e7fd3695ad8020d74a8c20bb8b1", - "server_login_state": "5c2ec839d40694328ed6133cc12b8da7ec4300589849eb193eb673d35e4645c8bce86cbd880012967dae7c0f1ac2a90a4d6ea9f3ee5c521c77a20600de4528ee89699ffdb9e8ba62442184bd4a696c6c5832801a425446869aefa2544260d618", - "password_file": "03dd5bbddab150cf7cd793d6702741e529ee13ab4ce4cfad731dd77fc13c2310e5d82ca5e29fa03deff3ed1d8eb1353389b02a78bd48fa256915314dac55cf5e74ee7beaaed8110b155efac3af2bb97a7a45262fa5702de4721c90ebcfb098b5964788cdaf2a92a5a161a819c2aa84985f5a8ea6fbedf01c87ddaa8be23fc16721", - "export_key": "35a93c215dc618dc3acbacc08d16e4879bf2054349facf2a33bc061dee57d787", - "session_key": "89699ffdb9e8ba62442184bd4a696c6c5832801a425446869aefa2544260d618" + "registration_request": "0240132c056e840d76432376499866bc24cbcc421352f97876e3db730eaf93c9a3", + "registration_response": "02aaf5d179cbd839043f1a5bb0b9d548240f83ba04fdf20bde2c4eb6c8cbd9af190231a120b62158db8b182afba15361f32870c17d09675fb2b751fab99a55b7f29b", + "registration_upload": "02d4231d770ef9ae965843a1675ad74199326c45903ba01740fb78802b3c513a94dadfe6d48822c9afb0180a8c153d05ec8165f12a65c5a4cdc4dd3319d1771d014982f91037e2e498ea3b7fe8f72c35d00a9b952c8ce4fb0563a49071d599390c13dd1bc302ed8244f467ae4efeffed774664d64a23e3be0526ca1a97bd0e184d", + "credential_request": "0240132c056e840d76432376499866bc24cbcc421352f97876e3db730eaf93c9a34a66273ed0c375274d59eb5d29f2f579c282dce9853401c9c7bdefe4018ed016027f8c859ded40011655cd5314f5dc3b42ed95c11da3ad181a70d911fadb818415", + "credential_response": "02aaf5d179cbd839043f1a5bb0b9d548240f83ba04fdf20bde2c4eb6c8cbd9af191d8e692fc6911170cfa00dbe665fa0d5db76a672245d111432b2fe35733d04f82b04c06b790ba4255130b98aff3a2f1fd6a0527cd9c8013b21eaf416292ce31f7f0cc1265563c461b5b201321c9aff0e33ebcbb3c378d44abe339070ee98d9c4273424602fe6defccedf46622f024f9d43569cb168ffde5f83ce2627e4b3033502304ada96918e021ec1595981ac41711853bd7a271bf3aa6c01e57ebdd18b50ed03a2fc14b586b9875732238ef1c8964ca168781c3002a0dd1b301aa692525cb86023db579c0d130a7272e9e43f0ae71cc585146f0c547f4d903b0e85fb5c855dc0", + "credential_finalization": "d721a8860a39f2f0b454a1721c3edef13bd9d2d1dc850624b4375e9824ab04ce", + "client_registration_state": "7c4a996eaac89d9cea984623277a142b52b63c6546ef426227922dec19d00a870240132c056e840d76432376499866bc24cbcc421352f97876e3db730eaf93c9a3", + "client_login_state": "7c4a996eaac89d9cea984623277a142b52b63c6546ef426227922dec19d00a870240132c056e840d76432376499866bc24cbcc421352f97876e3db730eaf93c9a34a66273ed0c375274d59eb5d29f2f579c282dce9853401c9c7bdefe4018ed016027f8c859ded40011655cd5314f5dc3b42ed95c11da3ad181a70d911fadb818415efeb2242f4068b651e29917611a295033e8369ee14c1091678f03273839972894a66273ed0c375274d59eb5d29f2f579c282dce9853401c9c7bdefe4018ed016", + "server_login_state": "b652d371e96e1b4afc79137d6f6fbdb7c98a254f2547f3fab2423ea2213a188c2884cb33441cb38a5d0d63e3d914de117781df0573022dd326766effb07e3cce5b812234056fefc56980a25a8d0a2614cd638594fae2b25cd17b456f2046c724", + "password_file": "02d4231d770ef9ae965843a1675ad74199326c45903ba01740fb78802b3c513a94dadfe6d48822c9afb0180a8c153d05ec8165f12a65c5a4cdc4dd3319d1771d014982f91037e2e498ea3b7fe8f72c35d00a9b952c8ce4fb0563a49071d599390c13dd1bc302ed8244f467ae4efeffed774664d64a23e3be0526ca1a97bd0e184d", + "export_key": "bcb1ed54d1baebf8c0ee5542623b1867cd3f9257a67fac4a456af55a9fd9e02a", + "session_key": "5b812234056fefc56980a25a8d0a2614cd638594fae2b25cd17b456f2046c724" } "#; #[cfg(all(feature = "x25519", feature = "ristretto255"))] static TEST_VECTOR_X25519_RISTRETTO255: &str = r#" { - "client_s_pk": "9b1f31c4e1a456d140ea5ae0f683c13785b4ecf473019aca643461afa09ccf1b", - "client_s_sk": "88e61aca2e4715cbbfa2bc3058c9ff388fc9c5a89178624d28ff14ce232e495c", - "client_e_pk": "3e532c63ccb8aabb87b1a724eda76b94083d7cb15174acda91635245618cde3d", - "client_e_sk": "18e9a925e2a1dd150f20322783a935bdfccb488478c6befcc31cce1a27643164", - "server_s_pk": "afe934c6742742e4f1389e42722ce080bb4c4963b1eeaeb8829ea22a11162941", - "server_s_sk": "f0f1348721d891985a3a92236fab57593fc3d997a649c6ce8858e8c20d7c1944", - "server_e_pk": "9a579563f40948693645f490ee3fb0b7ec3fd5de1331858fe95927f71a59a971", - "server_e_sk": "b81c82d7219bf318b75160dd010e96e83e0e080709c61edfbce206d6ec101a4a", - "fake_sk": "90f850aae07d8365e8d28d31ff87bbef1d50c9928c49a5b4ec7aabd4d69ddf75", + "client_s_pk": "d6ea34b61fa4625c1197f8f9fd51bc7023d4dfb0e17a95cf0ec38488ffff072c", + "client_s_sk": "f8fe7d4c525bd238c501c78a7b6ab26e076bb22c6b409ca08e34875ee4055850", + "client_e_pk": "7b0d1002539befa86f0cdf2a281f538842ec685bad21e9057a92390846ca0047", + "client_e_sk": "30e51bf7c5734fd3d1465b20affb65dc342f06513df999822832aa464aa29c5a", + "server_s_pk": "b6791c7cad7775b6cbc0bfa580319a1de159981771c59b0b86afeeff2767365a", + "server_s_sk": "68bfdb4e00e93059fb35e90db641ae1ef7af0fc8a7e013e2990431cf4c708563", + "server_e_pk": "c68d13eacc23578e731d78d2ccc37e2ff8e7cfdac3f76ee54d9ae40dd1167325", + "server_e_sk": "68b6d213f11d303e61929d299ca2424947e136d5a56b1400dda6286eaf5e4278", + "fake_sk": "c8f71d7e7864a25ee4e786744c5059ca268b7cf7a7610b4b3d763f368fae6972", "credential_identifier": "637265644964656e746966696572", "id_u": "696455", "id_s": "696453", "password": "70617373776f7264", - "blinding_factor": "5aa31e7d500431691fa3eb16a8a2e416b769ec3df66ace2c199e6b1cfb8a7e0e", - "oprf_seed": "ee0813a196ccc90a12de74c2d680eed39d6f6f16e55012881b32b4c02367f205fa5d7374a6c7119b28a586d59e9ea45760c011a3a81f064f07f80ffa23155e77", - "masking_nonce": "e3a3aecff193e9fbdd6677aeb1078bbf6d78f1893fd6f7acd77e9e05c4d6b35f9b267571d52e74a5b159e5ff55f93f31fa278e549802eb36b66f1ec8b77aa3be", - "envelope_nonce": "e2bd93bfcae01cc59e5e0d928923002682a291577b6e0e214c3a67c1ba94fd15", - "client_nonce": "e130bdb7b59020cd43a39fc588d5f05d33967c48b3e2a87488788897470797d5", - "server_nonce": "f1238020af1207007652c734b023758168c2156cc81b76a4f628f30a042e248f", + "blinding_factor": "fa0bbeb200bef1802f3317c0e6b92590d9431fb6f5cb7f579d0865950172e40f", + "oprf_seed": "8bbe6e550d125d9169342b5683b085be3aee7e6414fe2a4f6db2aa3493b16a9b75f109725d6d92c13f3f2814dec17f83e2fd20cf8b922ca1d928e8bf476f8154", + "masking_nonce": "885aa518b13d78757415f8839e1505a4ae8b5f04b6904ce9aff6de6d156d94756f3cb40352bbdafe521da49bf9a57bcde3597114161b023cfbf3b79051d2ee0d", + "envelope_nonce": "e5c5bb34123bb9b08eb961c6f3a94c6b627f1c5bcd3527d46a1652f662e078ac", + "client_nonce": "7fb4b8f81eefe57a8b1cf5d75465d557e04b21ed7800356713ecc63b0ebbfca5", + "server_nonce": "9e3f8ceb7174fdd7ceb2f1e37d4cd483e28e18fa60457416d2d5c468ae7501e7", "context": "636f6e74657874", - "registration_request": "9ef8b4a7817e4932f4e9837dd54b31ce9209cad61d7ea4003283158e5566620d", - "registration_response": "823eb375fcea47b3b1023848dc7b159ea4b9925f725a45f9e7da0f28c04f717eafe934c6742742e4f1389e42722ce080bb4c4963b1eeaeb8829ea22a11162941", - "registration_upload": "fe576ba51ba994ef0cac45a5fd55f663b2fcb9377d5ea1141d24f6c1a840b71890bf61e8066f25e3ea4148a685aaa2345cfdf3cd9157765c104659fcf695cb76b43f34a46ca41f5e78ae4ac857d98c6f105902305e695bcdec10dc4eda526fac88e61aca2e4715cbbfa2bc3058c9ff388fc9c5a89178624d28ff14ce232e495c90ea3a5efe3b34d84610f458759a7864eed0773290f7a5e5115eef6e5a81164f6e6fc5d026bcbfe55195dfdaa55b13b3d7f177ab8e5e318ffcd7d2ac5daf42c4", - "credential_request": "9ef8b4a7817e4932f4e9837dd54b31ce9209cad61d7ea4003283158e5566620de130bdb7b59020cd43a39fc588d5f05d33967c48b3e2a87488788897470797d53e532c63ccb8aabb87b1a724eda76b94083d7cb15174acda91635245618cde3d", - "credential_response": "823eb375fcea47b3b1023848dc7b159ea4b9925f725a45f9e7da0f28c04f717ee3a3aecff193e9fbdd6677aeb1078bbf6d78f1893fd6f7acd77e9e05c4d6b35fc05b4023afa48dba2a9c78abfb9c93353be3ce2adabe0d4cc4f69d9c0b635cc2e5b14ccec2a9bbabb4ad3f1591a3ac3c92dd989322ad7753e7f5834186a67c94ab65c6a446dcf06f13cf5ef0502f265c3be9e03770c54fe2cee1486cddbf292fa0f44b6173faefe0c093a7797bee2b04927c009f3653b42c3319bbb817920fbdb81c82d7219bf318b75160dd010e96e83e0e080709c61edfbce206d6ec101a4ae21bc06da818572e3a7e77f0eb74bbf7375379771dd7ada27c0b9bdd584f5f142eb61b7fb2c5f7d164597ec148f74a6a168ec0d93b06fb45d48d0a0c3e92e1da80cfe439fccde489c74b801de4401fadf4dcbd61cfe559ad2cf38e83662e2b06", - "credential_finalization": "fd18bc8aa8d789e6d954f962b52cb700296e88efd3a26f0761ff3e367d12b94ef187b2cc250519a2193fbd3c78247d3e0121aacdcdc5b22dcc818cd964c25754", - "client_registration_state": "00285aa31e7d500431691fa3eb16a8a2e416b769ec3df66ace2c199e6b1cfb8a7e0e70617373776f726400209ef8b4a7817e4932f4e9837dd54b31ce9209cad61d7ea4003283158e5566620d", - "client_login_state": "00285aa31e7d500431691fa3eb16a8a2e416b769ec3df66ace2c199e6b1cfb8a7e0e70617373776f726400609ef8b4a7817e4932f4e9837dd54b31ce9209cad61d7ea4003283158e5566620de130bdb7b59020cd43a39fc588d5f05d33967c48b3e2a87488788897470797d53e532c63ccb8aabb87b1a724eda76b94083d7cb15174acda91635245618cde3d004018e9a925e2a1dd150f20322783a935bdfccb488478c6befcc31cce1a27643164e130bdb7b59020cd43a39fc588d5f05d33967c48b3e2a87488788897470797d5", - "server_login_state": "b8bb1a1ff45040bf016aeab52aceec195109233f4c0e2589d4370658bb07f1d57f65d5e3007d94ed36d974c298f21184041c08c3298c9d16fa33591c19b07b45bdaaaee9c95f286dc4ce250b684bf3c5248ca0382f682d9eddeb5bf8fa16488696f7df7dec0d5090c57153aa1b3da588469ca6be7dc25954147ad3c08367f1bb2d2e6bd1a311eb2f3960b80a72e77158fc7b072c85f134695735ffed8206d465029c3ce886fee4665e05dfca5ef778dfe851bc31a8980dae67f15672d8e3f1dd", - "password_file": "fe576ba51ba994ef0cac45a5fd55f663b2fcb9377d5ea1141d24f6c1a840b71890bf61e8066f25e3ea4148a685aaa2345cfdf3cd9157765c104659fcf695cb76b43f34a46ca41f5e78ae4ac857d98c6f105902305e695bcdec10dc4eda526fac88e61aca2e4715cbbfa2bc3058c9ff388fc9c5a89178624d28ff14ce232e495c90ea3a5efe3b34d84610f458759a7864eed0773290f7a5e5115eef6e5a81164f6e6fc5d026bcbfe55195dfdaa55b13b3d7f177ab8e5e318ffcd7d2ac5daf42c4", - "export_key": "aafb0c3bc3694314180212233e811fa44cd35896420d3f65c3696e305c177fca6850bb1b36ed5b6fa3fdca9483dd2013ad30bb84f2a94979fc1fec2e461c1515", - "session_key": "2d2e6bd1a311eb2f3960b80a72e77158fc7b072c85f134695735ffed8206d465029c3ce886fee4665e05dfca5ef778dfe851bc31a8980dae67f15672d8e3f1dd" + "registration_request": "8eda5caa002e6574e677636eeba5967ec25505a125ea12d9857c0d8c3beb3551", + "registration_response": "ecf14ba8fb208a8d5b263170ffd84a9d21751810f52e539938ed22e71f66cb02b6791c7cad7775b6cbc0bfa580319a1de159981771c59b0b86afeeff2767365a", + "registration_upload": "020689ce9ffba0f198d9e63e23902ff1600656fdd604aa47c289d5d073cc472354e891e7c4f89058fd270813d320e0cb97a745722eb8038eec062e5aed5e6b40b88148d43e68b7f457c352c3b6523e0bc79795f651487d007574cbaf7dba317ff8fe7d4c525bd238c501c78a7b6ab26e076bb22c6b409ca08e34875ee4055850ea0fcb59720fdb42fcbddbccbaed60a0aec01d72403c63075468e8a03c9efc25206776154291cbce05d7567a82a10d8303f991b8689643c5727b1886c478a9b8", + "credential_request": "8eda5caa002e6574e677636eeba5967ec25505a125ea12d9857c0d8c3beb35517fb4b8f81eefe57a8b1cf5d75465d557e04b21ed7800356713ecc63b0ebbfca57b0d1002539befa86f0cdf2a281f538842ec685bad21e9057a92390846ca0047", + "credential_response": "ecf14ba8fb208a8d5b263170ffd84a9d21751810f52e539938ed22e71f66cb02885aa518b13d78757415f8839e1505a4ae8b5f04b6904ce9aff6de6d156d94756060ede0b8a8d061eaa376b4578fd39ec064f9f36c7a0602894690da72727b427148a2970ce50d06d93ed74dde1143f7d092f19541e8738c509dd5d34f4411d753959bc295083bc96a0b6e1d9a12a369c83fc2a50fab84276f83a2a63e5d5ba6dbb0b23752b7819c238123f0e69cbccc777fa6c35484608f324a3c30b307ad6068b6d213f11d303e61929d299ca2424947e136d5a56b1400dda6286eaf5e4278549bc184dd7a99b0749dfb1acb8ca862b649567d04b056c0530755d453e4c466d5728608562883eea4c922c313455999720cbbf3c6511d3666365132e39c1b6f094d05e73a75e15fb0869661337c3569fcfca75a9373d8fac9ff29c61be49a0d", + "credential_finalization": "6061b34bc847481034908047ded2b7e08450793091f96b9a425e4e4e24e65810596b2556e1ea1ae57e3f6bf234ba33fc393fe4fa98de984760df870a454fcdc9", + "client_registration_state": "fa0bbeb200bef1802f3317c0e6b92590d9431fb6f5cb7f579d0865950172e40f8eda5caa002e6574e677636eeba5967ec25505a125ea12d9857c0d8c3beb3551", + "client_login_state": "fa0bbeb200bef1802f3317c0e6b92590d9431fb6f5cb7f579d0865950172e40f8eda5caa002e6574e677636eeba5967ec25505a125ea12d9857c0d8c3beb35517fb4b8f81eefe57a8b1cf5d75465d557e04b21ed7800356713ecc63b0ebbfca57b0d1002539befa86f0cdf2a281f538842ec685bad21e9057a92390846ca004730e51bf7c5734fd3d1465b20affb65dc342f06513df999822832aa464aa29c5a7fb4b8f81eefe57a8b1cf5d75465d557e04b21ed7800356713ecc63b0ebbfca5", + "server_login_state": "d58815ef0bd83afafea536fe17c23f5292a5484d5748e7164b678bb4edbbfd99a31fc1b8e78ce8aab0908db29832e2c9644b4af4e3a167ab9a4f5e82c0a068eb8df23068244e4c7256c48abb28bc02529c3fbc2217c042fcc7f54e50f1516dde8f9f25c694e34604c9bea4b94090c3c911c22db5c74a79abbecf0354dc8d475575d17a1f85b7efdc2dd8b6e2fa9529bfe49d7cfa2563451fe6b9d5cd7344377c3730e197b550030c012b01466b142c9022b869fe5ea7c59412e5b6685db19997", + "password_file": "020689ce9ffba0f198d9e63e23902ff1600656fdd604aa47c289d5d073cc472354e891e7c4f89058fd270813d320e0cb97a745722eb8038eec062e5aed5e6b40b88148d43e68b7f457c352c3b6523e0bc79795f651487d007574cbaf7dba317ff8fe7d4c525bd238c501c78a7b6ab26e076bb22c6b409ca08e34875ee4055850ea0fcb59720fdb42fcbddbccbaed60a0aec01d72403c63075468e8a03c9efc25206776154291cbce05d7567a82a10d8303f991b8689643c5727b1886c478a9b8", + "export_key": "0527421cb5c31aeba8fddff1af3a673e94cbd7af57999eaed47e23ea3562d68362416d69afb3bcf450db76b4fea504d5d065e0a104d9a1848f20e64ff04f3cfd", + "session_key": "75d17a1f85b7efdc2dd8b6e2fa9529bfe49d7cfa2563451fe6b9d5cd7344377c3730e197b550030c012b01466b142c9022b869fe5ea7c59412e5b6685db19997" } "#; #[cfg(all(feature = "x25519", feature = "p256"))] static TEST_VECTOR_X25519_P256: &str = r#" { - "client_s_pk": "515850c2fb8fcf90378ba5baa2e5b05fd5244f90f49e4a4e8ded4553a696835a", - "client_s_sk": "2894850bbca99009c3a50e648011a57edda65bf88177197fff52378bde705878", - "client_e_pk": "8570fc35b68cf59e9c2d3d08a2452e9eaa9089b6d4cbee4053aedcd8eb4d3555", - "client_e_sk": "9001cb4337b57ca2a72e1a837ab72c5ee6f41348a4c77b5720a3fc6cd6f75561", - "server_s_pk": "583ef921ee685fe1a9d25492ed7221bf429dd8f3093cd78bf3de4b4822f11b56", - "server_s_sk": "f8c0872b11bebf21c83b300dedf222340c034a9831a3d21feaf7cb51c6f7805a", - "server_e_pk": "303d1d7ad0d6d466ee5a98a1407b1a05a891511cbdaa38695c63f9fb47a61c6a", - "server_e_sk": "c8ffba68071b11cabaae1f28bc5c816132dd2e1fc2d11ecf6286855f76e4b37f", - "fake_sk": "48aecca7847d09a5ba8ea1243d9a3527c16dc79852fd04eeb93083ef52e8f075", + "client_s_pk": "ee6282a908e24291fcd1e7ce0a6fc244cf9b6371889e31a908d1919cdd756776", + "client_s_sk": "785f65307f77f78cc4b20565a42c1954a30763d881528749f376b90a13ca2b73", + "client_e_pk": "c6e0310d186d3c869b384418a6574cd9fff826e3a91ac46d05ce0ab56e25b978", + "client_e_sk": "e889400a32d355cd203d6a1ee195a787217db28075de794d0c39ca29c44f1776", + "server_s_pk": "1c840f081ecaa88b6eff81536d28b3220cc7101e6e90b998461cc80ead285808", + "server_s_sk": "10138ce9d5660b1b23aaf520e1ec948bd1f318b571356aa3f9becf3db34daf7a", + "server_e_pk": "152d47f6ac15e7c2c11f29bd513d182db4eed09ef3974a6e4438b72ec9aa2d0c", + "server_e_sk": "589db8b32e957d97134b10f8b2fa107b908f88eb2a4620f2ae25d61107bf9e6f", + "fake_sk": "088a857c0f23ea4896cb067420a5264e8ea22f13d6b471cc4518cdf520de817b", "credential_identifier": "637265644964656e746966696572", "id_u": "696455", "id_s": "696453", "password": "70617373776f7264", - "blinding_factor": "0e2fe2a1a193da4c6739a1265cd9a2df297ac7312f2770afa9c8d6de37ead907", - "oprf_seed": "048e281519d6d7548d03dccc8684d91e22025fc573e076c1c5885839cf42b8ad", - "masking_nonce": "59ded518f0215d108d4b0ba8a34911c1d4178318816ab964e67d8315c6803c1fe403684d504bdcbbde77fb90d3824390dd7d3f04b9203636c23399ffdacf9e62", - "envelope_nonce": "119acabcfa0d808d0ce82b7d3de2193deb5b0e71dc111d456c8ad4ee32fa7306", - "client_nonce": "9e34fd4a6900a3dcb0bfcf8b6df799871bb0a11178ee0d7dad6c0fb74921f302", - "server_nonce": "d62fbaec787648da7900d89fd007822e79407016d98a62333239892d49375a7d", + "blinding_factor": "40b461844231f2f890fc68aa0da838e25f40af01ec1b212fdf6bad07db170757", + "oprf_seed": "b25a0265e824656034824b935d49d7f844d26acf1a7d8c6c40d635543a2e6d33", + "masking_nonce": "005cf982b3ddbb28ee252d729c83c4b9d74a54ac72f25325f7f21824530649fbf165383559cce8a4734d6fcd56e45f866828008d3d4c56dd57659c80bc3e094f", + "envelope_nonce": "0c9954390a2bac0bf09c083a2152bfce397281e7a5408c08b0b18d56c0ec686c", + "client_nonce": "b389ed08bf4bfbf895ea6706c3d967b5ec7c4af96c207ebe816c50b9615ab06e", + "server_nonce": "a920b7dbb1607caea2a3d7577531fb30173d0123a2353cf4151bea9e71caaab2", "context": "636f6e74657874", - "registration_request": "03cc7a78723430cbfa6f337c25d3ad586e5d20e2f8e9c2126a28c08f76493088f7", - "registration_response": "0247b0d70311fb623ee21236536cb5df543100b44abaacc3bf2627cca77ee80185583ef921ee685fe1a9d25492ed7221bf429dd8f3093cd78bf3de4b4822f11b56", - "registration_upload": "e3969807b3496f7a07afa9f2288e706f71125bbe1bc659e40f9c83eb3e428e430d9dc301ff73d3b95bf0fceab01ce66dc4c2f84dbea61526e6c1ee7c4adb8c912894850bbca99009c3a50e648011a57edda65bf88177197fff52378bde705878a6ede2210483b94ff0ca04b1eda09b841a735170f79d1674aacfbd3550bba356", - "credential_request": "03cc7a78723430cbfa6f337c25d3ad586e5d20e2f8e9c2126a28c08f76493088f79e34fd4a6900a3dcb0bfcf8b6df799871bb0a11178ee0d7dad6c0fb74921f3028570fc35b68cf59e9c2d3d08a2452e9eaa9089b6d4cbee4053aedcd8eb4d3555", - "credential_response": "0247b0d70311fb623ee21236536cb5df543100b44abaacc3bf2627cca77ee8018559ded518f0215d108d4b0ba8a34911c1d4178318816ab964e67d8315c6803c1fd513bf2f3cea8283a7ba98973d1f160213586e42a5e6ae5d6ac73f5deebc609e7481e84cd4f61b844db7457a5dc18121a0a6d8776d4e29d98cdf4892c18189439a3a7692a2be2910e0ba9fd8f7a28c10733ff781c4e36dabe86a819d35ce4745c8ffba68071b11cabaae1f28bc5c816132dd2e1fc2d11ecf6286855f76e4b37f2c2ffc6b9b2f6342231d5d3a9ea28023f543c7ccf3852413e411ab011b0c06523163f82d3cf9abb5e8517d0d47ef13071ac1001c6a1e39f2cbfe7440257d4db2", - "credential_finalization": "de00d81621b2394b201a0c9d731b6b96e9cdab29fedb14c749c51029446da74a", - "client_registration_state": "00280e2fe2a1a193da4c6739a1265cd9a2df297ac7312f2770afa9c8d6de37ead90770617373776f7264002103cc7a78723430cbfa6f337c25d3ad586e5d20e2f8e9c2126a28c08f76493088f7", - "client_login_state": "00280e2fe2a1a193da4c6739a1265cd9a2df297ac7312f2770afa9c8d6de37ead90770617373776f7264006103cc7a78723430cbfa6f337c25d3ad586e5d20e2f8e9c2126a28c08f76493088f79e34fd4a6900a3dcb0bfcf8b6df799871bb0a11178ee0d7dad6c0fb74921f3028570fc35b68cf59e9c2d3d08a2452e9eaa9089b6d4cbee4053aedcd8eb4d355500409001cb4337b57ca2a72e1a837ab72c5ee6f41348a4c77b5720a3fc6cd6f755619e34fd4a6900a3dcb0bfcf8b6df799871bb0a11178ee0d7dad6c0fb74921f302", - "server_login_state": "df965dfa291f57cfead138a43802798c270c481a35b2fbf3d6d0c1860ab73a8e5f9874bbe6a329b51e9015a551a7b49809de26f74ba2ff496782d94ae01468fc63b02cf977a143ebe1a1231a28367d1be1065d5c0273f959e1e97a08a74bf6f1", - "password_file": "e3969807b3496f7a07afa9f2288e706f71125bbe1bc659e40f9c83eb3e428e430d9dc301ff73d3b95bf0fceab01ce66dc4c2f84dbea61526e6c1ee7c4adb8c912894850bbca99009c3a50e648011a57edda65bf88177197fff52378bde705878a6ede2210483b94ff0ca04b1eda09b841a735170f79d1674aacfbd3550bba356", - "export_key": "6168b6786fbded7a888067b58e62035f0f1940c0fb6448fc69093d62597f365a", - "session_key": "63b02cf977a143ebe1a1231a28367d1be1065d5c0273f959e1e97a08a74bf6f1" + "registration_request": "02c1f758572663d7bb1fa5dbc8cf426b867a9936bc741e9acc8a31b18bf0e5bd33", + "registration_response": "03068d5d3fe0d6b3361c2c728b85dce104df42d3d11c2079392ab894ace50ff4001c840f081ecaa88b6eff81536d28b3220cc7101e6e90b998461cc80ead285808", + "registration_upload": "f49b790e8f2e36ca511957263868d1ee897b2936b1ae4922ac2ad0b7a0e38f3c2606360d0008b6ed33e4ca48d31f3992875445e3a53f42e4eee661aad96e2c50785f65307f77f78cc4b20565a42c1954a30763d881528749f376b90a13ca2b7374d474b4232682bf9033067a42d35f2b9936822372cd9ea4f9b8c38b14948ff5", + "credential_request": "02c1f758572663d7bb1fa5dbc8cf426b867a9936bc741e9acc8a31b18bf0e5bd33b389ed08bf4bfbf895ea6706c3d967b5ec7c4af96c207ebe816c50b9615ab06ec6e0310d186d3c869b384418a6574cd9fff826e3a91ac46d05ce0ab56e25b978", + "credential_response": "03068d5d3fe0d6b3361c2c728b85dce104df42d3d11c2079392ab894ace50ff400005cf982b3ddbb28ee252d729c83c4b9d74a54ac72f25325f7f21824530649fbed3e1ab6eb243095958829896b0286515a108213900d019d88d8578eb7919aec225c95400fd737bdfa72a8dfcfc12958fb794383b8da8f49d13cd554569097e0f9ed325ae363061f593e3cf7a2d28ac87e5e0d2a2f344e7286cf7f38e006908b589db8b32e957d97134b10f8b2fa107b908f88eb2a4620f2ae25d61107bf9e6f3691d795831920a6728252782da676dc34b5d069d92af4d306f8b13a81185b5e8f648ff448ba49b2fbe98d0cac15fce9f60b965e79e0903bdee7528549d4241b", + "credential_finalization": "1e7f17932a85f0d16ca1a40c1233695dd23a087f17f470df4eb51e9ff24cbe43", + "client_registration_state": "40b461844231f2f890fc68aa0da838e25f40af01ec1b212fdf6bad07db17075702c1f758572663d7bb1fa5dbc8cf426b867a9936bc741e9acc8a31b18bf0e5bd33", + "client_login_state": "40b461844231f2f890fc68aa0da838e25f40af01ec1b212fdf6bad07db17075702c1f758572663d7bb1fa5dbc8cf426b867a9936bc741e9acc8a31b18bf0e5bd33b389ed08bf4bfbf895ea6706c3d967b5ec7c4af96c207ebe816c50b9615ab06ec6e0310d186d3c869b384418a6574cd9fff826e3a91ac46d05ce0ab56e25b978e889400a32d355cd203d6a1ee195a787217db28075de794d0c39ca29c44f1776b389ed08bf4bfbf895ea6706c3d967b5ec7c4af96c207ebe816c50b9615ab06e", + "server_login_state": "9a2ccb3a4690792ee4c290ae12a84049b941ac7d6c5288c300f3af40b34fef6dc40347b218e9f65fe3c67d07173dcc9d73b7bcd5e2a128e7565e4c2fcaada2c631b54a2472ce398831783222437e916804e19a67771d900cde8733e890305ce3", + "password_file": "f49b790e8f2e36ca511957263868d1ee897b2936b1ae4922ac2ad0b7a0e38f3c2606360d0008b6ed33e4ca48d31f3992875445e3a53f42e4eee661aad96e2c50785f65307f77f78cc4b20565a42c1954a30763d881528749f376b90a13ca2b7374d474b4232682bf9033067a42d35f2b9936822372cd9ea4f9b8c38b14948ff5", + "export_key": "2b867ad9909d31946cb3c3738fb1c1e51ba09d768e83d6b03eb909e0e4298003", + "session_key": "31b54a2472ce398831783222437e916804e19a67771d900cde8733e890305ce3" } "#; @@ -318,8 +321,8 @@ fn populate_test_vectors(values: &Value) -> TestVectorParameters { } } -fn stringify_test_vectors(p: &TestVectorParameters) -> alloc::string::String { - let mut s = alloc::string::String::new(); +fn stringify_test_vectors(p: &TestVectorParameters) -> String { + let mut s = String::new(); s.push_str("{\n"); s.push_str(format!("\"client_s_pk\": \"{}\",\n", hex::encode(&p.client_s_pk)).as_str()); s.push_str(format!("\"client_s_sk\": \"{}\",\n", hex::encode(&p.client_s_sk)).as_str()); @@ -443,15 +446,21 @@ fn stringify_test_vectors(p: &TestVectorParameters) -> alloc::string::String { fn generate_parameters() -> Result where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + // ClientRegistration: KgSk + KgPk + ::ScalarLen: Add<::ElemLen>, + ClientRegistrationLen: ArrayLength, // RegistrationResponse: KgPk + KePk ::ElemLen: Add<::PkLen>, RegistrationResponseLen: ArrayLength, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload @@ -461,10 +470,14 @@ where // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, CredentialRequestLen: ArrayLength, + // ClientLogin: KgSk + CredentialRequest + Ke1State + ::ScalarLen: Add>, + Sum<::ScalarLen, CredentialRequestLen>: + ArrayLength + Add>, + ClientLoginLen: ArrayLength, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse ::ElemLen: Add, @@ -472,8 +485,7 @@ where CredentialResponseWithoutKeLen: ArrayLength, // Ke2Message: (Nonce + KePk) + Hash NonceLen: Add<::PkLen>, - Sum::PkLen>: - ArrayLength + Add<::OutputSize>, + Sum::PkLen>: ArrayLength + Add>, Ke2MessageLen: ArrayLength, // CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message CredentialResponseWithoutKeLen: Add>, @@ -495,7 +507,7 @@ where let id_s = b"idS"; let password = b"password"; let context = b"context"; - let mut oprf_seed = GenericArray::<_, ::OutputSize>::default(); + let mut oprf_seed = Output::::default(); rng.fill_bytes(&mut oprf_seed); let mut masking_nonce = [0u8; 64]; rng.fill_bytes(&mut masking_nonce); @@ -535,7 +547,7 @@ where ); let registration_request_bytes = client_registration_start_result.message.serialize(); - let client_registration_state = client_registration_start_result.state.serialize()?; + let client_registration_state = client_registration_start_result.state.serialize(); let server_registration_start_result = ServerRegistration::::start( &server_setup, @@ -554,6 +566,7 @@ where .state .finish( &mut finish_registration_rng, + password, server_registration_start_result.message, ClientRegistrationFinishParameters::new( Identifiers { @@ -578,11 +591,7 @@ where let client_login_start_result = ClientLogin::::start(&mut client_login_start_rng, password).unwrap(); let credential_request_bytes = client_login_start_result.message.serialize(); - let client_login_state = client_login_start_result - .state - .serialize() - .unwrap() - .to_vec(); + let client_login_state = client_login_start_result.state.serialize().to_vec(); let mut server_e_sk_and_nonce_rng = CycleRng::new( [ @@ -613,6 +622,7 @@ where let client_login_finish_result = client_login_start_result .state .finish( + password, server_login_start_result.message, ClientLoginFinishParameters::new( Some(context), @@ -654,7 +664,7 @@ where credential_response: credential_response_bytes.to_vec(), credential_finalization: credential_finalization_bytes.to_vec(), password_file: password_file_bytes.to_vec(), - client_registration_state, + client_registration_state: client_registration_state.to_vec(), client_login_state, server_login_state: server_login_state.to_vec(), session_key: client_login_finish_result.session_key.to_vec(), @@ -693,7 +703,15 @@ fn generate_test_vectors() -> Result<(), ProtocolError> { #[test] fn test_registration_request() -> Result<(), ProtocolError> { - fn inner(test_vector: &str) -> Result<(), ProtocolError> { + fn inner(test_vector: &str) -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + // ClientRegistration: KgSk + KgPk + ::ScalarLen: Add<::ElemLen>, + ClientRegistrationLen: ArrayLength, + { let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap()); let mut rng = CycleRng::new(parameters.blinding_factor.to_vec()); let client_registration_start_result = @@ -704,7 +722,7 @@ fn test_registration_request() -> Result<(), ProtocolError> { ); assert_eq!( hex::encode(¶meters.client_registration_state), - hex::encode(client_registration_start_result.state.serialize()?) + hex::encode(client_registration_start_result.state.serialize()) ); Ok(()) } @@ -726,7 +744,12 @@ fn test_registration_request() -> Result<(), ProtocolError> { fn test_serialization() -> Result<(), ProtocolError> { use core::mem; - fn inner(test_vector: &str) -> Result<(), ProtocolError> { + fn inner(test_vector: &str) -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap()); let mut rng = CycleRng::new(parameters.blinding_factor.to_vec()); let client_registration_start_result = @@ -765,6 +788,9 @@ fn test_serialization() -> Result<(), ProtocolError> { fn test_registration_response() -> Result<(), ProtocolError> { fn inner(test_vector: &str) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // RegistrationResponse: KgPk + KePk ::ElemLen: Add<::PkLen>, RegistrationResponseLen: ArrayLength, @@ -810,12 +836,15 @@ fn test_registration_response() -> Result<(), ProtocolError> { fn test_registration_upload() -> Result<(), ProtocolError> { fn inner(test_vector: &str) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, { @@ -829,6 +858,7 @@ fn test_registration_upload() -> Result<(), ProtocolError> { let result = ClientRegistration::::deserialize(¶meters.client_registration_state)? .finish( &mut finish_registration_rng, + ¶meters.password, RegistrationResponse::deserialize(¶meters.registration_response)?, ClientRegistrationFinishParameters::new( Identifiers { @@ -867,12 +897,15 @@ fn test_registration_upload() -> Result<(), ProtocolError> { fn test_password_file() -> Result<(), ProtocolError> { fn inner(test_vector: &str) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload @@ -906,9 +939,17 @@ fn test_password_file() -> Result<(), ProtocolError> { fn test_credential_request() -> Result<(), ProtocolError> { fn inner(test_vector: &str) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, CredentialRequestLen: ArrayLength, + // ClientLogin: KgSk + CredentialRequest + Ke1State + ::ScalarLen: Add>, + Sum<::ScalarLen, CredentialRequestLen>: + ArrayLength + Add>, + ClientLoginLen: ArrayLength, { let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap()); @@ -927,7 +968,7 @@ fn test_credential_request() -> Result<(), ProtocolError> { ); assert_eq!( hex::encode(¶meters.client_login_state), - hex::encode(client_login_start_result.state.serialize()?) + hex::encode(client_login_start_result.state.serialize()) ); Ok(()) } @@ -948,10 +989,12 @@ fn test_credential_request() -> Result<(), ProtocolError> { fn test_credential_response() -> Result<(), ProtocolError> { fn inner(test_vector: &str) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse ::ElemLen: Add, @@ -1022,16 +1065,19 @@ fn test_credential_response() -> Result<(), ProtocolError> { fn test_credential_finalization() -> Result<(), ProtocolError> { fn inner(test_vector: &str) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap()); let client_login_finish_result = ClientLogin::::deserialize(¶meters.client_login_state)?.finish( + ¶meters.password, CredentialResponse::::deserialize(¶meters.credential_response)?, ClientLoginFinishParameters::new( Some(¶meters.context), @@ -1077,7 +1123,12 @@ fn test_credential_finalization() -> Result<(), ProtocolError> { #[test] fn test_server_login_finish() -> Result<(), ProtocolError> { - fn inner(test_vector: &str) -> Result<(), ProtocolError> { + fn inner(test_vector: &str) -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap()); let server_login_result = ServerLogin::::deserialize(¶meters.server_login_state)? @@ -1110,10 +1161,12 @@ fn test_complete_flow( login_password: &[u8], ) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { let credential_identifier = b"credentialIdentifier"; @@ -1129,6 +1182,7 @@ where )?; let client_registration_finish_result = client_registration_start_result.state.finish( &mut client_rng, + registration_password, server_registration_start_result.message, ClientRegistrationFinishParameters::default(), )?; @@ -1144,6 +1198,7 @@ where )?; let client_login_result = client_login_start_result.state.finish( + login_password, server_login_start_result.message, ClientLoginFinishParameters::default(), ); @@ -1204,7 +1259,12 @@ fn test_complete_flow_fail() -> Result<(), ProtocolError> { #[test] fn test_zeroize_client_registration_start() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let mut client_rng = OsRng; let client_registration_start_result = ClientRegistration::::start(&mut client_rng, STR_PASSWORD.as_bytes())?; @@ -1232,7 +1292,12 @@ fn test_zeroize_client_registration_start() -> Result<(), ProtocolError> { #[test] fn test_zeroize_client_registration_finish() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let mut client_rng = OsRng; let mut server_rng = OsRng; let server_setup = ServerSetup::::new(&mut server_rng); @@ -1245,6 +1310,7 @@ fn test_zeroize_client_registration_finish() -> Result<(), ProtocolError> { )?; let client_registration_finish_result = client_registration_start_result.state.finish( &mut client_rng, + STR_PASSWORD.as_bytes(), server_registration_start_result.message, ClientRegistrationFinishParameters::default(), )?; @@ -1274,12 +1340,15 @@ fn test_zeroize_client_registration_finish() -> Result<(), ProtocolError> { fn test_zeroize_server_registration_finish() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload @@ -1296,6 +1365,7 @@ fn test_zeroize_server_registration_finish() -> Result<(), ProtocolError> { )?; let client_registration_finish_result = client_registration_start_result.state.finish( &mut client_rng, + STR_PASSWORD.as_bytes(), server_registration_start_result.message, ClientRegistrationFinishParameters::default(), )?; @@ -1326,6 +1396,9 @@ fn test_zeroize_server_registration_finish() -> Result<(), ProtocolError> { fn test_zeroize_client_login_start() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, CredentialRequestLen: ArrayLength, @@ -1359,10 +1432,12 @@ fn test_zeroize_client_login_start() -> Result<(), ProtocolError> { fn test_zeroize_server_login_start() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { let mut client_rng = OsRng; @@ -1377,6 +1452,7 @@ fn test_zeroize_server_login_start() -> Result<(), ProtocolError> { )?; let client_registration_finish_result = client_registration_start_result.state.finish( &mut client_rng, + STR_PASSWORD.as_bytes(), server_registration_start_result.message, ClientRegistrationFinishParameters::default(), )?; @@ -1417,10 +1493,12 @@ fn test_zeroize_server_login_start() -> Result<(), ProtocolError> { fn test_zeroize_client_login_finish() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, @@ -1438,6 +1516,7 @@ fn test_zeroize_client_login_finish() -> Result<(), ProtocolError> { )?; let client_registration_finish_result = client_registration_start_result.state.finish( &mut client_rng, + STR_PASSWORD.as_bytes(), server_registration_start_result.message, ClientRegistrationFinishParameters::default(), )?; @@ -1453,6 +1532,7 @@ fn test_zeroize_client_login_finish() -> Result<(), ProtocolError> { ServerLoginStartParameters::default(), )?; let client_login_finish_result = client_login_start_result.state.finish( + STR_PASSWORD.as_bytes(), server_login_start_result.message, ClientLoginFinishParameters::default(), )?; @@ -1482,10 +1562,12 @@ fn test_zeroize_client_login_finish() -> Result<(), ProtocolError> { fn test_zeroize_server_login_finish() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { let mut client_rng = OsRng; @@ -1500,6 +1582,7 @@ fn test_zeroize_server_login_finish() -> Result<(), ProtocolError> { )?; let client_registration_finish_result = client_registration_start_result.state.finish( &mut client_rng, + STR_PASSWORD.as_bytes(), server_registration_start_result.message, ClientRegistrationFinishParameters::default(), )?; @@ -1515,6 +1598,7 @@ fn test_zeroize_server_login_finish() -> Result<(), ProtocolError> { ServerLoginStartParameters::default(), )?; let client_login_finish_result = client_login_start_result.state.finish( + STR_PASSWORD.as_bytes(), server_login_start_result.message, ClientLoginFinishParameters::default(), )?; @@ -1545,7 +1629,12 @@ fn test_zeroize_server_login_finish() -> Result<(), ProtocolError> { #[test] fn test_scalar_always_nonzero() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { // Start out with a bunch of zeros to force resampling of scalar let mut client_registration_rng = CycleRng::new([vec![0u8; 128], vec![1u8; 128]].concat()); let client_registration_start_result = @@ -1591,7 +1680,12 @@ fn test_scalar_always_nonzero() -> Result<(), ProtocolError> { #[test] fn test_reflected_value_error_registration() -> Result<(), ProtocolError> { - fn inner() -> Result<(), ProtocolError> { + fn inner() -> Result<(), ProtocolError> + where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, + { let credential_identifier = b"credentialIdentifier"; let password = b"password"; let mut client_rng = OsRng; @@ -1615,6 +1709,7 @@ fn test_reflected_value_error_registration() -> Result<(), ProtocolError> { let client_registration_finish_result = client_registration_start_result.state.finish( &mut client_rng, + password, reflected_registration_response, ClientRegistrationFinishParameters::default(), ); @@ -1643,10 +1738,12 @@ fn test_reflected_value_error_registration() -> Result<(), ProtocolError> { fn test_reflected_value_error_login() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { let credential_identifier = b"credentialIdentifier"; @@ -1663,6 +1760,7 @@ fn test_reflected_value_error_login() -> Result<(), ProtocolError> { )?; let client_registration_finish_result = client_registration_start_result.state.finish( &mut client_rng, + password, server_registration_start_result.message, ClientRegistrationFinishParameters::default(), )?; @@ -1686,6 +1784,7 @@ fn test_reflected_value_error_login() -> Result<(), ProtocolError> { .set_evaluation_element_for_testing(alpha); let client_login_result = client_login_start_result.state.finish( + password, reflected_credential_response, ClientLoginFinishParameters::default(), ); diff --git a/src/tests/mock_rng.rs b/src/tests/mock_rng.rs index d646556..351a335 100644 --- a/src/tests/mock_rng.rs +++ b/src/tests/mock_rng.rs @@ -5,9 +5,9 @@ // License, Version 2.0 found in the LICENSE-APACHE file in the root directory // of this source tree. -use alloc::vec::Vec; use core::cmp::min; use rand::{CryptoRng, Error, RngCore}; +use std::vec::Vec; /// A simple implementation of `RngCore` for testing purposes. /// diff --git a/src/tests/opaque_vectors.rs b/src/tests/opaque_vectors.rs index c97920e..4723b8d 100644 --- a/src/tests/opaque_vectors.rs +++ b/src/tests/opaque_vectors.rs @@ -68,25 +68,25 @@ bf8d6503 #### Intermediate Values ~~~ -client_public_key: 3ea81ee30a44d65ca6db8f42a9c125277898ead7fe1604da98 -70ad4542044a56 -auth_key: 7816871e2ab2d039dc0d8a07ce94081dfd975de003ea1b7ff2b120cc74c -f18c32e11d2ed730fae9040f87be5c11cfc90cdf3393557c47065d7127ece8ca2b09c -randomized_pwd: c9c8c47dece13aed16b80ca049cedc86e984177d98b549ba40390 -eb77981f954537e743ca3ec854fce472981714aadb3a280f4b2c15040d97653c64b7e -5c265e +client_public_key: 60c9b59f46e93a2dc8c5dd0dd101fad1838f4c4c026691e9d1 +8d3de8f2b3940d +auth_key: 72c837a116b444f86229d432ea48221327339704fd2451704766bb3d42d +10796a2be4083998a78f31f52f3d2fff6ace6b9c2fa9dae1ce64ee36cc867f6cc9e48 +randomized_pwd: 024d0bc2c5e95421951227ee87d8c5488e6dc537b2bf014452edb +714bb98f0ef9590b1cca3345f2a1d0afff79967875306e07326b311662d5975b24e82 +07594e envelope: 71b8f14b7a1059cdadc414c409064a22cf9e970b0ffc6f1fc6fdd539c46 -76775eca8b48680e4973b26f754fbe0865af5135b284b00afce879c285db39b2ef0a9 -c1bd2f847c3f2139556b34885691be2d1917be4de9d2f50ef198950964142256 -handshake_secret: 706bae252489cd38228083790e3ead93f6b5b41682468741508 -124a58185fbb5fc2ee23850dd5285095d6e18dd133f16ecda7e35837429efdf71455e -a6642cf6 -server_mac_key: b63f98de411d2b008abaee6699ed14fa2834986f9fc2f9ae59af2 -292fe8aa5e125d0ab0d5e5954cb8de5966da7994d798c800062c17fc167c598aa0d86 -071685 -client_mac_key: 187335e3edd777cb419d055e54001325cb19ebac8d43cf736f101 -127bb19c932717960b2401699b0d5029cd3637a3175248048f1eba202eada9428b475 -f2867a +767750a343dd3f683692f4ed987ff286a4ece0813a4942e23477920608f261e1ab6f8 +727f532c9fd0cde8ec492cb76efdc855da76d0b6ccbe8a4dc0ba2709d63c4517 +handshake_secret: 01d81a6ba7c31a2c7c7ff4dab19db55d1f0290905645004bc2b +b8d703f00e486a34c15095df96d6524901eeac1d6c46d94a2ee390dcc5625c6b0baba +fe40e504 +server_mac_key: 5ee8f006713979257342d86a1541545b59e4e628b8be4b2f01438 +83cb9ce2cd9b6caded5733919739bd889b9426a03ad7c23db8b26ad13d2ad179e56dd +cfe76d +client_mac_key: 5b14da362ce9eaf3492ad315997911d9db3264f0e22e2a4cfb501 +f6f336c4e5e3d448f4c1b558101563c55a31e992aab92459c67231ca68de19ab12470 +4ca0f9 oprf_key: 3f76113135e6ca7e51ac5bb3e8774eb84709ad36b8907ec8f7bc3537828 71906 ~~~ @@ -94,38 +94,38 @@ oprf_key: 3f76113135e6ca7e51ac5bb3e8774eb84709ad36b8907ec8f7bc3537828 #### Output Values ~~~ -registration_request: 76cc85628d5ac0e01de4ede72479d607490e7f58b94578d -b7a0606d74bc58b03 -registration_response: 583fd26fd3130386b1a1a970e4617d45dc21c7a6f07052 -8f0175985570b4ea2018d5035fd0a9c1d6412226df037125901a43f4dff660c0549d4 +registration_request: ac7a6330f91d1e5c87365630c7be58641885d59ffe4d3f8 +a49c094271993331d +registration_response: 5c7d3c70cf7478ead859bb879b37cce78baef3b9d81e04 +f4c790ce25f2830e2e18d5035fd0a9c1d6412226df037125901a43f4dff660c0549d4 02f672bcc0933 -registration_upload: 3ea81ee30a44d65ca6db8f42a9c125277898ead7fe1604da -9870ad4542044a56dde0af371300d8b13f4dc7039ae643560c279c0e67be6086bfbe2 -188a65480689c9044a36b844b3f137a1fb594caff5e79002232a877aba39da085ce62 -e1a59f71b8f14b7a1059cdadc414c409064a22cf9e970b0ffc6f1fc6fdd539c467677 -5eca8b48680e4973b26f754fbe0865af5135b284b00afce879c285db39b2ef0a9c1bd -2f847c3f2139556b34885691be2d1917be4de9d2f50ef198950964142256 -KE1: e47c1c5e5eed1910a1cbb6420c5edf26ea3c099aaaedcb03599fc311a724d84f +registration_upload: 60c9b59f46e93a2dc8c5dd0dd101fad1838f4c4c026691e9 +d18d3de8f2b3940d7981498360f8f276df1dfb852a93ec4f4a0189dec5a96363296a6 +93fc8a51fb052ae8318dac48be7e3c3cd290f7b8c12b807617b7f9399417deed00158 +281ac771b8f14b7a1059cdadc414c409064a22cf9e970b0ffc6f1fc6fdd539c467677 +50a343dd3f683692f4ed987ff286a4ece0813a4942e23477920608f261e1ab6f8727f +532c9fd0cde8ec492cb76efdc855da76d0b6ccbe8a4dc0ba2709d63c4517 +KE1: e4e7ce5bf96ddb2924faf816774b26a0ec7a6dd9d3a5bced1f4a3675c3cfd14c 804133133e7ee6836c8515752e24bb44d323fef4ead34cde967798f2e9784f69f6792 6bd036c5dc4971816b9376e9f64737f361ef8269c18f69f1ab555e96d4a -KE2: b01355438b21dc20aaa46a5dea61d5b60f81b81f347f80e8ee3addc12f62be05 -54f9341ca183700f6b6acf28dbfe4a86afad788805de49f2d680ab86ff39ed7f98431 -127a277d18a821887ef0e23d92d73000161f14a3437d5fa6e028e4b33edad12212183 -73ef515b13f023d4a17ed5f62201416b4ae07f56605093eda407390f83457ce80c4ad -48e25a7875deacb41fa9ee9c3fb9895407733ef147a97fb0eee9b47abd930777b6599 -1c53b126f9f5aae3307a111a85107fe2229f93db8fe0f9c5ec75a8cd571370add249e +KE2: 1af11be29a90322dc16462d0861b1eb617611fe2f05e5e9860c164592d4f7f62 +54f9341ca183700f6b6acf28dbfe4a86afad788805de49f2d680ab86ff39ed7f76011 +9ed2f12f6ec4983f2c598068057af146fd09133c75b229145b7580d53cac4ba581155 +2e6786837a3e03d9f7971df0dad4a04fd6a6d4164101c91137a87f4afde7dae72daf2 +620082f46413bbb3071767d549833bcc523acc645b571a66318b0b1f8bf4b23de3542 +8373aa1d3a45c1e89eff88f03f9446e5dfc23b6f8394f9c5ec75a8cd571370add249e 99cb8a8c43f6ef05610ac6e354642bf4fedbf696e77d4749eb304c4d74be9457c5975 -46bc22aed699225499910fc913b3e907125ff3ab1b935c6740b10dd4441074507761b -1d955aba1296ba52061dfec49c5e003bf84a354d30f2a1f00fb320256002b781da075 -e838cc535ece42b26d6043af -KE3: 19624915863ad577d4c6c15d56207fe0dfd96a8ec489b4bc25a7b79cc33c1d75 -717c0ba4db2cc5bb95d275ba5a5bcd39ad17459fb162d83455658acd20a4b4e4 -export_key: 252cfa49d8fd722663fe16ef7451d8cc25345f05f4967859e7500763f -42b18b036fb1c4e7f0ad0110c71fb87f80da9ab53724976c4f8fa368d1c4cb6b9c6cd -e4 -session_key: f31b89ce77171a51e6da037ad77f634184406844057f7875f04c7c4d -e08aa26d2f3bf9ab78e1e8a5faa6f625b12008d98da5e00d8aa36f9e097890337ac9c -005 +46bc22aed699225499910fc913b3e907120638f222a1a08460f4e40d0686830d3d608 +ce89789489161438bf6809dbbce3a6ddb0ce8702576843b58465d6cedd4e965f3f81b +92992ecec0e2137b66eff0b4 +KE3: 1c0c743ff88f1a4ff07350eef61e899ae25d7fb23d555926b218bac4c1963071 +5038c56cca247630be8a8e66f3ff18b89c1bc97e1e2192fd7f14f2f60ed084a3 +export_key: 8408f92d282c7f4b0f5462e5206bd92937a4d53b0dcdef90afffd015c +5dee44dc4dc5ad35d1681c97e2b66de09203ac359a69f1d45f8c97dbc907589177ccc +24 +session_key: 05d03f4143e5866844f7ae921d3b48f3d611e930a6c4be0993a98290 +085110c5a27a2e5f92aeed861b90de068a51a952aa75bf97589be7c7104a4c30cc357 +506 ~~~ ### OPAQUE-3DH Real Test Vector 2 @@ -187,25 +187,25 @@ blind_login: e6f161ac189e6873a19a54efca4baa0719e801e336d929d35ca28b5b #### Intermediate Values ~~~ -client_public_key: 003e4b5cd9124a026302a223cd2187fb62285d33d987155c4a -3307aa55f60c5e -auth_key: c34629e50ddce1db7aa01edb9cf6979890c40f0e55d8abfc388dae762a6 -5300955344d1e273be49a1a513dbadeb045163b8882809f885dd46e978797484da85b -randomized_pwd: 2d0285e5872af71e6b6f3e76e1605de56ee229d1436563988aab1 -13b2f8104a7a14377b71158451988bb4ec11a235fbac2063dad136cffd0b1f76019d4 -123199 +client_public_key: 3036af4744effe59eb7ee5db0ebcb653bd4a1c7ad0c56c78af +1288f1e8538d1c +auth_key: 8820ff275662bf91d4ebcca74c9b90913eb3ee8151047926ad754da823e +98800db56a79c68b44d76ad906d26ed8b9e25d8ea862cfc6c2f0da86c623f6a24961a +randomized_pwd: 16decdbba6912903b7ae38de7040a79ebc59c9fbbac04add8a710 +0ff8aedbb9530c4e664bd08b2689a607e99923e80563a8379ddfdb37801718ed043fb +7bca07 envelope: d0c7b0f0047682bd87a87e0c3553b9bcdce7e1ae3348570df20bf274782 -9b2d2d20f701d2571da6f0fe29687724db96371b552df07e06c6cf3a2534147161ba4 -5e543a6d4a15eda6af8ec5aab229abbaac2af81b48c1737a419a524bb618a48d -handshake_secret: b7cab8367758393c3a7c72b38accaa91e164d77be82d4c01364 -0b8d2d6e1750f5ce1b77dcaf4173d07deeefc67895ad2d9ae6c6be8bdb384a9f54c7d -946ad85e -server_mac_key: aa959f4338f440f08dbaee86a576aae1ba65ee348f51e339feeda -8ce93ab0673904c1bb3de591689613f489705de68ae9e96146b0f54c7e0333fa50855 -587fd5 -client_mac_key: 3a3ca98df30379ac1cf59f3508b3daa60ea644c28f1e9de5a4911 -f641514db7df1f46ec850ed2f9a2053f5a7cccd77f0a9b14e0e7c570319b8080c4484 -cecf74 +9b2d24117867ef8aa569ed6fa8ad1b3749b0df472d431ce92da7775e44623d6c36f7e +9396d16ac58060704e9d42b37f09642ed7ee49008b4b81dc65d282ddcec0ab97 +handshake_secret: eef528fc4e46c387ef2bd68c06eb135ea18d743bcb632233594 +b213eb4eefaa4010b0f00785a204c77456f9007d8f7645fdc0c6795f486150a53fe17 +e6608179 +server_mac_key: ff6eeffbe0e88a966bdb39fa4fc933a488c0b802f913a7a6950d1 +c2eda0fc6acce6fdf7b060aa0be02efddb5a127e4dd893d3666e9b54d6fd6c85f52c9 +13138e +client_mac_key: 4babec778469dfed06cd89c6673b8511f337e27ce565a2fd68cb6 +2a04df035fabc2097ba33018a4cd858dc399a0563950d7ce8ffe26c223328023e4c70 +a16c8e oprf_key: 531b0c7b0a3f90060c28d3d96ef5fecf56e25b8e4bf71c14bc770804c3f b4507 ~~~ @@ -213,38 +213,38 @@ b4507 #### Output Values ~~~ -registration_request: ec2927a03ced1220168b6d5a54f0372f813ced8ad3673d5 -1dee92d2cbfee500c -registration_response: 588b259785af29c162958ebfdc4ca3b1fcf46bd1894c81 -854db7d2d41bf1933c8aa90cb321a38759fc253c444f317782962ca18d33101eab2c8 +registration_request: d81b76a8a78b8b0758f7ceffaa5c3cb4ac76c0517759ad8 +077ed87857e585f79 +registration_response: a48835aa277db6d7d501addbd431100a548867e3f1ee6f +d6ae4aacd817a66e4c8aa90cb321a38759fc253c444f317782962ca18d33101eab2c8 cda04405a181f -registration_upload: 003e4b5cd9124a026302a223cd2187fb62285d33d987155c -4a3307aa55f60c5e3114123a82551b4851bbc26b4a6a25444a60c501bb3e8eae95f2a -eae7971f1358c5fe0cfa3cbf7f493be05418740bc884c1a20ad220c43ea30a7af1e92 -3e81b7d0c7b0f0047682bd87a87e0c3553b9bcdce7e1ae3348570df20bf2747829b2d -2d20f701d2571da6f0fe29687724db96371b552df07e06c6cf3a2534147161ba45e54 -3a6d4a15eda6af8ec5aab229abbaac2af81b48c1737a419a524bb618a48d -KE1: d0a498e621d3ff7a011b37166a63ef40fe268f93c7d75a467eea42a98c0a490d +registration_upload: 3036af4744effe59eb7ee5db0ebcb653bd4a1c7ad0c56c78 +af1288f1e8538d1cedbc931daab2331b192808768f149499a04c6dffa4eae66a6e0d3 +399547c8b9e9a743a3cd20f08ce07adf84b27c9ca879d730bcc41823cbd60411fbde6 +c7faf2d0c7b0f0047682bd87a87e0c3553b9bcdce7e1ae3348570df20bf2747829b2d +24117867ef8aa569ed6fa8ad1b3749b0df472d431ce92da7775e44623d6c36f7e9396 +d16ac58060704e9d42b37f09642ed7ee49008b4b81dc65d282ddcec0ab97 +KE1: 8a32b2985d824b0e42b7d3c5091774acd64386f8a762678422f0b5cbabeda12b a6bcd29b5aecc3507fc1f8f7631af3d2f5105155222e48099e5e6085d8c1187a642e7 eecf19b804a62817486663d6c6c239396f709b663a4350cda67d025687a -KE2: 6810ba4cf3049dab416529542385d194eddf0105ad6480ea0c92f872cab6af46 -30635396b708ddb7fc10fb73c4e3a9258cd9c3f6f761b2c227853b5def228c854aa9f -c9066d61f2a64d5890ed79ff8e4a200444dc2e180ae57d6e78bdb594722d57283a3ff -9a6600f61341f9ad49c32be9054ad8a26837d8ccea6de753520b1eb836c85faa907a4 -428828fb5ad362ff1b5327afdd1d1c300e03db05f9d55c1535bac50d76b4e5f19dcd7 -0ee043d2254ffcae31bffaf426f0b862f5fd311649723fa57f7ef652185f89114109f +KE2: da642966461f20090d1e8d6b1f63ea70dc94fc6e0ea0bad46d011e906cc03c03 +30635396b708ddb7fc10fb73c4e3a9258cd9c3f6f761b2c227853b5def228c8594543 +768891810f779604eb9e07dcd37635def358e2f4531f464a4e0b3726c150d7872785c +9b6a22f00fe3527d9e938d4b503047484723585ee390925ab9d97e30f0860caef1243 +0459d8ca24e5ff1a2029c363ed00f2f3cd09ead304f217290d8915183c2667959d420 +175bfca3bbec3d603844ca0d5b5892888f0de19dc3b83fa57f7ef652185f89114109f 5a61cc8c9216fdd7398246bb7a0c20e2fbca2d8ae070cdffe5bb4b1c373e71be8e7d8 -f356ee5de37881533f10397bcd84d35445a04e7e9047091f5b371582b6f7eb8f8f665 -6f800f2ad2491122a28fb5623987c28cd9d8fae45e0ab205cff7635c83fe993a83b0f -b2c1c85e599f0a33bd65a7ef -KE3: 37de6eb166462dd8d36a6f0c75bbe826856cf6f7f067935aaf5fddaeb6e56935 -e8f1b53af96d5194dd49cb2438801745597affd3af7508f260746573d42144bd -export_key: cb43c5c131fc4ee3c72a9c5a664a0137d46088c58cf24de4408e838d8 -1b743f6e1b9516cdc307775c45d3c70d3a446180782cb4a7dea4be5777b1934a78c11 -e1 -session_key: a40fa034f8220e18c1991f981655e8255009d62a596a579f08fd476a -08cca7d66189a19e68f180e520de10ee841ab4e4f1a61291468429f093776f0bc8663 -528 +f356ee5de37881533f10397bcd84d354454f08b6c37449cf70cac0babb85d5302dc59 +a0ae16b2e54865642b8bb985f48444d49ad89a6a0707dd46c2d53b8b73dff46ac7176 +a6167f39818f605e3c39d22c +KE3: b9487ca4b1308ce593d765739992e19c10d63c47f4f2d3eb4bfd0ffa101b6959 +114b4f6051305652e0f48ad219a696f3f12fad685f8d6e371dddc10fda2ec87e +export_key: 258d525e93a07c17dd9e41afc4fbfe316152afad02c54a6d3d201fd77 +487903143ca2ef27718a1e48b2ade5dc614b027b8a46fd334b701df5d385aaef2b1bd +16 +session_key: 021c0c3f15940f3e898f2925949aa8bc262248fae7b9ed7d33a2900e +866548ed24760c2244a2c14bfc196a00ffd66ebf54839850b101bc5e617c37ccad45a +68a ~~~ ### OPAQUE-3DH Real Test Vector 3 @@ -303,20 +303,20 @@ cd15c478 #### Intermediate Values ~~~ -client_public_key: 03c84a1dc96d2b896f20b390e75ae7e5ebedbb4db6c6cc9a78 -96e3c5d5f280e7ab -auth_key: 9a6ce467dca8841cb0f706bfd83f39cc8e855d000d982554af799acc33d -8354e -randomized_pwd: d8a0060fa0d6118cf89fe9df92a9b65dd1b0dd86cccbdee067926 -7dce6f50e3a +client_public_key: 030f9b896400f6efd57c69a41b05ffedc456f041cb54a2ab56 +8f5595c586070708 +auth_key: 4e01ca008eb4f84b8cee1b84b3abfaeb4f2c7fb41d2c8ad0f4fe89d74e6 +f0fc5 +randomized_pwd: c741d0a042e653ee4ccf24648aee4e3b4c500cc28feb3a72eea0f +24f69006693 envelope: 2527e48c983deeb54c9c6337fdd9e120de85343dc7887f00248f1acacc4 -a8319bb19ce6d364d86bd95a1516a49e288e0e013a197609e1de0b4e9e5950ade9c13 -handshake_secret: 3f11e9bb0233a88d5c00f236485058ebcbfd24180d0b8f7f078 -e8b88fa8a1c04 -server_mac_key: 7d82030842afc175e1a0fbddceba0e0e53102bf170ee394419d2b -fdefefda358 -client_mac_key: a605eb6d2e72308f29fc1d1709a683aaa5d09e775134bded0deae -e17dccaa9a1 +a83190f798f947d61d060cb102e5eeb9bd698bec5d1e1b6788860ec7c2d2e590121b0 +handshake_secret: 78bedd3ee950e1795ddeca4e0d4f4267a971ace52e6f876d9b2 +c8a349ec2be2a +server_mac_key: c8e62b9aee6ae6e2199db70f16631a302e9269f27d5f6ef954572 +f8ca05f8d01 +client_mac_key: 31e3581fcfbb7d6b10b5cf78399fb844ab7afe42cf94f8b72178a +1618711bb25 oprf_key: d153d662a1e7dd4383837aa7125685d2be6f8041472ecbfd610e46952a6 a24f1 ~~~ @@ -324,32 +324,32 @@ a24f1 #### Output Values ~~~ -registration_request: 0325768a660df0c15f6f2a1dcbb7efd4f1c92702401edf3 -e2f0742c8dce85d5fa8 -registration_response: 03de5c8f7d8ea7fd9590b0c8321b5f508bb8f49bbff83c -5449ef50d66bf3e93892025b95a6add1f2f3d038811b5ad3494bed73b1e2500d8dade +registration_request: 037aa042e317344246ebb94c38fe9989e01f7265413ade1 +f7ffaa706a81f58cf19 +registration_response: 03c0b3e621cadf1a56aa48305e3101efedb6248157708c +7ba70af396fa62d29bf7025b95a6add1f2f3d038811b5ad3494bed73b1e2500d8dade c592d88406e25c2f2 -registration_upload: 03c84a1dc96d2b896f20b390e75ae7e5ebedbb4db6c6cc9a -7896e3c5d5f280e7aba453596f5b719f2cf3c0982ebd2466a8442f3a98d9dcfe420b3 -5acb7cd8d0e592527e48c983deeb54c9c6337fdd9e120de85343dc7887f00248f1aca -cc4a8319bb19ce6d364d86bd95a1516a49e288e0e013a197609e1de0b4e9e5950ade9 -c13 -KE1: 03884e56429f1ee53559f2e244392eb8f994fd46c8fd9ffdd24ac5a7af963a66 -3b967fcded96ed46986e60fcbdf985232639f537377ca3fcf07ad489956b2e9019033 +registration_upload: 030f9b896400f6efd57c69a41b05ffedc456f041cb54a2ab +568f5595c5860707085e76cb3c849637cfd386d9cc762050a476a58da7c24b8a39084 +4689d8d6482bd2527e48c983deeb54c9c6337fdd9e120de85343dc7887f00248f1aca +cc4a83190f798f947d61d060cb102e5eeb9bd698bec5d1e1b6788860ec7c2d2e59012 +1b0 +KE1: 0320fee3e9c08dfd30d00ce524cee6595d9bd7387629efa0cb9eba1ba82ec465 +13967fcded96ed46986e60fcbdf985232639f537377ca3fcf07ad489956b2e9019033 58b4eae039953116889466bfddeb40168e39ed83809fd5f0d5f2de9c5234398 -KE2: 0225dbce19cf48eb908d66d0e955d0fe7d0f67d09bb0362154c7316d69700e23 -29cb792f3657240ce5296dd5633e7333531009c11ee6ab46b6111f156d96a160b268f -4a82c2b61a752672a3e322b6b8580c1a2c76fad4563d06c12a27146f73dbb5267ca8b -b86a83d0b902b97ac14d12501697300815c5d5fdc262830a351bb4416baceb16938e6 -cfd021f43dee80b9bc400304a4398480e195bc51b3bcc186ff0bf8018e88ecfc53891 +KE2: 03f629c1a3a5a3dc83af63c52d3bd58bbd78d5054caee7731381e967a7c381fa +20cb792f3657240ce5296dd5633e7333531009c11ee6ab46b6111f156d96a160b22c1 +7f819537c821604229b8c07798c56f14b5104729a1336f153510f58ea921758f8a486 +13ec4ee3e5675dc8be14776c0bb6458bf0d3f76dd24af8b43b49c8fbfcb5229c0bbe3 +a37c440bdca76ce404b215ceb8842e95e81138416e161ea02c2648018e88ecfc53891 529278c47239f8fe6f1be88972721898ef81cc0a76a0b5500242bc29993976185dacf -6be815cbfa923aac80fad8b7f020c9d4f18e0b6867a17c4af032f0221800fec352a2b -ec9ddb2dd8b91a087aa51c7fbbaf5efcbbea52fe -KE3: eb86a68c5e8812293d1da4a60e499236ffdffb34b29f6f8f0ac46979f07b1ef4 -export_key: b755602f5d0a8c2118f38608a98cf08f20adadf5ef759cea8e246e5ed -5bf95c3 -session_key: 08b539a036c888da87a25205c9c386f382bc53b098dae42f88f2320c -48f1a3dd +6be815cbfa923aac80fad8b7f020c9d4f18e0b6867a1764573de6cf3b1b7737e7e56a +181fe0ec8754940adce33c4712bd35e7e9e08e7c +KE3: d9108b70e4ff4955911162ed1cec6df65c880aad120bbf10fd7f32eea71b1a04 +export_key: 086cd26a64f469f2d22ab0b5f0c524b10321c4019018b004d0f8383c0 +24059be +session_key: 36d1125dbf5ea45568e586645841efb6c5f53d357cdffb79edf1bb8d +b0b843a9 ~~~ ### OPAQUE-3DH Real Test Vector 4 @@ -410,20 +410,20 @@ blind_login: 4308682dc1bdab92ff91bb1a5fc5bc084223fe4369beddca3f1640a6 #### Intermediate Values ~~~ -client_public_key: 03a12f7047c8a1774a745520b2eaac995687fbb6212a418f9c -1696d4186278eaa3 -auth_key: 2461460e02dde8a10c98e2911d4d5a3be0bd85f095064ade2f3a0ae79a4 -89b07 -randomized_pwd: 3d990218aab34ca0137bbbb298adcf585d4495ae843eddcbe3ca8 -f969b690676 +client_public_key: 03ce71710d0d366e44e4a7e92cb111fc41353d4244cac1ce4d +8a622acaab9effc6 +auth_key: b894fa35f63413029fcc70e80a0d1b59d1c90c3c255bfb11cf7b58fb136 +d2aee +randomized_pwd: 0588794becaf8f5fee7921cb467e4ce8b3c048e7b42d815ed306d +ef278c231d3 envelope: 75c245690f9669a9af5699e8b23d6d1fa9e697aeb4526267d942b842e44 -26e423d452786ba80be94bd8ebe643394d1a07e745a07e97b37a88b585b8afd6ce3cb -handshake_secret: 586e927091452c797e0eb69fc90840f4c1923a6852834644c5f -47cc8b5810d55 -server_mac_key: 09f90fb15227c185ba6102b797251d32f6bfaec56b218743ba4bb -c64696f9734 -client_mac_key: 7612361b97d074852344ee92ecfe154b93241e696808438745d4c -b4f5b8513fb +26e42cb65c94629db9811649cd4f3ff92e5d2c67f7486203ea5e471f2655f363f9f19 +handshake_secret: 8a2547abef351fc1f94fb19a886c2e5ca16aba3b2bfe0b4a8cc +086dd47b62c08 +server_mac_key: fa7c99e15ca1036738b9b48799515be78e471a2d06c3c3920d6a3 +703d11c0360 +client_mac_key: d480fde6de5e91a08179d9780bf6db0d1b959ae2fa394c09acdc6 +07b993410c2 oprf_key: f14e1fc34ba1218bfd3f7373f036889bf4f35a8fbc9e8c9c07ccf2d2388 79d9c ~~~ @@ -431,32 +431,32 @@ oprf_key: f14e1fc34ba1218bfd3f7373f036889bf4f35a8fbc9e8c9c07ccf2d2388 #### Output Values ~~~ -registration_request: 02792b0f4670aced5970a68b01bb951004ccad962159be4 -b6783170c9ad68f6052 -registration_response: 02101f7b9999e363b44dfa946eaad9930fda88d53632aa -701778747b6a411a071c029a2c6097fbbcf3457fe3ff7d4ef8e89dab585a67dfed090 +registration_request: 02baa002c856f4b0d49542dcb1391f240f836178702f835 +819fd221bcf9b6e9eec +registration_response: 03864f4590c09b4c4155f0cbb731c5aab554ab1bc930c3 +28e7a58bd6227933d54f029a2c6097fbbcf3457fe3ff7d4ef8e89dab585a67dfed090 5c9f104d909138bae -registration_upload: 03a12f7047c8a1774a745520b2eaac995687fbb6212a418f -9c1696d4186278eaa37b6e2a7531d9ca9a324ac5c1a02303f00175c41646a873441a5 -eb69dcbec4ea975c245690f9669a9af5699e8b23d6d1fa9e697aeb4526267d942b842 -e4426e423d452786ba80be94bd8ebe643394d1a07e745a07e97b37a88b585b8afd6ce -3cb -KE1: 02fe96fc48d9fc921edd8e92ada581cbcc2a65e30962d0002ea5242f5baf627f -f646498f95ec7986f0602019b3fbb646db87a2fdbc12176d4f7ab74fa5fadace6002a +registration_upload: 03ce71710d0d366e44e4a7e92cb111fc41353d4244cac1ce +4d8a622acaab9effc66c5d2844e32ed930c56080fa523c15ec6d85f7db1bbd02c4692 +14b31e27f6c5775c245690f9669a9af5699e8b23d6d1fa9e697aeb4526267d942b842 +e4426e42cb65c94629db9811649cd4f3ff92e5d2c67f7486203ea5e471f2655f363f9 +f19 +KE1: 038469dadcb23317fa577317079c82bad1e20be41c783cd0ecad6bef3de1b16b +1446498f95ec7986f0602019b3fbb646db87a2fdbc12176d4f7ab74fa5fadace6002a 9f857ad3eabe09047049e8b8cee72feea2acb7fc487777c0b22d3add6a0e0c0 -KE2: 03463f69fc22bfa666c55bd38319addcf5816f063ec5ae9fdeb7e572603c6698 -025947586f69259e0708bdfab794f689eec14c7deb7edde68c81645156cf278f219cb -3882d08a0617909c1a9f545dace3d56b5034d8025220e0280d5d541eb22ade140fa11 -663bd0a4c787203b93e423f431b3702ffcc635919dcf0d22520d90596fccdef52f3ca -c75d2804a96d1521b78205c47c998cdb4aafcb7cce4c174671423581ac468101aee52 +KE2: 036297ebd0b53dabaae6377cb1c3ba1bdd942a67a5ce019b363f26cd11ae3707 +ac5947586f69259e0708bdfab794f689eec14c7deb7edde68c81645156cf278f21308 +4ce22d007db399a17af864b5ea826f4086f3d477ce236cacf7867de174692940b103b +367ccb8b5aee6ef352079bf95c5961442cf400432de4d904815d1a8a20f64f3e8447b +82c27f4c9b798769db0fb5ab8d29ea0ee54c1e371105388a7ae7c581ac468101aee52 8cc6b69daac7a90de8837d49708e76310767cbe4af18594d022aa8746ab4329d59129 -6652d44f6dfb04470103311bacd7ad51060ef5abac41ba38a2e46ce2cfd59c6dfdd1e -77758505d944b28e753a7254bac79302947dc7d0 -KE3: 2ae94c682a2bc4c89eb16c395dc09d2b14d216dee0e59f34c317f5a6d8bbc717 -export_key: 04f3100265180b083abbd84109f5ed963481eb78a5d377e888810217f -fb8af04 -session_key: 7a0a42051497621e659270552be01baadddd1ee829f802891535a3fb -ac2a33ec +6652d44f6dfb04470103311bacd7ad51060ef5abac41bfa6b8e732462d3de6bdb3ef3 +edcf4595b478a6704d578fde4eaf922e1c1e8504 +KE3: cd11b70f1ed59d101ec20a73745d3d654c3772236ed2c365a730ef8ee51da6d2 +export_key: 8e1eb57bcde2d58d805b16fa045811679c68b0ec2817b9ac61786786a +9032837 +session_key: b1f3da97388d6171719c3e2281e88da75b68d6945189f460db841cc6 +92f7e164 ~~~ ## Fake Test Vectors {#fake-vectors} @@ -509,7 +509,7 @@ server_private_keyshare: a4abffe3bef8082b78323ea4507fbb0ce8105ca62b38 masking_key: 077adba76f768fd0979f8dc006ca297e7954ebf0e81a893021ee24ac c35e1a3f4b5e0366c15771133082ec21035ae0ef0d8bcd0e59d26775ae953b9552fdf bf2 -KE1: 1ef5fc13fa7695e81b5fcadf57eb49a579b10e4f51bbee11afb278608592456b +KE1: 88303c5318f93d39bb8afde6df62593869ba4eec265b980e3843c013401e6c5a 8837b6c0709160251cbebe0d55e4423554c45da7a8952367cf336eb623379e80dae2f 1e0cd79b733131d499fb9e77efe0f235d73c1f920bdc5816259ad3a7429 ~~~ @@ -517,16 +517,16 @@ KE1: 1ef5fc13fa7695e81b5fcadf57eb49a579b10e4f51bbee11afb278608592456b #### Output Values ~~~ -KE2: 02648d7558231b92265efe08ec0b3dec70e596e36ea6c70ceae961411bf8f328 +KE2: 8a003351892efcf8615128a241e2bf091433fab5a080d7512b156f53e8602a20 7cb33db5ba8082e4f4bfb830e8e3f525b0ddcb70469b34224758d725ce53ac76094c0 aa800d9a0884392e4efbc0479e3cb84a38c9ead879f1ff755ad762c06812b9858f82c 9722acc61b8eb1d156bc994839bf9ed8a760615258d23e0f94fa2cffadc655ed0d6ff 6914066427366019d4e6989b65d13e38e8edc5ae6f82aa1b6a46bfe6ca0256c64d0cf db50a3eb7676e1d212e155e152e3bbc9d1fae3c679aacae1f4fee4ee4ba509fda550e a0421a85762305b1db20e37f4539b2327d37b805e5c0ac2904c7d9bf38f99e0050594 -e484b4d8ded8038ef6e0c141a985fa6b35afc0c330be0512ba1eace7c1cae0b807f01 -6f2a67b604008b270f3e41a8fb3d54084b62510495baa0309a993a48cf2110cfe2555 -33047291134a010c13509ba1 +e484b4d8ded8038ef6e0c141a985fa6b35ad4627117ba6a8cfe2a7c9d100800a62c84 +aacc83ed786d722921ee7037abf71b4af7381cdc3d40c4d9e4fc9f6dc2bb2fc15c8e3 +aa9eca8a83332841dda4524f ~~~ ### OPAQUE-3DH Fake Test Vector 2 @@ -575,21 +575,21 @@ server_private_keyshare: e8c25741b201c2ba00abe390e5a3933a75efdb71b50e 1e0087cc7235f6f9448a masking_key: 5bb4d884375d7dcbd562a62190cc569ccc809cff9d5aa5e176d48e96 46b558eb -KE1: 031ac7e5c8099fcb7de5ad5b6cf33ff53078dbee1da64f15f6cd53b2afe6e332 -06a91c9485d74c9010185f462ce1eec52f588a8e392f36915849b6bfcb6bd5b904037 +KE1: 0320dd7cff999858fb63be5d11db9c3fafbacbedb775303324d8859bfb31f6dc +dba91c9485d74c9010185f462ce1eec52f588a8e392f36915849b6bfcb6bd5b904037 6a35db8f7e582569dba2e573c4af1462f91c59a9bdee253ed13f60108746252 ~~~ #### Output Values ~~~ -KE2: 02ed3cb4182cb2c2659d6c1d88014e821ea4fc00de1aca987fae5483f5f8aa59 -d021cd364318a92b2afbfccea5d80d337f07defe40d92673a52f3844058f5d949a604 +KE2: 03cac8c1654bba83a122227e503e5e5d1a094def98d6835be289421cdc08d549 +a121cd364318a92b2afbfccea5d80d337f07defe40d92673a52f3844058f5d949a604 39294e7567fc29643e0d5c8799d0dffbbfc8609558b982012fa90aef2ce52b1ffdd8f 96bda49f5306ae346cd745812d3a953ff94712e4ed0acc67c99b432860e337fe3234b ba88415ac55368b938106cca4049b5c13496fe167d3a092bd990e2b772c1eb569cc2b 57741bf3be630e377c8245b11d0b6ad1fe1d606490c2720802a59205c836a2ab86e19 -dbd9a417818052179e9a5c99221e2d1d8a780dfe4734dc9b9b3f64e5b3572a8f05f68 -93b0fa4dd12fba85ea99c8760b8011321bc37263 +dbd9a417818052179e9a5c99221e2d1d8a780dfe4734d04a0d4911decc97ece7f24af +58f767090bf16677af9468a4026efbab99877399 ~~~ "#; diff --git a/src/tests/parser.rs b/src/tests/parser.rs index 1472cf7..26bb7ca 100644 --- a/src/tests/parser.rs +++ b/src/tests/parser.rs @@ -5,7 +5,9 @@ // License, Version 2.0 found in the LICENSE-APACHE file in the root directory // of this source tree. -use alloc::string::String; +use std::string::{String, ToString}; +use std::vec::Vec; +use std::{format, vec}; pub(crate) fn rfc_to_json(input: &str) -> String { format!("{{\n{}\n}}", parse_vector_types(input)) diff --git a/src/tests/test_opaque_vectors.rs b/src/tests/test_opaque_vectors.rs index 137b2be..ce13eeb 100755 --- a/src/tests/test_opaque_vectors.rs +++ b/src/tests/test_opaque_vectors.rs @@ -9,6 +9,7 @@ use crate::{ ciphersuite::CipherSuite, envelope::EnvelopeLen, errors::*, + hash::{OutputSize, ProxyHash}, key_exchange::{ group::KeGroup, traits::{Ke1MessageLen, Ke2MessageLen}, @@ -23,12 +24,15 @@ use crate::{ tests::mock_rng::CycleRng, *, }; -use alloc::{string::ToString, vec, vec::Vec}; use core::ops::Add; -use digest::FixedOutput; -use generic_array::{typenum::Sum, ArrayLength}; +use digest::core_api::{BlockSizeUser, CoreProxy}; +use generic_array::{ + typenum::{IsLess, Le, NonZero, Sum, U256}, + ArrayLength, +}; use json::JsonValue; -use voprf::group::Group; +use std::{println, string::ToString, vec, vec::Vec}; +use voprf::Group; #[allow(non_snake_case)] #[derive(Debug)] @@ -150,12 +154,15 @@ fn populate_test_vectors(values: &JsonValue) -> OpaqueTestVectorParameters { fn get_password_file_bytes(parameters: &OpaqueTestVectorParameters) -> Vec where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload @@ -253,7 +260,12 @@ fn tests() -> Result<(), ProtocolError> { fn test_registration_request( tvs: &[OpaqueTestVectorParameters], -) -> Result<(), ProtocolError> { +) -> Result<(), ProtocolError> +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ for parameters in tvs { let mut rng = CycleRng::new(parameters.blind_registration.to_vec()); let client_registration_start_result = @@ -270,6 +282,9 @@ fn test_registration_response( tvs: &[OpaqueTestVectorParameters], ) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // RegistrationResponse: KgPk + KePk ::ElemLen: Add<::PkLen>, RegistrationResponseLen: ArrayLength, @@ -304,12 +319,15 @@ fn test_registration_upload( tvs: &[OpaqueTestVectorParameters], ) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, { @@ -321,6 +339,7 @@ where let mut finish_registration_rng = CycleRng::new(parameters.envelope_nonce.to_vec()); let result = client_registration_start_result.state.finish( &mut finish_registration_rng, + ¶meters.password, RegistrationResponse::deserialize(¶meters.registration_response).unwrap(), ClientRegistrationFinishParameters::new( Identifiers { @@ -353,6 +372,9 @@ where fn test_ke1(tvs: &[OpaqueTestVectorParameters]) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // CredentialRequest: KgPk + Ke1Message ::ElemLen: Add>, CredentialRequestLen: ArrayLength, @@ -383,28 +405,29 @@ where fn test_ke2(tvs: &[OpaqueTestVectorParameters]) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse ::ElemLen: Add, Sum<::ElemLen, NonceLen>: ArrayLength + Add>, CredentialResponseWithoutKeLen: ArrayLength, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message CredentialResponseWithoutKeLen: Add>, @@ -467,10 +490,12 @@ where fn test_ke3(tvs: &[OpaqueTestVectorParameters]) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { for parameters in tvs { @@ -485,6 +510,7 @@ where ClientLogin::::start(&mut client_login_start_rng, ¶meters.password)?; let client_login_finish_result = client_login_start_result.state.finish( + ¶meters.password, CredentialResponse::::deserialize(¶meters.KE2)?, ClientLoginFinishParameters::new( Some(¶meters.context.clone()), @@ -524,19 +550,21 @@ fn test_server_login_finish( tvs: &[OpaqueTestVectorParameters], ) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // Envelope: Nonce + Hash - NonceLen: Add<::OutputSize>, + NonceLen: Add>, EnvelopeLen: ArrayLength, // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add<::OutputSize>, - Sum<::PkLen, ::OutputSize>: + ::PkLen: Add>, + Sum<::PkLen, OutputSize>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, { for parameters in tvs { @@ -591,10 +619,12 @@ fn test_fake_vectors( tvs: &[OpaqueTestVectorParameters], ) -> Result<(), ProtocolError> where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add<::OutputSize>, - Sum::OutputSize>: - ArrayLength + Add<::PkLen>, + NonceLen: Add>, + Sum>: ArrayLength + Add<::PkLen>, MaskedResponseLen: ArrayLength, // CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse ::ElemLen: Add,