diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 70f0a78..f6c7bef 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,16 +13,16 @@ jobs: fail-fast: false matrix: backend_feature: - - --features ristretto255_u64,ristretto255_voprf - - --features ristretto255_u32,ristretto255_voprf - - - - --features x25519_u64,ristretto255_u64,ristretto255_voprf - - --features x25519_u32,ristretto255_u32,ristretto255_voprf - - --features x25519_u64 - - --features x25519_u32 + - --features ristretto255-u64,ristretto255-voprf + - --features ristretto255-u32,ristretto255-voprf + - + - --features x25519-u64,ristretto255-u64,ristretto255-voprf + - --features x25519-u32,ristretto255-u32,ristretto255-voprf + - --features x25519-u64 + - --features x25519-u32 frontend_feature: - - - - --features slow-hash + - + - --features argon2 - --features serde toolchain: - stable @@ -61,13 +61,13 @@ jobs: # 32-bit x86 - i686-unknown-linux-gnu backend_feature: - - --features ristretto255_u64,ristretto255_voprf - - --features ristretto255_u32,ristretto255_voprf - - - - x25519_u64,ristretto255_u64,ristretto255_voprf - - x25519_u32,ristretto255_u64,ristretto255_voprf - - x25519_u64 - - x25519_u32 + - --features ristretto255-u64,ristretto255-voprf + - --features ristretto255-u32,ristretto255-voprf + - + - x25519-u64,ristretto255-u64,ristretto255-voprf + - x25519-u32,ristretto255-u64,ristretto255-voprf + - x25519-u64 + - x25519-u32 steps: - uses: actions/checkout@v2 - uses: hecrj/setup-rust-action@v1 @@ -135,15 +135,15 @@ jobs: # for any no_std target - thumbv6m-none-eabi backend_feature: - - ristretto255_u64,ristretto255_voprf - - ristretto255_u32,ristretto255_voprf - - - - x25519_u64,ristretto255_u64,ristretto255_voprf - - x25519_u32,ristretto255_u32,ristretto255_voprf - - x25519_u64 - - x25519_u32 + - ristretto255-u64,ristretto255-voprf + - ristretto255-u32,ristretto255-voprf + - + - x25519-u64,ristretto255-u64,ristretto255-voprf + - x25519-u32,ristretto255-u32,ristretto255-voprf + - x25519-u64 + - x25519-u32 frontend_feature: - - slow-hash + - argon2 - serde steps: - uses: actions/checkout@v2 @@ -158,13 +158,13 @@ jobs: fail-fast: false matrix: backend_feature: - - --features ristretto255_u64,ristretto255_voprf - - --features ristretto255_u32,ristretto255_voprf - - - - --features x25519_u64,ristretto255_u64,ristretto255_voprf - - --features x25519_u32,ristretto255_u32,ristretto255_voprf - - --features x25519_u32 - - --features x25519_u32 + - --features ristretto255-u64,ristretto255-voprf + - --features ristretto255-u32,ristretto255-voprf + - + - --features x25519-u64,ristretto255-u64,ristretto255-voprf + - --features x25519-u32,ristretto255-u32,ristretto255-voprf + - --features x25519-u32 + - --features x25519-u32 steps: - name: Checkout sources uses: actions/checkout@v2 @@ -201,7 +201,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: clippy - args: --all-targets --features slow-hash,std,x25519_u64 -- -D warnings + args: --all-targets --features argon2,std,x25519-u64 -- -D warnings - name: Run cargo doc uses: actions-rs/cargo@v1 @@ -209,7 +209,7 @@ jobs: RUSTDOCFLAGS: -D warnings with: command: doc - args: --no-deps --document-private-items --features slow-hash,std,x25519_u64 + args: --no-deps --document-private-items --features argon2,std,x25519-u64 format: name: cargo fmt diff --git a/Cargo.toml b/Cargo.toml index 6899371..b39fc1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,42 +12,33 @@ rust-version = "1.57" version = "2.0.0-pre.1" [features] -default = ["ristretto255_u64", "ristretto255_voprf", "serde"] +default = ["ristretto255-u64", "ristretto255-voprf", "serde"] ristretto255 = ["curve25519-dalek", "voprf/ristretto255"] -ristretto255_fiat_u32 = ["curve25519-dalek/fiat_u32_backend", "ristretto255"] -ristretto255_fiat_u64 = ["curve25519-dalek/fiat_u64_backend", "ristretto255"] -ristretto255_simd = ["curve25519-dalek/simd_backend", "ristretto255"] -ristretto255_u32 = ["curve25519-dalek/u32_backend", "ristretto255"] -ristretto255_u64 = ["curve25519-dalek/u64_backend", "ristretto255"] -ristretto255_voprf = ["ristretto255", "voprf/ristretto255-ciphersuite"] +ristretto255-fiat-u32 = ["curve25519-dalek/fiat_u32_backend", "ristretto255"] +ristretto255-fiat-u64 = ["curve25519-dalek/fiat_u64_backend", "ristretto255"] +ristretto255-simd = ["curve25519-dalek/simd_backend", "ristretto255"] +ristretto255-u32 = ["curve25519-dalek/u32_backend", "ristretto255"] +ristretto255-u64 = ["curve25519-dalek/u64_backend", "ristretto255"] +ristretto255-voprf = ["ristretto255", "voprf/ristretto255-ciphersuite"] serde = ["serde_", "generic-array/serde", "voprf/serde"] -slow-hash = ["argon2"] -std = ["getrandom", "rand/std", "rand/std_rng", "voprf/std"] -x25519 = ["curve25519-dalek-3"] -x25519_fiat_u32 = ["x25519", "x25519-dalek/fiat_u32_backend"] -x25519_fiat_u64 = ["x25519", "x25519-dalek/fiat_u64_backend"] -# x25519-dalek isn't properly re-exposing `simd_backend`. -x25519_simd = [ - "curve25519-dalek-3/simd_backend", - "x25519", - "x25519-dalek/nightly", -] -x25519_u32 = ["x25519", "x25519-dalek/u32_backend"] -x25519_u64 = ["x25519", "x25519-dalek/u64_backend"] +std = ["getrandom"] +x25519 = ["curve25519-dalek"] +x25519-fiat-u32 = ["curve25519-dalek/fiat_u32_backend", "x25519"] +x25519-fiat-u64 = ["curve25519-dalek/fiat_u64_backend", "x25519"] +x25519-simd = ["curve25519-dalek/simd_backend", "x25519"] +x25519-u32 = ["curve25519-dalek/u32_backend", "x25519"] +x25519-u64 = ["curve25519-dalek/u64_backend", "x25519"] [dependencies] -argon2 = { version = "0.3", default-features = false, features = [ +argon2 = { version = "0.4", default-features = false, features = [ "alloc", ], optional = true } -constant_time_eq = "0.1" curve25519-dalek = { version = "=4.0.0-pre.1", default-features = false, optional = true } -curve25519-dalek-3 = { version = "3", package = "curve25519-dalek", default-features = false, optional = true } derive-where = { version = "=1.0.0-rc.3", features = ["zeroize-on-drop"] } digest = "0.10" displaydoc = { version = "0.2", default-features = false } elliptic-curve = { version = "0.12.0-pre.1", features = ["hash2curve", "sec1"] } generic-array = "0.14" -getrandom = { version = "0.2", optional = true } hkdf = "0.12" hmac = "0.12" rand = { version = "0.8", default-features = false } @@ -56,20 +47,17 @@ serde_ = { version = "1", package = "serde", default-features = false, features ], optional = true } subtle = { version = "2.3", default-features = false } voprf = { version = "0.3", default-features = false, features = ["danger"] } -x25519-dalek = { version = "=2.0.0-pre.1", default-features = false, optional = true } -zeroize = { version = "1", features = ["zeroize_derive"] } +zeroize = { version = "1.5", features = ["zeroize_derive"] } [target.'cfg(target_arch = "wasm32")'.dependencies] getrandom = { version = "0.2", features = ["js"], optional = true } [dev-dependencies] -base64 = "0.13" bincode = "1" -chacha20poly1305 = "0.9" +chacha20poly1305 = "=0.10.0-pre" criterion = "0.3" hex = "0.4" json = "0.12" -lazy_static = "1" p256 = { version = "=0.11.0-pre.0", default-features = false, features = [ "hash2curve", "voprf", @@ -79,19 +67,14 @@ rand = "0.8" regex = "1" rustyline = "9" serde_json = "1" -sha2 = "0.10" [[bench]] harness = false name = "opaque" [package.metadata.docs.rs] -features = ["std", "slow-hash", "x25519_u64"] +features = ["argon2", "std", "x25519-u64"] targets = [] [patch.crates-io] -chacha20 = { git = "https://github.com/RustCrypto/stream-ciphers" } -chacha20poly1305 = { git = "https://github.com/khonsulabs/aeads", branch = "update-dependencies" } -derive-where = { git = "https://github.com/ModProg/derive-where" } -poly1305 = { git = "https://github.com/RustCrypto/universal-hashes" } voprf = { git = "https://github.com/khonsulabs/voprf", branch = "v08" } diff --git a/benches/opaque.rs b/benches/opaque.rs index d5ed20e..15fd4d4 100644 --- a/benches/opaque.rs +++ b/benches/opaque.rs @@ -12,14 +12,14 @@ use criterion::Criterion; use opaque_ke::*; use rand::rngs::OsRng; -#[cfg(feature = "ristretto255_u64")] -static SUFFIX: &str = "ristretto255_u64"; -#[cfg(feature = "ristretto255_u32")] -static SUFFIX: &str = "ristretto255_u32"; -#[cfg(feature = "ristretto255_fiat_u64")] -static SUFFIX: &str = "ristretto255_fiat_u64"; -#[cfg(feature = "ristretto255_fiat_u32")] -static SUFFIX: &str = "ristretto255_fiat_u32"; +#[cfg(feature = "ristretto255-u64")] +static SUFFIX: &str = "ristretto255-u64"; +#[cfg(feature = "ristretto255-u32")] +static SUFFIX: &str = "ristretto255-u32"; +#[cfg(feature = "ristretto255-fiat-u64")] +static SUFFIX: &str = "ristretto255-fiat-u64"; +#[cfg(feature = "ristretto255-fiat-u32")] +static SUFFIX: &str = "ristretto255-fiat-u32"; #[cfg(all(not(feature = "ristretto255")))] static SUFFIX: &str = "p256"; @@ -27,18 +27,18 @@ struct Default; #[cfg(feature = "ristretto255")] impl CipherSuite for Default { - type OprfGroup = opaque_ke::Ristretto255; + type OprfCs = opaque_ke::Ristretto255; type KeGroup = opaque_ke::Ristretto255; - type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; - type SlowHash = opaque_ke::slow_hash::NoOpHash; + type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; + type Ksf = opaque_ke::ksf::Identity; } #[cfg(not(feature = "ristretto255"))] impl CipherSuite for Default { - type OprfGroup = p256::NistP256; + type OprfCs = p256::NistP256; type KeGroup = p256::NistP256; - type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; - type SlowHash = opaque_ke::slow_hash::NoOpHash; + type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; + type Ksf = opaque_ke::ksf::Identity; } fn server_setup(c: &mut Criterion) { diff --git a/examples/digital_locker.rs b/examples/digital_locker.rs index c7b8ba1..5d0aed4 100644 --- a/examples/digital_locker.rs +++ b/examples/digital_locker.rs @@ -49,18 +49,18 @@ struct Default; #[cfg(feature = "ristretto255")] impl CipherSuite for Default { - type OprfGroup = opaque_ke::Ristretto255; + type OprfCs = opaque_ke::Ristretto255; type KeGroup = opaque_ke::Ristretto255; - type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; - type SlowHash = opaque_ke::slow_hash::NoOpHash; + type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; + type Ksf = opaque_ke::ksf::Identity; } #[cfg(not(feature = "ristretto255"))] impl CipherSuite for Default { - type OprfGroup = p256::NistP256; + type OprfCs = p256::NistP256; type KeGroup = p256::NistP256; - type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; - type SlowHash = opaque_ke::slow_hash::NoOpHash; + type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; + type Ksf = opaque_ke::ksf::Identity; } struct Locker { diff --git a/examples/simple_login.rs b/examples/simple_login.rs index 77c060b..4897430 100644 --- a/examples/simple_login.rs +++ b/examples/simple_login.rs @@ -43,18 +43,18 @@ struct Default; #[cfg(feature = "ristretto255")] impl CipherSuite for Default { - type OprfGroup = opaque_ke::Ristretto255; + type OprfCs = opaque_ke::Ristretto255; type KeGroup = opaque_ke::Ristretto255; - type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; - type SlowHash = opaque_ke::slow_hash::NoOpHash; + type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; + type Ksf = opaque_ke::ksf::Identity; } #[cfg(not(feature = "ristretto255"))] impl CipherSuite for Default { - type OprfGroup = p256::NistP256; + type OprfCs = p256::NistP256; type KeGroup = p256::NistP256; - type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; - type SlowHash = opaque_ke::slow_hash::NoOpHash; + type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; + type Ksf = opaque_ke::ksf::Identity; } // Password-based registration between a client and server diff --git a/src/ciphersuite.rs b/src/ciphersuite.rs index 16e0a4a..c614379 100644 --- a/src/ciphersuite.rs +++ b/src/ciphersuite.rs @@ -15,17 +15,14 @@ use generic_array::typenum::{IsLess, IsLessOrEqual, Le, NonZero, U256}; use crate::hash::{Hash, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::key_exchange::traits::KeyExchange; -use crate::slow_hash::SlowHash; +use crate::ksf::Ksf; /// Configures the underlying primitives used in OPAQUE -/// * `OprfGroup`: 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`. +/// * `OprfCs`: A VOPRF ciphersuite, see [`voprf::CipherSuite`]. /// * `KeGroup`: A `Group` used for the `KeyExchange`. /// * `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 +/// * `Ksf`: A key stretching function, typically used for password hashing pub trait CipherSuite where as OutputSizeUser>::OutputSize: @@ -35,17 +32,15 @@ where < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, Le<< as CoreProxy>::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`. - type OprfGroup: voprf::CipherSuite; + /// A VOPRF ciphersuite, see [`voprf::CipherSuite`]. + type OprfCs: voprf::CipherSuite; /// A `Group` used for the `KeyExchange`. type KeGroup: KeGroup; /// A key exchange protocol type KeyExchange: KeyExchange, Self::KeGroup>; - /// A slow hashing function, typically used for password hashing - type SlowHash: SlowHash; + /// A key stretching function, typically used for password hashing + type Ksf: Ksf; } -pub(crate) type OprfGroup = <::OprfGroup as voprf::CipherSuite>::Group; -pub(crate) type OprfHash = <::OprfGroup as voprf::CipherSuite>::Hash; +pub(crate) type OprfGroup = <::OprfCs as voprf::CipherSuite>::Group; +pub(crate) type OprfHash = <::OprfCs as voprf::CipherSuite>::Hash; diff --git a/src/envelope.rs b/src/envelope.rs index 1531fda..2f2bb79 100644 --- a/src/envelope.rs +++ b/src/envelope.rs @@ -26,7 +26,7 @@ use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::keypair::{KeyPair, PublicKey}; use crate::opaque::{bytestrings_from_identifiers, Identifiers}; -use crate::serialization::{MacExt, Serialize}; +use crate::serialization::{Input, MacExt}; // Constant string used as salt for HKDF computation const STR_AUTH_KEY: [u8; 7] = *b"AuthKey"; @@ -35,6 +35,11 @@ const STR_PRIVATE_KEY: [u8; 10] = *b"PrivateKey"; const STR_OPAQUE_DERIVE_AUTH_KEY_PAIR: [u8; 24] = *b"OPAQUE-DeriveAuthKeyPair"; type NonceLen = U32; +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(crate = "serde") +)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, ZeroizeOnDrop)] pub(crate) enum InnerEnvelopeMode { Zero = 0, @@ -65,7 +70,12 @@ impl TryFrom for InnerEnvelopeMode { /// The specification update has simplified this assumption by taking an /// XOR-based approach without compromising on security, and to avoid the /// confusion around the implementation of an RKR-secure encryption. -#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") +)] +#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, ZeroizeOnDrop)] pub(crate) struct Envelope where as OutputSizeUser>::OutputSize: @@ -80,33 +90,6 @@ where hmac: Output>, } -impl Drop for Envelope -where - as OutputSizeUser>::OutputSize: - IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, - OprfHash: Hash, - as CoreProxy>::Core: ProxyHash, - < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, - Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, -{ - fn drop(&mut self) { - self.mode.zeroize(); - self.nonce.zeroize(); - self.hmac.zeroize(); - } -} - -impl ZeroizeOnDrop for Envelope -where - as OutputSizeUser>::OutputSize: - IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, - OprfHash: Hash, - as CoreProxy>::Core: ProxyHash, - < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, - Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, -{ -} - // 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 @@ -122,8 +105,8 @@ where { pub(crate) client_static_keypair: KeyPair, pub(crate) export_key: Output>, - pub(crate) id_u: Serialize<'a, U2, ::PkLen>, - pub(crate) id_s: Serialize<'a, U2, ::PkLen>, + pub(crate) id_u: Input<'a, U2, ::PkLen>, + pub(crate) id_s: Input<'a, U2, ::PkLen>, } pub(crate) struct OpenedInnerEnvelope @@ -175,10 +158,10 @@ where build_inner_envelope_internal::(randomized_pwd_hasher.clone(), nonce)?, ); - let server_s_pk_bytes = server_s_pk.to_bytes(); + let server_s_pk_bytes = server_s_pk.serialize(); let (id_u, id_s) = bytestrings_from_identifiers::( ids, - client_s_pk.to_bytes(), + client_s_pk.serialize(), server_s_pk_bytes.clone(), )?; let aad = construct_aad(id_u.iter(), id_s.iter(), &server_s_pk_bytes); @@ -246,10 +229,10 @@ where } }; - let server_s_pk_bytes = server_s_pk.to_bytes(); + let server_s_pk_bytes = server_s_pk.serialize(); let (id_u, id_s) = bytestrings_from_identifiers::( optional_ids, - client_static_keypair.public().to_bytes(), + client_static_keypair.public().serialize(), server_s_pk_bytes.clone(), )?; let aad = construct_aad(id_u.iter(), id_s.iter(), &server_s_pk_bytes); @@ -362,7 +345,7 @@ where .expand(&nonce.concat(STR_PRIVATE_KEY.into()), &mut keypair_seed) .map_err(|_| InternalError::HkdfError)?; let client_static_keypair = KeyPair::::from_private_key_slice( - &CS::KeGroup::serialize_sk(&CS::KeGroup::hash_to_scalar::>( + &CS::KeGroup::serialize_sk(CS::KeGroup::hash_to_scalar::>( &[keypair_seed.as_slice()], &GenericArray::from(STR_OPAQUE_DERIVE_AUTH_KEY_PAIR), )?), @@ -388,7 +371,7 @@ where .expand(&nonce.concat(STR_PRIVATE_KEY.into()), &mut keypair_seed) .map_err(|_| InternalError::HkdfError)?; let client_static_keypair = KeyPair::::from_private_key_slice( - &CS::KeGroup::serialize_sk(&CS::KeGroup::hash_to_scalar::>( + &CS::KeGroup::serialize_sk(CS::KeGroup::hash_to_scalar::>( &[keypair_seed.as_slice()], &GenericArray::from(STR_OPAQUE_DERIVE_AUTH_KEY_PAIR), )?), diff --git a/src/errors.rs b/src/errors.rs index 4080a4d..66aba7c 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -37,8 +37,8 @@ pub enum InternalError { HkdfError, /// Computing HMAC failed while supplying a secret key HmacError, - /// Computing the slow hashing function failed - SlowHashError, + /// Computing the key stretching function failed + KsfError, /** This error occurs when the envelope seal open hmac check fails HMAC check in seal open failed. */ SealOpenHmacError, @@ -70,7 +70,7 @@ impl Debug for InternalError { Self::HashToScalar => f.debug_tuple("HashToScalar").finish(), Self::HkdfError => f.debug_tuple("HkdfError").finish(), Self::HmacError => f.debug_tuple("HmacError").finish(), - Self::SlowHashError => f.debug_tuple("SlowHashError").finish(), + Self::KsfError => f.debug_tuple("KsfError").finish(), Self::SealOpenHmacError => f.debug_tuple("SealOpenHmacError").finish(), Self::IncompatibleEnvelopeModeError => { f.debug_tuple("IncompatibleEnvelopeModeError").finish() @@ -105,7 +105,7 @@ impl InternalError { Self::HashToScalar => InternalError::HashToScalar, Self::HkdfError => InternalError::HkdfError, Self::HmacError => InternalError::HmacError, - Self::SlowHashError => InternalError::SlowHashError, + Self::KsfError => InternalError::KsfError, Self::SealOpenHmacError => InternalError::SealOpenHmacError, Self::IncompatibleEnvelopeModeError => InternalError::IncompatibleEnvelopeModeError, Self::OprfError(error) => InternalError::OprfError(error), diff --git a/src/impls.rs b/src/impls.rs deleted file mode 100644 index ccdb637..0000000 --- a/src/impls.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// -// This source code is licensed under both the MIT license found in the -// LICENSE-MIT file in the root directory of this source tree and the Apache -// License, Version 2.0 found in the LICENSE-APACHE file in the root directory -// of this source tree. - -/// 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)*),+$(,)?)?) => { - #[cfg(feature = "serde")] - impl serde_::Serialize for $item - where - as OutputSizeUser>::OutputSize: - IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, - OprfHash: Hash, - as CoreProxy>::Core: ProxyHash, - < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, - Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, - $($($path: $bound1 $(+ $bound2)*),+)? - { - fn serialize(&self, serializer: S) -> Result - where - S: serde_::Serializer, - { - serializer.serialize_bytes(&self.serialize()) - } - } - - #[cfg(feature = "serde")] - impl<'de, CS: CipherSuite> serde_::Deserialize<'de> for $item - where - as OutputSizeUser>::OutputSize: - IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, - OprfHash: Hash, - as CoreProxy>::Core: ProxyHash, - < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, - Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, - { - fn deserialize(deserializer: D) -> Result - where - D: serde_::Deserializer<'de>, - { - use serde_::de::Error; - - struct ByteVisitor(core::marker::PhantomData) - where - as OutputSizeUser>::OutputSize: - IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, - OprfHash: Hash, - as CoreProxy>::Core: ProxyHash, - < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, - Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero; - - impl<'de, CS: CipherSuite> serde_::de::Visitor<'de> for ByteVisitor - where - as OutputSizeUser>::OutputSize: - IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, - OprfHash: Hash, - as CoreProxy>::Core: ProxyHash, - < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, - Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, - { - type Value = $item; - - fn expecting( - &self, - formatter: &mut core::fmt::Formatter, - ) -> core::fmt::Result { - formatter.write_str(core::concat!( - "the byte representation of a ", - core::stringify!($t) - )) - } - - fn visit_bytes(self, value: &[u8]) -> Result - where - E: Error, - { - $item::::deserialize(value).map_err(|_| { - Error::invalid_value( - serde_::de::Unexpected::Bytes(value), - &core::concat!( - "invalid byte sequence for ", - core::stringify!($t) - ), - ) - }) - } - } - - deserializer - .deserialize_bytes(ByteVisitor::(core::marker::PhantomData)) - .map_err(Error::custom) - } - } - }; -} diff --git a/src/key_exchange/group/elliptic_curve.rs b/src/key_exchange/group/elliptic_curve.rs index fef2f5f..5473904 100644 --- a/src/key_exchange/group/elliptic_curve.rs +++ b/src/key_exchange/group/elliptic_curve.rs @@ -11,8 +11,7 @@ use elliptic_curve::group::cofactor::CofactorGroup; use elliptic_curve::hash2curve::{ExpandMsgXmd, FromOkm, GroupDigest}; use elliptic_curve::sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint}; use elliptic_curve::{ - AffinePoint, Curve, FieldSize, NonZeroScalar, ProjectiveArithmetic, ProjectivePoint, PublicKey, - Scalar, SecretKey, + AffinePoint, Field, FieldSize, Group, ProjectivePoint, PublicKey, Scalar, SecretKey, }; use generic_array::typenum::{IsLess, IsLessOrEqual, U256}; use generic_array::GenericArray; @@ -21,31 +20,34 @@ use rand::{CryptoRng, RngCore}; use super::KeGroup; use crate::errors::InternalError; -impl KeGroup for G +impl KeGroup for G where + G: GroupDigest, FieldSize: ModulusSize, AffinePoint: FromEncodedPoint + ToEncodedPoint, ProjectivePoint: CofactorGroup + ToEncodedPoint, Scalar: FromOkm, { - type Pk = PublicKey; + type Pk = ProjectivePoint; type PkLen = as ModulusSize>::CompressedPointSize; - type Sk = SecretKey; + type Sk = Scalar; type SkLen = FieldSize; - fn serialize_pk(pk: &Self::Pk) -> GenericArray { + fn serialize_pk(pk: Self::Pk) -> GenericArray { GenericArray::clone_from_slice(pk.to_encoded_point(true).as_bytes()) } - fn deserialize_pk(bytes: &GenericArray) -> Result { - PublicKey::from_sec1_bytes(bytes).map_err(|_| InternalError::PointError) + fn deserialize_pk(bytes: &[u8]) -> Result { + PublicKey::::from_sec1_bytes(bytes) + .map(|public_key| public_key.to_projective()) + .map_err(|_| InternalError::PointError) } fn random_sk(rng: &mut R) -> Self::Sk { - SecretKey::random(rng) + *SecretKey::::random(rng).to_nonzero_scalar() } // Implements the `HashToScalar()` function @@ -55,31 +57,31 @@ where H::OutputSize: IsLess + IsLessOrEqual, { Self::hash_to_scalar::>(input, dst) - .ok() - .and_then(|scalar| Option::>::from(NonZeroScalar::new(scalar))) - .map(SecretKey::from) - .ok_or(InternalError::HashToScalar) + .map_err(|_| InternalError::HashToScalar) + .and_then(|scalar| { + if bool::from(scalar.is_zero()) { + Err(InternalError::HashToScalar) + } else { + Ok(scalar) + } + }) } - fn public_key(sk: &Self::Sk) -> Self::Pk { - sk.public_key() + fn public_key(sk: Self::Sk) -> Self::Pk { + ProjectivePoint::::generator() * sk } - fn diffie_hellman(pk: &Self::Pk, sk: &Self::Sk) -> GenericArray { - GenericArray::clone_from_slice( - (pk.to_projective() * sk.to_nonzero_scalar().as_ref()) - .to_encoded_point(true) - .as_bytes(), - ) + fn diffie_hellman(pk: Self::Pk, sk: Self::Sk) -> GenericArray { + Self::serialize_pk(pk * sk) } - fn zeroize_sk_on_drop(_sk: &mut Self::Sk) {} - - fn serialize_sk(sk: &Self::Sk) -> GenericArray { - sk.to_be_bytes() + fn serialize_sk(sk: Self::Sk) -> GenericArray { + sk.into() } - fn deserialize_sk(bytes: &GenericArray) -> Result { - SecretKey::from_be_bytes(bytes).map_err(|_| InternalError::PointError) + fn deserialize_sk(bytes: &[u8]) -> Result { + SecretKey::::from_be_bytes(bytes) + .map(|secret_key| *secret_key.to_nonzero_scalar()) + .map_err(|_| InternalError::PointError) } } diff --git a/src/key_exchange/group/mod.rs b/src/key_exchange/group/mod.rs index 95f4526..e46e434 100644 --- a/src/key_exchange/group/mod.rs +++ b/src/key_exchange/group/mod.rs @@ -18,25 +18,26 @@ use digest::Digest; use generic_array::typenum::{IsLess, IsLessOrEqual, U256}; use generic_array::{ArrayLength, GenericArray}; use rand::{CryptoRng, RngCore}; +use zeroize::Zeroize; use crate::errors::InternalError; /// A group representation for use in the key exchange pub trait KeGroup { /// Public key - type Pk: Clone; + type Pk: Copy + Zeroize; /// Length of the public key type PkLen: ArrayLength; /// Secret key - type Sk: Clone; + type Sk: Copy + Zeroize; /// Length of the secret key type SkLen: ArrayLength; /// Serializes `self` - fn serialize_pk(pk: &Self::Pk) -> GenericArray; + fn serialize_pk(pk: Self::Pk) -> GenericArray; /// Return a public key from its fixed-length bytes representation - fn deserialize_pk(bytes: &GenericArray) -> Result; + fn deserialize_pk(bytes: &[u8]) -> Result; /// Generate a random secret key fn random_sk(rng: &mut R) -> Self::Sk; @@ -52,17 +53,14 @@ pub trait KeGroup { H::OutputSize: IsLess + IsLessOrEqual; /// Return a public key from its secret key - fn public_key(sk: &Self::Sk) -> Self::Pk; + fn public_key(sk: Self::Sk) -> Self::Pk; /// Diffie-Hellman key exchange - fn diffie_hellman(pk: &Self::Pk, sk: &Self::Sk) -> GenericArray; - - /// Zeroize secret key on drop. - fn zeroize_sk_on_drop(sk: &mut Self::Sk); + fn diffie_hellman(pk: Self::Pk, sk: Self::Sk) -> GenericArray; /// Serializes `self` - fn serialize_sk(sk: &Self::Sk) -> GenericArray; + fn serialize_sk(sk: Self::Sk) -> GenericArray; /// Return a public key from its fixed-length bytes representation - fn deserialize_sk(bytes: &GenericArray) -> Result; + fn deserialize_sk(bytes: &[u8]) -> Result; } diff --git a/src/key_exchange/group/ristretto255.rs b/src/key_exchange/group/ristretto255.rs index cf7fe3b..d355ed5 100644 --- a/src/key_exchange/group/ristretto255.rs +++ b/src/key_exchange/group/ristretto255.rs @@ -10,6 +10,7 @@ use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint}; use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::Identity; use digest::core_api::BlockSizeUser; use digest::{Digest, OutputSizeUser}; use elliptic_curve::hash2curve::{ExpandMsg, ExpandMsgXmd, Expander}; @@ -17,7 +18,6 @@ use generic_array::typenum::{IsLess, IsLessOrEqual, U256, U32, U64}; use generic_array::GenericArray; use rand::{CryptoRng, RngCore}; use voprf::Group; -use zeroize::Zeroize; use super::KeGroup; use crate::errors::InternalError; @@ -33,13 +33,18 @@ impl KeGroup for Ristretto255 { type Sk = Scalar; type SkLen = U32; - fn serialize_pk(pk: &Self::Pk) -> GenericArray { + fn serialize_pk(pk: Self::Pk) -> GenericArray { pk.compress().to_bytes().into() } - fn deserialize_pk(bytes: &GenericArray) -> Result { + fn deserialize_pk(bytes: &[u8]) -> Result { + if bytes.len() != 32 { + return Err(InternalError::PointError); + } + CompressedRistretto::from_slice(bytes) .decompress() + .filter(|point| point != &RistrettoPoint::identity()) .ok_or(InternalError::PointError) } @@ -48,9 +53,7 @@ impl KeGroup for Ristretto255 { let scalar = { #[cfg(not(test))] { - let mut scalar_bytes = [0u8; 64]; - rng.fill_bytes(&mut scalar_bytes); - Scalar::from_bytes_mod_order_wide(&scalar_bytes) + Scalar::random(rng) } // Tests need an exact conversion from bytes to scalar, sampling only 32 bytes @@ -63,7 +66,7 @@ impl KeGroup for Ristretto255 { } }; - if scalar != Scalar::zero() && scalar.is_canonical() { + if scalar != Scalar::zero() { break scalar; } } @@ -81,31 +84,38 @@ impl KeGroup for Ristretto255 { .map_err(|_| InternalError::HashToScalar)? .fill_bytes(&mut uniform_bytes); - Ok(Scalar::from_bytes_mod_order_wide(&uniform_bytes.into())) + let scalar = Scalar::from_bytes_mod_order_wide(&uniform_bytes.into()); + + if scalar == Scalar::zero() { + Err(InternalError::HashToScalar) + } else { + Ok(scalar) + } } - fn public_key(sk: &Self::Sk) -> Self::Pk { + fn public_key(sk: Self::Sk) -> Self::Pk { RISTRETTO_BASEPOINT_POINT * sk } - fn diffie_hellman(pk: &Self::Pk, sk: &Self::Sk) -> GenericArray { - Self::serialize_pk(&(pk * sk)) + fn diffie_hellman(pk: Self::Pk, sk: Self::Sk) -> GenericArray { + Self::serialize_pk(pk * sk) } - fn zeroize_sk_on_drop(sk: &mut Self::Sk) { - sk.zeroize() - } - - fn serialize_sk(sk: &Self::Sk) -> GenericArray { + fn serialize_sk(sk: Self::Sk) -> GenericArray { sk.to_bytes().into() } - fn deserialize_sk(bytes: &GenericArray) -> Result { - Scalar::from_canonical_bytes((*bytes).into()).ok_or(InternalError::PointError) + fn deserialize_sk(bytes: &[u8]) -> Result { + bytes + .try_into() + .ok() + .and_then(Scalar::from_canonical_bytes) + .filter(|scalar| scalar != &Scalar::zero()) + .ok_or(InternalError::PointError) } } -#[cfg(feature = "ristretto255_voprf")] +#[cfg(feature = "ristretto255-voprf")] impl voprf::CipherSuite for Ristretto255 { const ID: u16 = voprf::Ristretto255::ID; diff --git a/src/key_exchange/group/x25519.rs b/src/key_exchange/group/x25519.rs index 690b4d0..878aad8 100644 --- a/src/key_exchange/group/x25519.rs +++ b/src/key_exchange/group/x25519.rs @@ -7,15 +7,16 @@ //! Key Exchange group implementation for X25519 -use curve25519_dalek_3::scalar::Scalar; +use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE; +use curve25519_dalek::montgomery::MontgomeryPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::Identity; use digest::core_api::BlockSizeUser; use digest::Digest; use elliptic_curve::hash2curve::{ExpandMsg, ExpandMsgXmd, Expander}; use generic_array::typenum::{IsLess, IsLessOrEqual, U256, U32, U64}; use generic_array::GenericArray; use rand::{CryptoRng, RngCore}; -use x25519_dalek::{PublicKey, StaticSecret}; -use zeroize::Zeroize; use super::KeGroup; use crate::errors::InternalError; @@ -25,31 +26,30 @@ pub struct X25519; /// The implementation of such a subgroup for Ristretto impl KeGroup for X25519 { - type Pk = PublicKey; + type Pk = MontgomeryPoint; type PkLen = U32; - type Sk = StaticSecret; + type Sk = Scalar; type SkLen = U32; - fn serialize_pk(pk: &Self::Pk) -> GenericArray { + fn serialize_pk(pk: Self::Pk) -> GenericArray { pk.to_bytes().into() } - fn deserialize_pk(bytes: &GenericArray) -> Result { - if **bytes == [0; 32] { - Err(InternalError::PointError) - } else { - Ok(PublicKey::from(<[_; 32]>::from(*bytes))) - } + fn deserialize_pk(bytes: &[u8]) -> Result { + bytes + .try_into() + .ok() + .map(MontgomeryPoint) + .filter(|pk| pk != &MontgomeryPoint::identity()) + .ok_or(InternalError::PointError) } fn random_sk(rng: &mut R) -> Self::Sk { - let mut scalar_bytes = [0u8; 32]; - loop { - rng.fill_bytes(&mut scalar_bytes); + let scalar = Scalar::random(rng); - if scalar_bytes != [0u8; 32] { - break StaticSecret::from(scalar_bytes); + if scalar != Scalar::zero() { + break scalar; } } } @@ -66,38 +66,33 @@ impl KeGroup for X25519 { .map_err(|_| InternalError::HashToScalar)? .fill_bytes(&mut uniform_bytes); - Ok(StaticSecret::from( - Scalar::from_bytes_mod_order_wide(&uniform_bytes.into()).to_bytes(), - )) + let scalar = Scalar::from_bytes_mod_order_wide(&uniform_bytes.into()); + + if scalar == Scalar::zero() { + Err(InternalError::HashToScalar) + } else { + Ok(scalar) + } } - fn public_key(sk: &Self::Sk) -> Self::Pk { - PublicKey::from(sk) + fn public_key(sk: Self::Sk) -> Self::Pk { + (&ED25519_BASEPOINT_TABLE * &sk).to_montgomery() } - fn diffie_hellman(pk: &Self::Pk, sk: &Self::Sk) -> GenericArray { - sk.diffie_hellman(pk).to_bytes().into() + fn diffie_hellman(pk: Self::Pk, sk: Self::Sk) -> GenericArray { + Self::serialize_pk(sk * pk) } - fn zeroize_sk_on_drop(sk: &mut Self::Sk) { - sk.zeroize() - } - - fn serialize_sk(sk: &Self::Sk) -> GenericArray { + fn serialize_sk(sk: Self::Sk) -> GenericArray { sk.to_bytes().into() } - fn deserialize_sk(bytes: &GenericArray) -> Result { - if **bytes == [0; 32] { - Err(InternalError::PointError) - } else { - let sk = StaticSecret::from(<[u8; 32]>::from(*bytes)); - - if sk.to_bytes() == **bytes { - Ok(sk) - } else { - Err(InternalError::PointError) - } - } + fn deserialize_sk(bytes: &[u8]) -> Result { + bytes + .try_into() + .ok() + .and_then(Scalar::from_canonical_bytes) + .filter(|scalar| scalar != &Scalar::zero()) + .ok_or(InternalError::PointError) } } diff --git a/src/key_exchange/traits.rs b/src/key_exchange/traits.rs index 0889a4f..2cf9526 100644 --- a/src/key_exchange/traits.rs +++ b/src/key_exchange/traits.rs @@ -18,39 +18,17 @@ use crate::hash::{Hash, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::keypair::{PrivateKey, PublicKey, SecretKey}; -#[cfg(not(test))] -pub type GenerateKe2Result = ( - >::KE2State, - >::KE2Message, -); -#[cfg(test)] -pub type GenerateKe2Result = ( - >::KE2State, - >::KE2Message, - Output, - Output, -); -#[cfg(not(test))] -pub type GenerateKe3Result = (Output, >::KE3Message); -#[cfg(test)] -pub type GenerateKe3Result = ( - Output, - >::KE3Message, - Output, - Output, -); - pub trait KeyExchange where D::Core: ProxyHash, ::BlockSize: IsLess, Le<::BlockSize, U256>: NonZero, { - type KE1State: FromBytes + ToBytes + ZeroizeOnDrop + Clone; - type KE2State: FromBytes + ToBytes + ZeroizeOnDrop + Clone; - type KE1Message: FromBytes + ToBytes + ZeroizeOnDrop + Clone; - type KE2Message: FromBytes + ToBytes + ZeroizeOnDrop + Clone; - type KE3Message: FromBytes + ToBytes + ZeroizeOnDrop + Clone; + type KE1State: Deserialize + Serialize + ZeroizeOnDrop + Clone; + type KE2State: Deserialize + Serialize + ZeroizeOnDrop + Clone; + type KE1Message: Deserialize + Serialize + ZeroizeOnDrop + Clone; + type KE2Message: Deserialize + Serialize + ZeroizeOnDrop + Clone; + type KE3Message: Deserialize + Serialize + ZeroizeOnDrop + Clone; fn generate_ke1( rng: &mut R, @@ -88,23 +66,45 @@ where ) -> Result, ProtocolError>; } -pub trait FromBytes: Sized { - fn from_bytes(input: &[u8]) -> Result; +pub trait Deserialize: Sized { + fn deserialize(input: &[u8]) -> Result; } -pub trait ToBytes { +pub trait Serialize { type Len: ArrayLength; - fn to_bytes(&self) -> GenericArray; + fn serialize(&self) -> GenericArray; } +#[cfg(not(test))] +pub type GenerateKe2Result = ( + >::KE2State, + >::KE2Message, +); +#[cfg(test)] +pub type GenerateKe2Result = ( + >::KE2State, + >::KE2Message, + Output, + Output, +); +#[cfg(not(test))] +pub type GenerateKe3Result = (Output, >::KE3Message); +#[cfg(test)] +pub type GenerateKe3Result = ( + Output, + >::KE3Message, + Output, + Output, +); + pub type Ke1StateLen = - <, CS::KeGroup>>::KE1State as ToBytes>::Len; + <, CS::KeGroup>>::KE1State as Serialize>::Len; pub type Ke1MessageLen = - <, CS::KeGroup>>::KE1Message as ToBytes>::Len; + <, CS::KeGroup>>::KE1Message as Serialize>::Len; pub type Ke2StateLen = - <, CS::KeGroup>>::KE2State as ToBytes>::Len; + <, CS::KeGroup>>::KE2State as Serialize>::Len; pub type Ke2MessageLen = - <, CS::KeGroup>>::KE2Message as ToBytes>::Len; + <, CS::KeGroup>>::KE2Message as Serialize>::Len; pub type Ke3MessageLen = - <, CS::KeGroup>>::KE3Message as ToBytes>::Len; + <, CS::KeGroup>>::KE3Message as Serialize>::Len; diff --git a/src/key_exchange/tripledh.rs b/src/key_exchange/tripledh.rs index 797bbef..8e13485 100644 --- a/src/key_exchange/tripledh.rs +++ b/src/key_exchange/tripledh.rs @@ -18,17 +18,16 @@ use generic_array::{ArrayLength, GenericArray}; use hkdf::{Hkdf, HkdfExtract}; use hmac::{Hmac, Mac}; use rand::{CryptoRng, RngCore}; -use zeroize::{Zeroize, ZeroizeOnDrop}; use crate::errors::utils::{check_slice_size, check_slice_size_atleast}; use crate::errors::{InternalError, ProtocolError}; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::key_exchange::traits::{ - FromBytes, GenerateKe2Result, GenerateKe3Result, KeyExchange, ToBytes, + Deserialize, GenerateKe2Result, GenerateKe3Result, KeyExchange, Serialize, }; use crate::keypair::{KeyPair, PrivateKey, PublicKey, SecretKey}; -use crate::serialization::{Serialize, UpdateExt}; +use crate::serialization::{Input, UpdateExt}; /////////////// // Constants // @@ -48,71 +47,42 @@ static STR_OPAQUE: &[u8] = b"OPAQUE-"; // ====================== // //////////////////////////// -#[allow(clippy::upper_case_acronyms)] /// The Triple Diffie-Hellman key exchange implementation -pub struct TripleDH; +pub struct TripleDh; /// The client state produced after the first key exchange message #[cfg_attr( feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), - serde( - bound( - deserialize = "KG::Sk: serde_::Deserialize<'de>", - serialize = "KG::Sk: serde_::Serialize", - ), - crate = "serde_" - ) + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") )] -#[derive_where(Clone)] +#[derive_where(Clone, ZeroizeOnDrop)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; KG::Sk)] pub struct Ke1State { client_e_sk: PrivateKey, client_nonce: GenericArray, } -impl Drop for Ke1State { - fn drop(&mut self) { - self.client_nonce.zeroize(); - } -} - -impl ZeroizeOnDrop for Ke1State {} - /// The first key exchange message #[cfg_attr( feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), - serde( - bound( - deserialize = "KG::Pk: serde_::Deserialize<'de>", - serialize = "KG::Pk: serde_::Serialize", - ), - crate = "serde_" - ) + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") )] -#[derive_where(Clone)] +#[derive_where(Clone, ZeroizeOnDrop)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; KG::Pk)] pub struct Ke1Message { pub(crate) client_nonce: GenericArray, pub(crate) client_e_pk: PublicKey, } -impl Drop for Ke1Message { - fn drop(&mut self) { - self.client_nonce.zeroize(); - } -} - -impl ZeroizeOnDrop for Ke1Message {} - /// The server state produced after the second key exchange message #[cfg_attr( feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), - serde(bound = "", crate = "serde_") + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") )] -#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, ZeroizeOnDrop)] pub struct Ke2State where D::Core: ProxyHash, @@ -124,40 +94,13 @@ where session_key: Output, } -impl Drop for Ke2State -where - D::Core: ProxyHash, - ::BlockSize: IsLess, - Le<::BlockSize, U256>: NonZero, -{ - fn drop(&mut self) { - self.km3.zeroize(); - self.hashed_transcript.zeroize(); - self.session_key.zeroize(); - } -} - -impl ZeroizeOnDrop for Ke2State -where - D::Core: ProxyHash, - ::BlockSize: IsLess, - Le<::BlockSize, U256>: NonZero, -{ -} - /// The second key exchange message #[cfg_attr( feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), - serde( - bound( - deserialize = "KG::Pk: serde_::Deserialize<'de>", - serialize = "KG::Pk: serde_::Serialize", - ), - crate = "serde_" - ) + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") )] -#[derive_where(Clone)] +#[derive_where(Clone, ZeroizeOnDrop)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; KG::Pk)] pub struct Ke2Message where @@ -170,33 +113,13 @@ where mac: Output, } -impl Drop for Ke2Message -where - D::Core: ProxyHash, - ::BlockSize: IsLess, - Le<::BlockSize, U256>: NonZero, -{ - fn drop(&mut self) { - self.server_nonce.zeroize(); - self.mac.zeroize(); - } -} - -impl ZeroizeOnDrop for Ke2Message -where - D::Core: ProxyHash, - ::BlockSize: IsLess, - Le<::BlockSize, U256>: NonZero, -{ -} - /// The third key exchange message #[cfg_attr( feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), - serde(bound = "", crate = "serde_") + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") )] -#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, ZeroizeOnDrop)] pub struct Ke3Message where D::Core: ProxyHash, @@ -206,31 +129,12 @@ where mac: Output, } -impl Drop for Ke3Message -where - D::Core: ProxyHash, - ::BlockSize: IsLess, - Le<::BlockSize, U256>: NonZero, -{ - fn drop(&mut self) { - self.mac.zeroize(); - } -} - -impl ZeroizeOnDrop for Ke3Message -where - D::Core: ProxyHash, - ::BlockSize: IsLess, - Le<::BlockSize, U256>: NonZero, -{ -} - //////////////////////////////// // High-level Implementations // // ========================== // //////////////////////////////// -impl KeyExchange for TripleDH +impl KeyExchange for TripleDh where D::Core: ProxyHash, ::BlockSize: IsLess, @@ -294,7 +198,7 @@ where let mut transcript_hasher = D::new() .chain(STR_RFC) .chain_iter( - Serialize::::from(context) + Input::::from(context) .map_err(ProtocolError::into_custom)? .iter(), ) @@ -303,10 +207,10 @@ where .chain_iter(id_s.into_iter()) .chain_iter(l2_bytes) .chain(server_nonce) - .chain(&server_e_kp.public().to_bytes()); + .chain(&server_e_kp.public().serialize()); let result = derive_3dh_keys::( - TripleDHComponents { + TripleDhComponents { pk1: ke1_message.client_e_pk.clone(), sk1: server_e_kp.private().clone(), pk2: ke1_message.client_e_pk.clone(), @@ -356,7 +260,7 @@ where ) -> Result, ProtocolError> { let mut transcript_hasher = D::new() .chain(STR_RFC) - .chain_iter(Serialize::::from(context)?.iter()) + .chain_iter(Input::::from(context)?.iter()) .chain_iter(id_u) .chain_iter(serialized_credential_request) .chain_iter(id_s) @@ -364,7 +268,7 @@ where .chain(ke2_message.to_bytes_without_mac()); let result = derive_3dh_keys::>( - TripleDHComponents { + TripleDhComponents { pk1: ke2_message.server_e_pk.clone(), sk1: ke1_state.client_e_sk.clone(), pk2: server_s_pk, @@ -422,9 +326,8 @@ where //==================== // ///////////////////////// -#[allow(clippy::upper_case_acronyms)] // The triple of public and private components used in the 3DH computation -struct TripleDHComponents> { +struct TripleDhComponents> { pk1: PublicKey, sk1: PrivateKey, pk2: PublicKey, @@ -435,10 +338,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 = (Output, Output, Output); +type TripleDhDerivationResult = (Output, Output, Output); #[cfg(test)] -type TripleDHDerivationResult = (Output, Output, Output, Output); +type TripleDhDerivationResult = (Output, Output, Output, Output); //////////////////////////////////////////////// // Helper functions and Trait Implementations // @@ -451,9 +353,9 @@ type TripleDHDerivationResult = (Output, Output, Output, Output); // and server keypairs, along with some auxiliary metadata, to produce the // session key and two MAC keys fn derive_3dh_keys>( - dh: TripleDHComponents, + dh: TripleDhComponents, hashed_derivation_transcript: &[u8], -) -> Result, ProtocolError> +) -> Result, ProtocolError> where D::Core: ProxyHash, ::BlockSize: IsLess, @@ -529,9 +431,9 @@ where let length_u16: u16 = u16::try_from(OutputSize::::USIZE).map_err(|_| ProtocolError::SerializationError)?; - let label = Serialize::::from_label(STR_OPAQUE, label)?; + let label = Input::::from_label(STR_OPAQUE, label)?; let label = label.to_array_3(); - let context = Serialize::::from(context)?; + let context = Input::::from(context)?; let context = context.to_array_2(); let hkdf_label = [ @@ -570,8 +472,8 @@ fn generate_nonce(rng: &mut R) -> GenericArray FromBytes for Ke1State { - fn from_bytes(bytes: &[u8]) -> Result { +impl Deserialize for Ke1State { + fn deserialize(bytes: &[u8]) -> Result { let key_len = KG::SkLen::USIZE; let nonce_len = NonceLen::USIZE; @@ -586,7 +488,7 @@ impl FromBytes for Ke1State { } } -impl ToBytes for Ke1State +impl Serialize for Ke1State where // Ke1State: KeSk + Nonce KG::SkLen: Add, @@ -594,13 +496,13 @@ where { type Len = Sum; - fn to_bytes(&self) -> GenericArray { + fn serialize(&self) -> GenericArray { self.client_e_sk.serialize().concat(self.client_nonce) } } -impl FromBytes for Ke1Message { - fn from_bytes(ke1_message_bytes: &[u8]) -> Result { +impl Deserialize for Ke1Message { + fn deserialize(ke1_message_bytes: &[u8]) -> Result { let nonce_len = NonceLen::USIZE; let checked_nonce = check_slice_size( ke1_message_bytes, @@ -615,7 +517,7 @@ impl FromBytes for Ke1Message { } } -impl ToBytes for Ke1Message +impl Serialize for Ke1Message where // Ke1Message: Nonce + KePk NonceLen: Add, @@ -623,18 +525,18 @@ where { type Len = Sum; - fn to_bytes(&self) -> GenericArray { - self.client_nonce.concat(self.client_e_pk.to_bytes()) + fn serialize(&self) -> GenericArray { + self.client_nonce.concat(self.client_e_pk.serialize()) } } -impl FromBytes for Ke2State +impl Deserialize for Ke2State where D::Core: ProxyHash, ::BlockSize: IsLess, Le<::BlockSize, U256>: NonZero, { - fn from_bytes(input: &[u8]) -> Result { + fn deserialize(input: &[u8]) -> Result { let hash_len = OutputSize::::USIZE; let checked_bytes = check_slice_size(input, 3 * hash_len, "ke2_state")?; @@ -648,7 +550,7 @@ where } } -impl ToBytes for Ke2State +impl Serialize for Ke2State where D::Core: ProxyHash, ::BlockSize: IsLess, @@ -660,7 +562,7 @@ where { type Len = Sum, OutputSize>, OutputSize>; - fn to_bytes(&self) -> GenericArray { + fn serialize(&self) -> GenericArray { self.km3 .clone() .concat(self.hashed_transcript.clone()) @@ -668,13 +570,13 @@ where } } -impl FromBytes for Ke2Message +impl Deserialize for Ke2Message where D::Core: ProxyHash, ::BlockSize: IsLess, Le<::BlockSize, U256>: NonZero, { - fn from_bytes(input: &[u8]) -> Result { + fn deserialize(input: &[u8]) -> Result { let key_len = ::PkLen::USIZE; let nonce_len = NonceLen::USIZE; let checked_nonce = check_slice_size_atleast(input, nonce_len, "ke2_message nonce")?; @@ -701,7 +603,7 @@ where } } -impl ToBytes for Ke2Message +impl Serialize for Ke2Message where D::Core: ProxyHash, ::BlockSize: IsLess, @@ -713,9 +615,9 @@ where { type Len = Sum, OutputSize>; - fn to_bytes(&self) -> GenericArray { + fn serialize(&self) -> GenericArray { self.server_nonce - .concat(self.server_e_pk.to_bytes()) + .concat(self.server_e_pk.serialize()) .concat(self.mac.clone()) } } @@ -729,17 +631,17 @@ where Sum: ArrayLength, { fn to_bytes_without_mac(&self) -> GenericArray> { - self.server_nonce.concat(self.server_e_pk.to_bytes()) + self.server_nonce.concat(self.server_e_pk.serialize()) } } -impl FromBytes for Ke3Message +impl Deserialize for Ke3Message where D::Core: ProxyHash, ::BlockSize: IsLess, Le<::BlockSize, U256>: NonZero, { - fn from_bytes(bytes: &[u8]) -> Result { + fn deserialize(bytes: &[u8]) -> Result { let checked_bytes = check_slice_size(bytes, OutputSize::::USIZE, "ke3_message")?; Ok(Self { @@ -748,7 +650,7 @@ where } } -impl ToBytes for Ke3Message +impl Serialize for Ke3Message where D::Core: ProxyHash, ::BlockSize: IsLess, @@ -756,7 +658,7 @@ where { type Len = OutputSize; - fn to_bytes(&self) -> GenericArray { + fn serialize(&self) -> GenericArray { self.mac.clone() } } diff --git a/src/keypair.rs b/src/keypair.rs index 3c13305..332319d 100644 --- a/src/keypair.rs +++ b/src/keypair.rs @@ -12,22 +12,20 @@ use derive_where::derive_where; use generic_array::{ArrayLength, GenericArray}; use rand::{CryptoRng, RngCore}; -use zeroize::ZeroizeOnDrop; use crate::errors::{InternalError, ProtocolError}; use crate::key_exchange::group::KeGroup; -use crate::serialization::GenericArrayExt; /// A Keypair trait with public-private verification #[cfg_attr( feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), + derive(serde::Deserialize, serde::Serialize), serde( bound( - deserialize = "KG::Pk: serde_::Deserialize<'de>, S: serde_::Deserialize<'de>", - serialize = "KG::Pk: serde_::Serialize, S: serde_::Serialize" + deserialize = "S: serde::Deserialize<'de>", + serialize = "S: serde::Serialize" ), - crate = "serde_" + crate = "serde" ) )] #[derive_where(Clone)] @@ -64,7 +62,7 @@ impl KeyPair { /// Generating a random key pair given a cryptographic rng pub(crate) fn generate_random(rng: &mut R) -> Self { let sk = KG::random_sk(rng); - let pk = KG::public_key(&sk); + let pk = KG::public_key(sk); Self { pk: PublicKey(pk), sk: PrivateKey(sk), @@ -98,36 +96,10 @@ where } /// Wrapper around a Key to enforce that it's a private one. -#[cfg_attr( - feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), - serde( - bound( - deserialize = "KG::Sk: serde_::Deserialize<'de>", - serialize = "KG::Sk: serde_::Serialize" - ), - crate = "serde_" - ) -)] -#[derive_where(Clone)] +#[derive_where(Clone, ZeroizeOnDrop)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; KG::Sk)] pub struct PrivateKey(KG::Sk); -impl Drop for PrivateKey { - fn drop(&mut self) { - KG::zeroize_sk_on_drop(&mut self.0) - } -} - -impl ZeroizeOnDrop for PrivateKey {} - -impl PrivateKey { - /// Convert from bytes - pub fn from_bytes(key_bytes: &GenericArray) -> Result { - KG::deserialize_sk(key_bytes).map(Self) - } -} - /// A trait specifying the requirements for a private key container pub trait SecretKey: Clone + Sized { /// Custom error type that can be passed down to `InternalError::Custom` @@ -159,52 +131,84 @@ impl SecretKey for PrivateKey { &self, pk: PublicKey, ) -> Result, InternalError> { - Ok(KG::diffie_hellman(&pk.0, &self.0)) + Ok(KG::diffie_hellman(pk.0, self.0)) } fn public_key(&self) -> Result, InternalError> { - Ok(PublicKey(KG::public_key(&self.0))) + Ok(PublicKey(KG::public_key(self.0))) } fn serialize(&self) -> GenericArray { - KG::serialize_sk(&self.0) + KG::serialize_sk(self.0) } fn deserialize(input: &[u8]) -> Result { - GenericArray::try_from_slice(input).and_then(Self::from_bytes) + KG::deserialize_sk(input).map(Self) + } +} + +#[cfg(feature = "serde")] +impl<'de, KG: KeGroup> serde::Deserialize<'de> for PrivateKey { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::Error; + + KG::deserialize_sk(&GenericArray::<_, KG::SkLen>::deserialize(deserializer)?) + .map(Self) + .map_err(D::Error::custom) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for PrivateKey { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + KG::serialize_sk(self.0).serialize(serializer) } } /// Wrapper around a Key to enforce that it's a public one. -#[cfg_attr( - feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), - serde( - bound( - deserialize = "KG::Pk: serde_::Deserialize<'de>", - serialize = "KG::Pk: serde_::Serialize" - ), - crate = "serde_" - ) -)] -#[derive_where(Clone)] +#[derive_where(Clone, ZeroizeOnDrop)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; KG::Pk)] pub struct PublicKey(KG::Pk); impl PublicKey { /// Convert from bytes - pub fn from_bytes(key_bytes: &GenericArray) -> Result { + pub fn deserialize(key_bytes: &[u8]) -> Result { KG::deserialize_pk(key_bytes).map(Self) } /// Convert to bytes - pub fn to_bytes(&self) -> GenericArray { - KG::serialize_pk(&self.0) + pub fn serialize(&self) -> GenericArray { + KG::serialize_pk(self.0) } +} - /// Convert from slice - pub fn deserialize(input: &[u8]) -> Result { - GenericArray::try_from_slice(input).and_then(Self::from_bytes) +#[cfg(feature = "serde")] +impl<'de, KG: KeGroup> serde::Deserialize<'de> for PublicKey { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::Error; + + KG::deserialize_pk(&GenericArray::<_, KG::PkLen>::deserialize(deserializer)?) + .map(Self) + .map_err(D::Error::custom) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for PublicKey { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + KG::serialize_pk(self.0).serialize(serializer) } } @@ -290,15 +294,15 @@ mod tests { impl CipherSuite for Default { #[cfg(feature = "ristretto255")] - type OprfGroup = crate::Ristretto255; + type OprfCs = crate::Ristretto255; #[cfg(not(feature = "ristretto255"))] - type OprfGroup = ::p256::NistP256; + type OprfCs = ::p256::NistP256; #[cfg(feature = "ristretto255")] type KeGroup = crate::Ristretto255; #[cfg(not(feature = "ristretto255"))] type KeGroup = ::p256::NistP256; - type KeyExchange = crate::key_exchange::tripledh::TripleDH; - type SlowHash = crate::slow_hash::NoOpHash; + type KeyExchange = crate::key_exchange::tripledh::TripleDh; + type Ksf = crate::ksf::Identity; } type KeCurve = ::KeGroup; diff --git a/src/slow_hash.rs b/src/ksf.rs similarity index 75% rename from src/slow_hash.rs rename to src/ksf.rs index 7ee63a2..9aacc9e 100644 --- a/src/slow_hash.rs +++ b/src/ksf.rs @@ -5,15 +5,15 @@ // License, Version 2.0 found in the LICENSE-APACHE file in the root directory // of this source tree. -//! Trait specifying a slow hashing function +//! Trait specifying a key stretching function use generic_array::{ArrayLength, GenericArray}; use crate::errors::InternalError; -/// Used for the slow hashing function in OPAQUE -pub trait SlowHash: Default { - /// Computes the slow hashing function +/// Used for the key stretching function in OPAQUE +pub trait Ksf: Default { + /// Computes the key stretching function fn hash>( &self, input: GenericArray, @@ -22,9 +22,9 @@ pub trait SlowHash: Default { /// A no-op hash which simply returns its input #[derive(Default)] -pub struct NoOpHash; +pub struct Identity; -impl SlowHash for NoOpHash { +impl Ksf for Identity { fn hash>( &self, input: GenericArray, @@ -33,15 +33,15 @@ impl SlowHash for NoOpHash { } } -#[cfg(feature = "slow-hash")] -impl SlowHash for argon2::Argon2<'_> { +#[cfg(feature = "argon2")] +impl Ksf for argon2::Argon2<'_> { fn hash>( &self, input: GenericArray, ) -> Result, InternalError> { let mut output = GenericArray::default(); self.hash_password_into(&input, &[0; argon2::MIN_SALT_LEN], &mut output) - .map_err(|_| InternalError::SlowHashError)?; + .map_err(|_| InternalError::KsfError)?; Ok(output) } } diff --git a/src/lib.rs b/src/lib.rs index 1c4d457..7a101f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,26 +26,26 @@ //! * for the key exchange //! * a key exchange protocol, //! * a hashing function, and -//! * a slow hashing function. +//! * a key stretching function. //! //! We will use the following choices in this example: //! ```ignore //! use opaque_ke::CipherSuite; //! struct Default; //! impl CipherSuite for Default { -//! type OprfGroup = opaque_ke::Ristretto255; +//! type OprfCs = opaque_ke::Ristretto255; //! type KeGroup = opaque_ke::Ristretto255; -//! type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! type Ksf = opaque_ke::ksf::Identity; //! } //! ``` //! See [examples/simple_login.rs](https://github.com/novifinancial/opaque-ke/blob/main/examples/simple_login.rs) //! for a working example of a simple password-based login using OPAQUE. //! -//! Note that our choice of slow hashing function in this example, `NoOpHash`, +//! Note that our choice of key stretching function in this example, `Identity`, //! is selected only to ensure that the tests execute quickly. A real -//! application should use an actual slow hashing function, such as `Argon2`, -//! which can be enabled through the `slow-hash` feature. See more details in +//! application should use an actual key stretching function, such as `Argon2`, +//! which can be enabled through the `argon2` feature. See more details in //! the [features](#features) section. //! //! ## Setup @@ -58,17 +58,17 @@ //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! use rand::rngs::OsRng; //! use rand::RngCore; @@ -101,23 +101,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ServerRegistration, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! use opaque_ke::ClientRegistration; //! use rand::rngs::OsRng; @@ -139,23 +139,23 @@ //! # errors::ProtocolError, //! # ClientRegistration, //! # ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -186,23 +186,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -234,23 +234,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -287,23 +287,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ServerRegistration, ServerLogin, CredentialFinalization, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! use opaque_ke::ClientLogin; @@ -324,23 +324,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, CredentialFinalization, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -387,23 +387,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -443,23 +443,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -539,23 +539,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -619,15 +619,15 @@ //! [ClientRegistration::start] and [ClientLogin::start]. //! //! The export key retains as much secrecy as the password itself, and is -//! similarly derived through an evaluation of the slow hashing function. Hence, -//! only the parties which know the password the client uses during registration -//! and login can recover this secret, as it is never exposed to the server. As -//! a result, the export key can be used (separately from the OPAQUE protocol) -//! to provide confidentiality and integrity to other data which only the client -//! should be able to process. For instance, if the server is expected to -//! maintain any client-side secrets which require a password to access, then -//! this export key can be used to encrypt these secrets so that they remain -//! hidden from the server (see [examples/digital_locker.rs](https://github.com/novifinancial/opaque-ke/blob/main/examples/digital_locker.rs) +//! similarly derived through an evaluation of the key stretching function. +//! Hence, only the parties which know the password the client uses during +//! registration and login can recover this secret, as it is never exposed to +//! the server. As a result, the export key can be used (separately from the +//! OPAQUE protocol) to provide confidentiality and integrity to other data +//! which only the client should be able to process. For instance, if the server +//! is expected to maintain any client-side secrets which require a password to +//! access, then this export key can be used to encrypt these secrets so that +//! they remain hidden from the server (see [examples/digital_locker.rs](https://github.com/novifinancial/opaque-ke/blob/main/examples/digital_locker.rs) //! for a working example). //! //! You can access the export key from the `export_key` field of @@ -636,23 +636,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -717,23 +717,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, Identifiers, ServerRegistration, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -765,23 +765,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, CredentialFinalization, Identifiers, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -824,23 +824,23 @@ //! # use opaque_ke::{ //! # errors::ProtocolError, //! # ClientRegistration, ClientRegistrationFinishParameters, ServerRegistration, ClientLogin, ClientLoginFinishParameters, Identifiers, ServerLogin, ServerLoginStartParameters, CredentialFinalization, ServerSetup, -//! # slow_hash::NoOpHash, +//! # ksf::Identity, //! # }; //! # use opaque_ke::CipherSuite; //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # use rand::{rngs::OsRng, RngCore}; //! # let mut client_rng = OsRng; @@ -926,17 +926,17 @@ //! # struct Default; //! # #[cfg(feature = "ristretto255")] //! # impl CipherSuite for Default { -//! # type OprfGroup = opaque_ke::Ristretto255; +//! # type OprfCs = opaque_ke::Ristretto255; //! # type KeGroup = opaque_ke::Ristretto255; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[cfg(not(feature = "ristretto255"))] //! # impl CipherSuite for Default { -//! # type OprfGroup = p256::NistP256; +//! # type OprfCs = p256::NistP256; //! # type KeGroup = p256::NistP256; -//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH; -//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDh; +//! # type Ksf = opaque_ke::ksf::Identity; //! # } //! # #[derive(Debug)] //! # struct YourRemoteKeyError; @@ -944,7 +944,7 @@ //! # struct YourRemoteKey(<::KeGroup as KeGroup>::Sk); //! # impl YourRemoteKey { //! # fn diffie_hellman(&self, pk: &[u8]) -> Result::KeGroup as KeGroup>::PkLen>, YourRemoteKeyError> { todo!() } -//! # fn public_key(&self) -> Result::KeGroup as KeGroup>::PkLen>, YourRemoteKeyError> { Ok(<::KeGroup>::serialize_pk(&<::KeGroup>::public_key(&self.0))) } +//! # fn public_key(&self) -> Result::KeGroup as KeGroup>::PkLen>, YourRemoteKeyError> { Ok(<::KeGroup>::serialize_pk(<::KeGroup>::public_key(self.0))) } //! # } //! impl SecretKey<::KeGroup> for YourRemoteKey { //! type Error = YourRemoteKeyError; @@ -954,13 +954,13 @@ //! &self, //! pk: PublicKey<::KeGroup>, //! ) -> Result::KeGroup as KeGroup>::PkLen>, InternalError> { -//! YourRemoteKey::diffie_hellman(self, &pk.to_bytes()).map_err(InternalError::Custom) +//! YourRemoteKey::diffie_hellman(self, &pk.serialize()).map_err(InternalError::Custom) //! } //! //! fn public_key( //! &self //! ) -> Result::KeGroup>, InternalError> { -//! PublicKey::from_bytes(&YourRemoteKey::public_key(self).map_err(InternalError::Custom)?).map_err(InternalError::into_custom) +//! PublicKey::deserialize(&YourRemoteKey::public_key(self).map_err(InternalError::Custom)?).map_err(InternalError::into_custom) //! } //! //! fn serialize(&self) -> GenericArray { @@ -981,12 +981,12 @@ //! //! # Features //! -//! - The `slow-hash` feature, when enabled, introduces a dependency on `argon2` -//! and implements the `SlowHash` trait for `Argon2` with a set of default parameters. +//! - The `argon2` feature, when enabled, introduces a dependency on `argon2` +//! and implements the `Ksf` trait for `Argon2` with a set of default parameters. //! In general, secure instantiations should choose to invoke a memory-hard password //! hashing function when the client's password is expected to have low entropy, -//! instead of relying on [slow_hash::NoOpHash] as done in the above example. The -//! more computationally intensive the `SlowHash` function is, the more resistant +//! instead of relying on [ksf::Identity] as done in the above example. The +//! more computationally intensive the `Ksf` function is, the more resistant //! the server's password file records will be against offline dictionary and precomputation //! attacks; see [the OPAQUE paper](https://eprint.iacr.org/2018/163.pdf) for //! more details. @@ -995,24 +995,24 @@ //! //! - The backend features are re-exported from [curve25519-dalek](https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features) //! and allow for selecting the corresponding backend for the curve arithmetic -//! used. The `ristretto255_u64` feature is included as the default. Other -//! features are mapped as `ristretto255_u32`, `ristretto255_fiat_u64` and -//! `ristretto255_fiat_u32`. Any `ristretto255_*` backend feature will enable +//! used. The `ristretto255-u64` feature is included as the default. Other +//! features are mapped as `ristretto255-u32`, `ristretto255-fiat-u64` and +//! `ristretto255-fiat-u32`. Any `ristretto255-*` backend feature will enable //! the `ristretto255` feature, which can be used too, but keep in mind that //! `curve25519-dalek` will fail to compile without a selected backend. This -//! enables the use of [`Ristretto255`] as a `KeGroup` and `OprfGroup`. +//! enables the use of [`Ristretto255`] as a `KeGroup` and `OprfCs`. //! //! - The `x25519` feature is similar to the `ristretto255` feature and requires -//! to select a backend like `x25519_u64`, other backends are the same as in -//! `ristretto255_*`. This enables [`X25519`] as a `KeGroup`. +//! to select a backend like `x25519-u64`, other backends are the same as in +//! `ristretto255-*`. This enables [`X25519`] as a `KeGroup`. //! -//! - The `ristretto255_simd` feature is re-exported from [curve25519-dalek](https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features) +//! - The `ristretto255-simd` feature is re-exported from [curve25519-dalek](https://doc.dalek.rs/curve25519_dalek/index.html#backends-and-features) //! and enables parallel formulas, using either AVX2 or AVX512-IFMA. This will -//! automatically enable the `ristretto255_u64` feature and requires Rust +//! automatically enable the `ristretto255-u64` feature and requires Rust //! nightly. //! //! - The `p256` feature enables the use of [`p256::NistP256`] as a `KeGroup` -//! and a `OprfGroup` for `CipherSuite`. +//! and a `OprfCs` for `CipherSuite`. //! //! - The `bench` feature is used only for running performance benchmarks for //! this implementation. @@ -1022,25 +1022,27 @@ #![cfg_attr(not(test), deny(unsafe_code))] #![no_std] #![warn(clippy::cargo, missing_docs)] -#![allow(clippy::multiple_crate_versions, type_alias_bounds)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![allow(type_alias_bounds)] #[cfg(any(feature = "std", test))] extern crate std; +#[cfg(feature = "serde")] +extern crate serde_ as serde; + // Error types pub mod errors; -#[macro_use] -mod impls; pub mod ciphersuite; mod envelope; pub mod hash; pub mod key_exchange; pub mod keypair; +pub mod ksf; mod messages; mod opaque; mod serialization; -pub mod slow_hash; mod util; #[cfg(test)] diff --git a/src/messages.rs b/src/messages.rs index 282e3f6..c1fa4e9 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -18,7 +18,6 @@ use generic_array::{ArrayLength, GenericArray}; use rand::{CryptoRng, RngCore}; use subtle::ConstantTimeEq; use voprf::Group; -use zeroize::{Zeroize, ZeroizeOnDrop}; use crate::ciphersuite::{CipherSuite, OprfGroup, OprfHash}; use crate::envelope::{Envelope, EnvelopeLen}; @@ -27,7 +26,7 @@ use crate::errors::ProtocolError; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::key_exchange::traits::{ - FromBytes, Ke1MessageLen, Ke2MessageLen, Ke3MessageLen, KeyExchange, ToBytes, + Deserialize, Ke1MessageLen, Ke2MessageLen, Ke3MessageLen, KeyExchange, Serialize, }; use crate::key_exchange::tripledh::NonceLen; use crate::keypair::{PublicKey, SecretKey}; @@ -39,8 +38,13 @@ use crate::opaque::{MaskedResponse, MaskedResponseLen, ServerSetup}; //////////////////////////// /// The message sent by the client to the server, to initiate registration +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") +)] #[derive_where(Clone)] -#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; voprf::BlindedElement)] +#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; voprf::BlindedElement)] pub struct RegistrationRequest where as OutputSizeUser>::OutputSize: @@ -51,15 +55,18 @@ where Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { /// blinded password information - pub(crate) blinded_element: voprf::BlindedElement, + pub(crate) blinded_element: voprf::BlindedElement, } -impl_serialize_and_deserialize_for!(RegistrationRequest); - /// The answer sent by the server to the user, upon reception of the /// registration attempt +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") +)] #[derive_where(Clone)] -#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; voprf::EvaluationElement, ::Pk)] +#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; voprf::EvaluationElement, ::Pk)] pub struct RegistrationResponse where as OutputSizeUser>::OutputSize: @@ -70,22 +77,19 @@ where Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { /// The server's oprf output - pub(crate) evaluation_element: voprf::EvaluationElement, + pub(crate) evaluation_element: voprf::EvaluationElement, /// Server's static public key pub(crate) server_s_pk: PublicKey, } -impl_serialize_and_deserialize_for!( - RegistrationResponse - where - // RegistrationResponse: KgPk + KePk - as Group>::ElemLen: Add<::PkLen>, - RegistrationResponseLen: ArrayLength, -); - /// The final message from the client, containing sealed cryptographic /// identifiers -#[derive_where(Clone)] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") +)] +#[derive_where(Clone, ZeroizeOnDrop)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; ::Pk)] pub struct RegistrationUpload where @@ -105,49 +109,24 @@ where pub(crate) client_s_pk: PublicKey, } -impl Drop for RegistrationUpload -where - as OutputSizeUser>::OutputSize: - IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, - OprfHash: Hash, - as CoreProxy>::Core: ProxyHash, - < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, - Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, -{ - fn drop(&mut self) { - self.masking_key.zeroize(); - } -} - -impl ZeroizeOnDrop for RegistrationUpload -where - as OutputSizeUser>::OutputSize: - IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, - OprfHash: Hash, - as CoreProxy>::Core: ProxyHash, - < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, - Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, -{ -} - -impl_serialize_and_deserialize_for!( - RegistrationUpload - where - // Envelope: Nonce + Hash - NonceLen: Add>>, - EnvelopeLen: ArrayLength, - // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add>>, - Sum<::PkLen, OutputSize>>: - ArrayLength | Add>, - RegistrationUploadLen: ArrayLength, -); - /// The message sent by the user to the server, to initiate registration +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde( + bound( + deserialize = ", \ + CS::KeGroup>>::KE1Message: serde::Deserialize<'de>", + serialize = ", CS::KeGroup>>::KE1Message: \ + serde::Serialize" + ), + crate = "serde" + ) +)] #[derive_where(Clone, ZeroizeOnDrop)] #[derive_where( Debug, Eq, Hash, PartialEq; - voprf::BlindedElement, + voprf::BlindedElement, , CS::KeGroup>>::KE1Message, )] pub struct CredentialRequest @@ -159,24 +138,29 @@ where < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { - pub(crate) blinded_element: voprf::BlindedElement, + pub(crate) blinded_element: voprf::BlindedElement, pub(crate) ke1_message: , CS::KeGroup>>::KE1Message, } -impl_serialize_and_deserialize_for!( - CredentialRequest - where - // CredentialRequest: KgPk + Ke1Message - as Group>::ElemLen: Add>, - CredentialRequestLen: ArrayLength, -); - /// The answer sent by the server to the user, upon reception of the login /// attempt +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde( + bound( + deserialize = ", \ + CS::KeGroup>>::KE2Message: serde::Deserialize<'de>", + serialize = ", CS::KeGroup>>::KE2Message: \ + serde::Serialize" + ), + crate = "serde" + ) +)] #[derive_where(Clone)] #[derive_where( Debug, Eq, Hash, PartialEq; - voprf::EvaluationElement, + voprf::EvaluationElement, , CS::KeGroup>>::KE2Message, )] pub struct CredentialResponse @@ -189,32 +173,27 @@ where Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { /// the server's oprf output - pub(crate) evaluation_element: voprf::EvaluationElement, + pub(crate) evaluation_element: voprf::EvaluationElement, pub(crate) masking_nonce: GenericArray, pub(crate) masked_response: MaskedResponse, pub(crate) ke2_message: , CS::KeGroup>>::KE2Message, } -impl_serialize_and_deserialize_for!( - CredentialResponse - where - // CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse - as Group>::ElemLen: Add, - Sum< as Group>::ElemLen, NonceLen>: - ArrayLength | Add>, - CredentialResponseWithoutKeLen: ArrayLength, - // MaskedResponse: (Nonce + Hash) + KePk - NonceLen: Add>>, - Sum>>: - ArrayLength | Add<::PkLen>, - MaskedResponseLen: ArrayLength, - // CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message - CredentialResponseWithoutKeLen: Add>, - CredentialResponseLen: ArrayLength, -); - /// The answer sent by the client to the server, upon reception of the sealed /// envelope +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde( + bound( + deserialize = ", \ + CS::KeGroup>>::KE3Message: serde::Deserialize<'de>", + serialize = ", CS::KeGroup>>::KE3Message: \ + serde::Serialize" + ), + crate = "serde" + ) +)] #[derive_where(Clone)] #[derive_where( Debug, Eq, Hash, PartialEq; @@ -232,8 +211,6 @@ where pub(crate) ke3_message: , CS::KeGroup>>::KE3Message, } -impl_serialize_and_deserialize_for!(CredentialFinalization); - //////////////////////////////// // High-level Implementations // // ========================== // @@ -253,7 +230,7 @@ where { /// Only used for testing purposes #[cfg(test)] - pub fn get_blinded_element_for_testing(&self) -> voprf::BlindedElement { + pub fn get_blinded_element_for_testing(&self) -> voprf::BlindedElement { self.blinded_element.clone() } @@ -291,7 +268,7 @@ where RegistrationResponseLen: ArrayLength, { as Group>::serialize_elem(self.evaluation_element.value()) - .concat(self.server_s_pk.to_bytes()) + .concat(self.server_s_pk.serialize()) } /// Deserialization from bytes @@ -347,7 +324,7 @@ where RegistrationUploadLen: ArrayLength, { self.client_s_pk - .to_bytes() + .serialize() .concat(self.masking_key.clone()) .concat(self.envelope.serialize()) } @@ -405,7 +382,7 @@ where CredentialRequestLen: ArrayLength, { as Group>::serialize_elem(self.blinded_element.value()) - .concat(self.ke1_message.to_bytes()) + .concat(self.ke1_message.serialize()) } pub(crate) fn serialize_iter<'a>( @@ -424,7 +401,7 @@ where // Check that the message is actually containing an element of the correct // subgroup let blinded_element = - voprf::BlindedElement::::deserialize(&checked_slice[..elem_len])?; + voprf::BlindedElement::::deserialize(&checked_slice[..elem_len])?; // Throw an error if the identity group element is encountered if bool::from( as Group>::identity_elem().ct_eq(&blinded_element.value())) { @@ -432,7 +409,7 @@ where } let ke1_message = - , CS::KeGroup>>::KE1Message::from_bytes( + , CS::KeGroup>>::KE1Message::deserialize( &checked_slice[elem_len..], )?; @@ -444,7 +421,7 @@ where /// Only used for testing purposes #[cfg(test)] - pub fn get_blinded_element_for_testing(&self) -> voprf::BlindedElement { + pub fn get_blinded_element_for_testing(&self) -> voprf::BlindedElement { self.blinded_element.clone() } } @@ -485,7 +462,7 @@ where as Group>::serialize_elem(self.evaluation_element.value()) .concat(self.masking_nonce) .concat(self.masked_response.serialize()) - .concat(self.ke2_message.to_bytes()) + .concat(self.ke2_message.serialize()) } pub(crate) fn serialize_without_ke<'a>( @@ -516,8 +493,7 @@ where // Check that the message is actually containing an element of the correct // subgroup let beta_bytes = &checked_slice[..elem_len]; - let evaluation_element = - voprf::EvaluationElement::::deserialize(beta_bytes)?; + let evaluation_element = voprf::EvaluationElement::::deserialize(beta_bytes)?; // Throw an error if the identity group element is encountered if bool::from( as Group>::identity_elem().ct_eq(&evaluation_element.value())) @@ -531,7 +507,7 @@ where &checked_slice[elem_len + nonce_len..elem_len + nonce_len + masked_response_len], ); let ke2_message = - , CS::KeGroup>>::KE2Message::from_bytes( + , CS::KeGroup>>::KE2Message::deserialize( &checked_slice[elem_len + nonce_len + masked_response_len..], )?; @@ -570,13 +546,13 @@ where { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> { - self.ke3_message.to_bytes() + self.ke3_message.serialize() } /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { let ke3_message = - , CS::KeGroup>>::KE3Message::from_bytes( + , CS::KeGroup>>::KE3Message::deserialize( input, )?; Ok(Self { ke3_message }) diff --git a/src/opaque.rs b/src/opaque.rs index 03ccbae..8cf6ceb 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -27,13 +27,13 @@ use crate::errors::{InternalError, ProtocolError}; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::key_exchange::traits::{ - FromBytes, Ke1MessageLen, Ke1StateLen, Ke2StateLen, KeyExchange, ToBytes, + Deserialize, Ke1MessageLen, Ke1StateLen, Ke2StateLen, KeyExchange, Serialize, }; use crate::key_exchange::tripledh::NonceLen; use crate::keypair::{KeyPair, PrivateKey, PublicKey, SecretKey}; +use crate::ksf::Ksf; use crate::messages::{CredentialRequestLen, RegistrationUploadLen}; -use crate::serialization::Serialize; -use crate::slow_hash::SlowHash; +use crate::serialization::Input; use crate::{ CredentialFinalization, CredentialRequest, CredentialResponse, RegistrationRequest, RegistrationResponse, RegistrationUpload, @@ -57,15 +57,13 @@ const STR_OPAQUE_DERIVE_KEY_PAIR: &[u8; 20] = b"OPAQUE-DeriveKeyPair"; /// The state elements the server holds upon setup #[cfg_attr( feature = "serde", - derive(serde_::Deserialize, serde_::Serialize), + derive(serde::Deserialize, serde::Serialize), serde( bound( - deserialize = "::Pk: serde_::Deserialize<'de>, ::Sk: serde_::Deserialize<'de>, S: serde_::Deserialize<'de>", - serialize = "::Pk: serde_::Serialize, ::Sk: serde_::Serialize, S: serde_::Serialize" + deserialize = "S: serde::Deserialize<'de>", + serialize = "S: serde::Serialize" ), - crate = "serde_" + crate = "serde" ) )] #[derive_where(Clone)] @@ -87,11 +85,16 @@ pub struct ServerSetup< } /// The state elements the client holds to register itself +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") +)] #[derive_where(Clone, ZeroizeOnDrop)] #[derive_where( Debug, Eq, Hash, PartialEq; - voprf::NonVerifiableClient, - voprf::BlindedElement, + voprf::NonVerifiableClient, + voprf::BlindedElement, )] pub struct ClientRegistration where @@ -102,19 +105,16 @@ where < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { - pub(crate) oprf_client: voprf::NonVerifiableClient, - pub(crate) blinded_element: voprf::BlindedElement, + pub(crate) oprf_client: voprf::NonVerifiableClient, + pub(crate) blinded_element: voprf::BlindedElement, } -impl_serialize_and_deserialize_for!( - ClientRegistration - where - // ClientRegistration: KgSk + KgPk - as Group>::ScalarLen: Add< as Group>::ElemLen>, - ClientRegistrationLen: ArrayLength, -); - /// The state elements the server holds to record a registration +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") +)] #[derive_where(Clone, ZeroizeOnDrop)] #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; ::Pk)] pub struct ServerRegistration(pub(crate) RegistrationUpload) @@ -126,25 +126,27 @@ where < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero; -impl_serialize_and_deserialize_for!( - ServerRegistration - where - // Envelope: Nonce + Hash - NonceLen: Add>>, - EnvelopeLen: ArrayLength, - // RegistrationUpload: (KePk + Hash) + Envelope - ::PkLen: Add>>, - Sum<::PkLen, OutputSize>>: - ArrayLength | Add>, - RegistrationUploadLen: ArrayLength, - // ServerRegistration = RegistrationUpload -); - /// The state elements the client holds to perform a login +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde( + bound( + deserialize = ", \ + CS::KeGroup>>::KE1Message: serde::Deserialize<'de>, , CS::KeGroup>>::KE1State: \ + serde::Deserialize<'de>", + serialize = ", CS::KeGroup>>::KE1Message: \ + serde::Serialize, , \ + CS::KeGroup>>::KE1State: serde::Serialize" + ), + crate = "serde" + ) +)] #[derive_where(Clone, ZeroizeOnDrop)] #[derive_where( Debug, Eq, Hash, PartialEq; - voprf::NonVerifiableClient, + voprf::NonVerifiableClient, , CS::KeGroup>>::KE1State, CredentialRequest, )] @@ -157,25 +159,25 @@ where < as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess, Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { - pub(crate) oprf_client: voprf::NonVerifiableClient, + pub(crate) oprf_client: voprf::NonVerifiableClient, pub(crate) ke1_state: , CS::KeGroup>>::KE1State, pub(crate) credential_request: CredentialRequest, } -impl_serialize_and_deserialize_for!( - ClientLogin - where - // CredentialRequest: KgPk + Ke1Message - as Group>::ElemLen: Add>, - CredentialRequestLen: ArrayLength, - // ClientLogin: KgSk + CredentialRequest + Ke1State - as Group>::ScalarLen: Add>, - Sum< as Group>::ScalarLen, CredentialRequestLen>: - ArrayLength | Add>, - ClientLoginLen: ArrayLength, -); - /// The state elements the server holds to record a login +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde( + bound( + deserialize = ", CS::KeGroup>>::KE2State: \ + serde::Deserialize<'de>", + serialize = ", CS::KeGroup>>::KE2State: \ + serde::Serialize" + ), + crate = "serde" + ) +)] #[derive_where(Clone, ZeroizeOnDrop)] #[derive_where( Debug, Eq, Hash, PartialEq; @@ -193,8 +195,6 @@ where ke2_state: , CS::KeGroup>>::KE2State, } -impl_serialize_and_deserialize_for!(ServerLogin); - //////////////////////////////// // High-level Implementations // // ========================== // @@ -376,7 +376,7 @@ where password, self.oprf_client.clone(), registration_response.evaluation_element, - params.slow_hash, + params.ksf, )?; let mut masking_key = Output::>::default(); @@ -450,7 +450,7 @@ where credential_identifier: &[u8], ) -> Result, ProtocolError> { let oprf_key = - oprf_key_from_seed::(&server_setup.oprf_seed, credential_identifier)?; + oprf_key_from_seed::(&server_setup.oprf_seed, credential_identifier)?; let server = voprf::NonVerifiableServer::new_with_key(&oprf_key)?; let evaluation_element = server.evaluate(&message.blinded_element, None)?; @@ -510,7 +510,7 @@ where self.oprf_client .serialize() .concat(self.credential_request.serialize()) - .concat(self.ke1_state.to_bytes()) + .concat(self.ke1_state.serialize()) } /// Deserialization from bytes @@ -522,7 +522,7 @@ where check_slice_size(input, client_len + request_len + state_len, "client_login")?; let ke1_state = - , CS::KeGroup>>::KE1State::from_bytes( + , CS::KeGroup>>::KE1State::deserialize( &checked_slice[client_len + request_len..], )?; Ok(Self { @@ -598,7 +598,7 @@ where password, self.oprf_client.clone(), credential_response.evaluation_element.clone(), - params.slow_hash, + params.ksf, )?; let mut masking_key = Output::>::default(); @@ -638,7 +638,7 @@ where let blinded_element = OprfGroup::::serialize_elem(self.credential_request.blinded_element.value()); - let ke1_message = self.credential_request.ke1_message.to_bytes(); + let ke1_message = self.credential_request.ke1_message.serialize(); let serialized_credential_request = CredentialRequest::::serialize_iter(&blinded_element, &ke1_message); @@ -682,14 +682,14 @@ where { /// Serialization into bytes pub fn serialize(&self) -> GenericArray> { - self.ke2_state.to_bytes() + self.ke2_state.serialize() } /// Deserialization from bytes pub fn deserialize(bytes: &[u8]) -> Result { Ok(Self { ke2_state: - , CS::KeGroup>>::KE2State::from_bytes( + , CS::KeGroup>>::KE2State::deserialize( bytes, )?, }) @@ -744,19 +744,19 @@ where let (id_u, id_s) = bytestrings_from_identifiers::( identifiers, - client_s_pk.to_bytes(), - server_s_pk.to_bytes(), + client_s_pk.serialize(), + server_s_pk.serialize(), ) .map_err(ProtocolError::into_custom)?; let blinded_element = OprfGroup::::serialize_elem(credential_request.blinded_element.value()); - let ke1_message = credential_request.ke1_message.to_bytes(); + let ke1_message = credential_request.ke1_message.serialize(); let credential_request_bytes = CredentialRequest::::serialize_iter(&blinded_element, &ke1_message); let oprf_key = - oprf_key_from_seed::(&server_setup.oprf_seed, credential_identifier) + oprf_key_from_seed::(&server_setup.oprf_seed, credential_identifier) .map_err(ProtocolError::into_custom)?; let server = voprf::NonVerifiableServer::new_with_key(&oprf_key) .map_err(|e| ProtocolError::into_custom(e.into()))?; @@ -847,8 +847,8 @@ where { /// Specifying the identifiers idU and idS pub identifiers: Identifiers<'i>, - /// Specifying a configuration for the slow hash - pub slow_hash: Option<&'h CS::SlowHash>, + /// Specifying a configuration for the key stretching function + pub ksf: Option<&'h CS::Ksf>, } impl<'i, 'h, CS: CipherSuite> ClientRegistrationFinishParameters<'i, 'h, CS> @@ -861,11 +861,8 @@ where Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { /// Create a new [`ClientRegistrationFinishParameters`] - pub fn new(identifiers: Identifiers<'i>, slow_hash: Option<&'h CS::SlowHash>) -> Self { - Self { - identifiers, - slow_hash, - } + pub fn new(identifiers: Identifiers<'i>, ksf: Option<&'h CS::Ksf>) -> Self { + Self { identifiers, ksf } } } @@ -968,8 +965,8 @@ where /// Specifying a user identifier and server identifier that will be matched /// against the server pub identifiers: Identifiers<'i>, - /// Specifying a configuration for the slow hash - pub slow_hash: Option<&'h CS::SlowHash>, + /// Specifying a configuration for the key stretching hash + pub ksf: Option<&'h CS::Ksf>, } impl<'c, 'i, 'h, CS: CipherSuite> ClientLoginFinishParameters<'c, 'i, 'h, CS> @@ -985,12 +982,12 @@ where pub fn new( context: Option<&'c [u8]>, identifiers: Identifiers<'i>, - slow_hash: Option<&'h CS::SlowHash>, + ksf: Option<&'h CS::Ksf>, ) -> Self { Self { context, identifiers, - slow_hash, + ksf, } } } @@ -1060,7 +1057,7 @@ pub struct ServerLoginStartParameters<'c, 'i> { #[derive_where(Clone)] #[derive_where( Debug; - voprf::EvaluationElement, + voprf::EvaluationElement, , CS::KeGroup>>::KE2Message, , CS::KeGroup>>::KE2State, )] @@ -1097,9 +1094,9 @@ where #[allow(clippy::type_complexity)] fn get_password_derived_key( input: &[u8], - oprf_client: voprf::NonVerifiableClient, - evaluation_element: voprf::EvaluationElement, - slow_hash: Option<&CS::SlowHash>, + oprf_client: voprf::NonVerifiableClient, + evaluation_element: voprf::EvaluationElement, + ksf: Option<&CS::Ksf>, ) -> Result<(Output>, Hkdf>), ProtocolError> where as OutputSizeUser>::OutputSize: @@ -1111,10 +1108,10 @@ where { 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()) + let hardened_output = if let Some(ksf) = ksf { + ksf.hash(oprf_output.clone()) } else { - CS::SlowHash::default().hash(oprf_output.clone()) + CS::Ksf::default().hash(oprf_output.clone()) } .map_err(ProtocolError::from)?; @@ -1152,6 +1149,11 @@ where )) } +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "", crate = "serde") +)] #[derive_where(Clone)] #[derive_where(Debug, Eq, Hash, PartialEq)] pub(crate) struct MaskedResponse @@ -1235,7 +1237,7 @@ where for (x1, x2) in xor_pad.iter_mut().zip( server_s_pk - .to_bytes() + .serialize() .as_slice() .iter() .chain(envelope.serialize().iter()), @@ -1287,16 +1289,16 @@ pub(crate) fn bytestrings_from_identifiers( ids: Identifiers, client_s_pk: GenericArray, server_s_pk: GenericArray, -) -> Result<(Serialize, Serialize), ProtocolError> { +) -> Result<(Input, Input), ProtocolError> { let client_identity = if let Some(client) = ids.client { - Serialize::::from(client)? + Input::::from(client)? } else { - Serialize::::from_owned(client_s_pk)? + Input::::from_owned(client_s_pk)? }; let server_identity = if let Some(server) = ids.server { - Serialize::::from(server)? + Input::::from(server)? } else { - Serialize::::from_owned(server_s_pk)? + Input::::from_owned(server_s_pk)? }; Ok((client_identity, server_identity)) @@ -1308,7 +1310,7 @@ pub(crate) fn bytestrings_from_identifiers( fn blind( rng: &mut R, password: &[u8], -) -> Result, voprf::Error> +) -> Result, voprf::Error> where as OutputSizeUser>::OutputSize: IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, diff --git a/src/serialization/mod.rs b/src/serialization/mod.rs index 81060f9..a530508 100644 --- a/src/serialization/mod.rs +++ b/src/serialization/mod.rs @@ -45,38 +45,34 @@ pub(crate) fn os2ip(input: &[u8]) -> Result { /// Computes `I2OSP(len(input), max_bytes) || input` and helps hold output /// without allocation. -pub(crate) struct Serialize< - 'a, - L1: ArrayLength, - L2: ArrayLength = U0, - L3: ArrayLength = U0, -> { +pub(crate) struct Input<'a, L1: ArrayLength, L2: ArrayLength = U0, L3: ArrayLength = U0> +{ octet: GenericArray, - input: Input<'a, L2, L3>, + input: InnerInput<'a, L2, L3>, } -enum Input<'a, L1: ArrayLength, L2: ArrayLength> { +enum InnerInput<'a, L1: ArrayLength, L2: ArrayLength> { Owned(GenericArray), Borrowed(&'a [u8]), Label(([&'a [u8]; 2], PhantomData)), } -impl<'a, L1: ArrayLength, L2: ArrayLength, L3: ArrayLength> Serialize<'a, L1, L2, L3> { +impl<'a, L1: ArrayLength, L2: ArrayLength, L3: ArrayLength> Input<'a, L1, L2, L3> { // Variation of `serialize` that takes a borrowed `input - pub(crate) fn from(input: &'a [u8]) -> Result, ProtocolError> { - Ok(Serialize { + pub(crate) fn from(input: &'a [u8]) -> Result, ProtocolError> { + Ok(Input { octet: i2osp::(input.len())?, - input: Input::Borrowed(input), + input: InnerInput::Borrowed(input), }) } // Variation of `serialize` that takes an owned `input` pub(crate) fn from_owned( input: GenericArray, - ) -> Result, ProtocolError> { - Ok(Serialize { + ) -> Result, ProtocolError> { + Ok(Input { octet: i2osp::(input.len())?, - input: Input::Owned(input), + input: InnerInput::Owned(input), }) } @@ -84,10 +80,10 @@ impl<'a, L1: ArrayLength, L2: ArrayLength, L3: ArrayLength> Serializ pub(crate) fn from_label( opaque: &'a [u8], label: &'a [u8], - ) -> Result, ProtocolError> { - Ok(Serialize { + ) -> Result, ProtocolError> { + Ok(Input { octet: i2osp::(opaque.len() + label.len())?, - input: Input::Label(([opaque, label], PhantomData)), + input: InnerInput::Label(([opaque, label], PhantomData)), }) } @@ -96,11 +92,11 @@ impl<'a, L1: ArrayLength, L2: ArrayLength, L3: ArrayLength> Serializ [self.octet.as_slice()] .into_iter() .chain(match &self.input { - Input::Owned(bytes) => [bytes.as_slice()], - Input::Borrowed(bytes) => [*bytes], - Input::Label((iter, _)) => [iter[0]], + InnerInput::Owned(bytes) => [bytes.as_slice()], + InnerInput::Borrowed(bytes) => [*bytes], + InnerInput::Label((iter, _)) => [iter[0]], }) - .chain(if let Input::Label((iter, _)) = &self.input { + .chain(if let InnerInput::Label((iter, _)) = &self.input { Some(iter[1]) } else { None @@ -108,11 +104,11 @@ impl<'a, L1: ArrayLength, L2: ArrayLength, L3: ArrayLength> Serializ } } -impl<'a, L1: ArrayLength, L2: ArrayLength> Serialize<'a, L1, L2, U0> { +impl<'a, L1: ArrayLength, L2: ArrayLength> Input<'a, L1, L2, U0> { pub(crate) fn to_array_2(&self) -> [&[u8]; 2] { let input = match &self.input { - Input::Borrowed(value) => value, - Input::Owned(value) => value.as_slice(), + InnerInput::Borrowed(value) => value, + InnerInput::Owned(value) => value.as_slice(), _ => unreachable!("unexpected `Serialize` constructed with wrong generics"), }; @@ -120,10 +116,10 @@ impl<'a, L1: ArrayLength, L2: ArrayLength> Serialize<'a, L1, L2, U0> { } } -impl<'a, L1: ArrayLength, L2: ArrayLength> Serialize<'a, L1, L2, U2> { +impl<'a, L1: ArrayLength, L2: ArrayLength> Input<'a, L1, L2, U2> { pub(crate) fn to_array_3(&self) -> [&[u8]; 3] { match self.input { - Input::Label((label, _)) => [self.octet.as_slice(), label[0], label[1]], + InnerInput::Label((label, _)) => [self.octet.as_slice(), label[0], label[1]], _ => unreachable!("unexpected `Serialize` constructed with wrong generics"), } } diff --git a/src/serialization/tests.rs b/src/serialization/tests.rs index 4d68dbd..500245f 100644 --- a/src/serialization/tests.rs +++ b/src/serialization/tests.rs @@ -25,9 +25,9 @@ use crate::errors::*; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::key_exchange::traits::{ - FromBytes, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, ToBytes, + Deserialize, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, Serialize, }; -use crate::key_exchange::tripledh::{NonceLen, TripleDH}; +use crate::key_exchange::tripledh::{NonceLen, TripleDh}; use crate::keypair::{KeyPair, SecretKey}; use crate::messages::CredentialResponseWithoutKeLen; use crate::opaque::{ClientLoginLen, ClientRegistrationLen, MaskedResponseLen}; @@ -39,19 +39,19 @@ struct Ristretto255; #[cfg(feature = "ristretto255")] impl CipherSuite for Ristretto255 { - type OprfGroup = crate::Ristretto255; + type OprfCs = crate::Ristretto255; type KeGroup = crate::Ristretto255; - type KeyExchange = TripleDH; - type SlowHash = crate::slow_hash::NoOpHash; + type KeyExchange = TripleDh; + type Ksf = crate::ksf::Identity; } struct P256; impl CipherSuite for P256 { - type OprfGroup = ::p256::NistP256; + type OprfCs = ::p256::NistP256; type KeGroup = ::p256::NistP256; - type KeyExchange = TripleDH; - type SlowHash = crate::slow_hash::NoOpHash; + type KeyExchange = TripleDh; + type Ksf = crate::ksf::Identity; } fn random_point() -> ::Pk @@ -65,7 +65,7 @@ where { let mut rng = OsRng; let sk = CS::KeGroup::random_sk(&mut rng); - CS::KeGroup::public_key(&sk) + CS::KeGroup::public_key(sk) } #[test] @@ -85,7 +85,7 @@ fn client_registration_roundtrip() -> Result<(), ProtocolError> { let pw = b"hunter2"; let mut rng = OsRng; - let blind_result = &voprf::NonVerifiableClient::::blind(pw, &mut rng)?; + let blind_result = &voprf::NonVerifiableClient::::blind(pw, &mut rng)?; let bytes: Vec = blind_result .state @@ -145,7 +145,7 @@ fn server_registration_roundtrip() -> Result<(), ProtocolError> { let mock_client_kp = KeyPair::::generate_random(&mut rng); // serialization order: oprf_key, public key, envelope let mut bytes = Vec::::new(); - bytes.extend_from_slice(&mock_client_kp.public().to_bytes()); + bytes.extend_from_slice(&mock_client_kp.public().serialize()); bytes.extend_from_slice(&masking_key); bytes.extend_from_slice(&mock_envelope_bytes); let reg = ServerRegistration::::deserialize(&bytes)?; @@ -173,7 +173,7 @@ fn registration_request_roundtrip() -> Result<(), ProtocolError> { Le<< as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero, { let pt = random_point::(); - let pt_bytes = CS::KeGroup::serialize_pk(&pt); + let pt_bytes = CS::KeGroup::serialize_pk(pt); let mut input = Vec::new(); input.extend_from_slice(&pt_bytes); @@ -218,10 +218,10 @@ fn registration_response_roundtrip() -> Result<(), ProtocolError> { RegistrationResponseLen: ArrayLength, { let pt = random_point::(); - let beta_bytes = CS::KeGroup::serialize_pk(&pt); + let beta_bytes = CS::KeGroup::serialize_pk(pt); let mut rng = OsRng; let skp = KeyPair::::generate_random(&mut rng); - let pubkey_bytes = skp.public().to_bytes(); + let pubkey_bytes = skp.public().serialize(); let mut input = Vec::new(); input.extend_from_slice(&beta_bytes); @@ -275,7 +275,7 @@ fn registration_upload_roundtrip() -> Result<(), ProtocolError> { { let mut rng = OsRng; let skp = KeyPair::::generate_random(&mut rng); - let pubkey_bytes = skp.public().to_bytes(); + let pubkey_bytes = skp.public().serialize(); let mut key = [0u8; 32]; rng.fill_bytes(&mut key); @@ -331,7 +331,7 @@ fn credential_request_roundtrip() -> Result<(), ProtocolError> { { let mut rng = OsRng; let alpha = random_point::(); - let alpha_bytes = CS::KeGroup::serialize_pk(&alpha); + let alpha_bytes = CS::KeGroup::serialize_pk(alpha); let client_e_kp = KeyPair::::generate_random(&mut rng); let mut client_nonce = [0u8; NonceLen::USIZE]; @@ -339,7 +339,7 @@ fn credential_request_roundtrip() -> Result<(), ProtocolError> { let ke1m: Vec = [ client_nonce.as_ref(), - client_e_kp.public().to_bytes().as_ref(), + client_e_kp.public().serialize().as_ref(), ] .concat(); @@ -397,7 +397,7 @@ fn credential_response_roundtrip() -> Result<(), ProtocolError> { CredentialResponseLen: ArrayLength, { let pt = random_point::(); - let pt_bytes = CS::KeGroup::serialize_pk(&pt); + let pt_bytes = CS::KeGroup::serialize_pk(pt); let mut rng = OsRng; @@ -416,7 +416,7 @@ fn credential_response_roundtrip() -> Result<(), ProtocolError> { let ke2m: Vec = [ server_nonce.as_ref(), - server_e_kp.public().to_bytes().as_ref(), + server_e_kp.public().serialize().as_ref(), &mac, ] .concat(); @@ -523,15 +523,15 @@ fn client_login_roundtrip() -> Result<(), ProtocolError> { ] .concat(); - let blind_result = voprf::NonVerifiableClient::::blind(pw, &mut rng)?; + let blind_result = voprf::NonVerifiableClient::::blind(pw, &mut rng)?; let credential_request = CredentialRequest:: { blinded_element: blind_result.message, ke1_message: - , CS::KeGroup>>::KE1Message::from_bytes( + , CS::KeGroup>>::KE1Message::deserialize( &[ client_nonce.as_ref(), - client_e_kp.public().to_bytes().as_ref(), + client_e_kp.public().serialize().as_ref(), ] .concat(), )?, @@ -577,14 +577,14 @@ fn ke1_message_roundtrip() -> Result<(), ProtocolError> { let ke1m = [ client_nonce.as_slice(), - client_e_kp.public().to_bytes().as_ref(), + client_e_kp.public().serialize().as_ref(), ] .concat(); let reg = - , CS::KeGroup>>::KE1Message::from_bytes( + , CS::KeGroup>>::KE1Message::deserialize( &ke1m, )?; - let reg_bytes = reg.to_bytes(); + let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, ke1m); Ok(()) @@ -618,16 +618,16 @@ fn ke2_message_roundtrip() -> Result<(), ProtocolError> { let ke2m: Vec = [ server_nonce.as_slice(), - server_e_kp.public().to_bytes().as_ref(), + server_e_kp.public().serialize().as_ref(), &mac, ] .concat(); let reg = - , CS::KeGroup>>::KE2Message::from_bytes( + , CS::KeGroup>>::KE2Message::deserialize( &ke2m, )?; - let reg_bytes = reg.to_bytes(); + let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, ke2m); Ok(()) @@ -658,10 +658,10 @@ fn ke3_message_roundtrip() -> Result<(), ProtocolError> { let ke3m: Vec = [mac].concat(); let reg = - , CS::KeGroup>>::KE3Message::from_bytes( + , CS::KeGroup>>::KE3Message::deserialize( &ke3m, )?; - let reg_bytes = reg.to_bytes(); + let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, ke3m); Ok(()) diff --git a/src/tests/full_test.rs b/src/tests/full_test.rs index fe3a00b..a158090 100644 --- a/src/tests/full_test.rs +++ b/src/tests/full_test.rs @@ -27,14 +27,14 @@ use crate::errors::*; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::key_exchange::traits::{Ke1MessageLen, Ke1StateLen, Ke2MessageLen}; -use crate::key_exchange::tripledh::{NonceLen, TripleDH}; +use crate::key_exchange::tripledh::{NonceLen, TripleDh}; use crate::keypair::SecretKey; +use crate::ksf::Identity; use crate::messages::{ CredentialRequestLen, CredentialResponseLen, CredentialResponseWithoutKeLen, RegistrationResponseLen, RegistrationUploadLen, }; use crate::opaque::*; -use crate::slow_hash::NoOpHash; use crate::tests::mock_rng::CycleRng; use crate::*; @@ -46,19 +46,19 @@ struct Ristretto255; #[cfg(feature = "ristretto255")] impl CipherSuite for Ristretto255 { - type OprfGroup = crate::Ristretto255; + type OprfCs = crate::Ristretto255; type KeGroup = crate::Ristretto255; - type KeyExchange = TripleDH; - type SlowHash = NoOpHash; + type KeyExchange = TripleDh; + type Ksf = Identity; } struct P256; impl CipherSuite for P256 { - type OprfGroup = p256::NistP256; + type OprfCs = p256::NistP256; type KeGroup = p256::NistP256; - type KeyExchange = TripleDH; - type SlowHash = NoOpHash; + type KeyExchange = TripleDh; + type Ksf = Identity; } #[cfg(all(feature = "x25519", feature = "ristretto255"))] @@ -66,10 +66,10 @@ struct X25519Ristretto255; #[cfg(all(feature = "x25519", feature = "ristretto255"))] impl CipherSuite for X25519Ristretto255 { - type OprfGroup = crate::Ristretto255; + type OprfCs = crate::Ristretto255; type KeGroup = crate::X25519; - type KeyExchange = TripleDH; - type SlowHash = NoOpHash; + type KeyExchange = TripleDh; + type Ksf = Identity; } #[cfg(feature = "x25519")] @@ -77,10 +77,10 @@ struct X25519P256; #[cfg(feature = "x25519")] impl CipherSuite for X25519P256 { - type OprfGroup = p256::NistP256; + type OprfCs = p256::NistP256; type KeGroup = crate::X25519; - type KeyExchange = TripleDH; - type SlowHash = NoOpHash; + type KeyExchange = TripleDh; + type Ksf = Identity; } pub struct TestVectorParameters { @@ -200,76 +200,76 @@ static TEST_VECTOR_P256: &str = r#" #[cfg(all(feature = "x25519", feature = "ristretto255"))] static TEST_VECTOR_X25519_RISTRETTO255: &str = r#" { - "client_s_pk": "4df1ab49521829e233f34b412d48598d046afa20156f117898b7809b070ab526", - "client_s_sk": "9055cba6082b86d8856b8ac3720c16a7ca07ff3303874149a0b5656e391bb05a", - "client_e_pk": "9bbea5c768383168e385d895007f3eba4ecfbcadef26305449a76b2440465e3d", - "client_e_sk": "388fac72f9c2e9aeeb189963015f7af1692a4a31fefaf06b4ecb66d066d9fe43", - "server_s_pk": "f2f02607a409b5de08ee6e1e51ae674462397997682ea7c48c2d3c762378075b", - "server_s_sk": "c06fed7591d65aa5f6a23cda5d53bde59707bc2d62c2ba61382380b77cae497a", - "server_e_pk": "ee5251c72b241bfa4d926fed7d5082ee31a406e622731550912ac0fce105515f", - "server_e_sk": "b018aa7067155ce9bb6d2fdbc163e706888d8e0cdff1e47f45073556abc8da5a", - "fake_sk": "b8c3c7caec7ef8985a8c84dc183d98e2dbc9c30bd13b86e9c37c810fa0e1cc5e", + "client_s_pk": "f0f51a83591f6749ddfd56c78d9aaa672908713c5fcc8670b3e7341c84218c78", + "client_s_sk": "b4a46dc06b981100c15529e4675babe4ed05444de2fd4fc7dba6d3aaf9fca40a", + "client_e_pk": "cba41b4605abd945351ebbd18aa99d24b1053e70c8c010df7c454fe874b37f74", + "client_e_sk": "7afd7b93bdfff65d1162d44d550afc0b3fb7bf3a3d09ccd170d5d63c97d70c02", + "server_s_pk": "f261e911ebecac75b1a192acaf393a3541ca13572ad81d3d2729ba48718d0c77", + "server_s_sk": "3d8c12aa8f615c4133688da832f177853b7051d2ab87e8ba0c48bfeeb87f7003", + "server_e_pk": "f1ef201d97dfdc7d21a0386d20d62d2a10212586e749b06928a8d48550b04d44", + "server_e_sk": "652d258cc211026e6b1ca51a5b2b5946459bd0926d896c4c46712176d5db7507", + "fake_sk": "c93b7c3f24d51230df51bd96623fb4a142b1eccb75e0d9a9939eb0acf2e37d0b", "credential_identifier": "637265644964656e746966696572", "id_u": "696455", "id_s": "696453", "password": "70617373776f7264", - "blinding_factor": "d36ed47358b72a28796b5b0fc4f9301a294659da94d394f227e6e9b8ea277c0b", - "oprf_seed": "b430182519702493f1991bbf7506c335b5e6e3899e5f1266a7f4c99dd16bf2efab3355a7e75423c2d0e54ee7cc1c16d3fc8975e47946f4bea95a77a06bfeea7c", - "masking_nonce": "ce8202d2438b73cfe23d5f7bccc172ee6a354d690c1770ef07f4f269978bb0dbd6df845d9d9cb969ec8bf41dadef3835ba1d1dd4360b15ba5ad6cb77b9a53879", - "envelope_nonce": "04c9e2914f5874089839e78eb29d342d3c472c0bdb62e1abedf74bbf505fec79", - "client_nonce": "c01061951b0f6acc314a0cfa2f45b8f2e2125e0f1896fa63c1d97d8f74245c16", - "server_nonce": "50fe3f0de7db78443da1eadb15d36d6645ea3f94ffcc57b862befda2a9bd10a5", + "blinding_factor": "18492200ec40f425a8593c6b3f57d966785abef2e7ec77cc16dbc0112c10eb00", + "oprf_seed": "55d8b3b5c222b1b7bac76574bf13450459cbb7e8b270a58c3b584f39f0bc694df55774ff7d083c69a92f0345622bd49fefa6fe6d99456ea5f9f60c28d07ef870", + "masking_nonce": "c1b2ae7f568e055153527c75972a111525cbb50328eb90f0ed2f2a4cb770c3939b2bf94f689009928ee26af2376269515aaed6aff72c79d07a5f84aec159cb17", + "envelope_nonce": "45e9ab506171882d56a0a3017ccbe24049cd22c2ebb3519a4d1110a4f853e63d", + "client_nonce": "30f07d7239e894136324f33bbfd00f63bcd33bb255bdb072f57591d44c7a1f32", + "server_nonce": "58231100ea33e00550de7ba3b1865dceaaba3835c2ca1ef22365af068590636b", "context": "636f6e74657874", - "registration_request": "b889d6957f21a33951637b12f12007efc50d7b87811c96b8cc0072a605f1d24c", - "registration_response": "200bcd11d44e9a10541a465ed3b130d4d10632dd7433965578e33d181e321113f2f02607a409b5de08ee6e1e51ae674462397997682ea7c48c2d3c762378075b", - "registration_upload": "79d14f4164e722a8dcabffd4a341104e217d1597eeb414d4e4597d7c4376bf3b23ed2104a05b3ff4a12160f73172bbb195a3a399489bc4092e471e181a524b6c7fb6f955cacb8f8d0db54b89287b496e48b34b1a6204960925469d712c793bd89055cba6082b86d8856b8ac3720c16a7ca07ff3303874149a0b5656e391bb05a9490086c367c3705a0a46a497c797de7e67c0c7d1803e17e1cfd78d949c7b8558fa46da9fb3445bdef5e285a561e04518919387726a1b73660e687bda8a14256", - "credential_request": "b889d6957f21a33951637b12f12007efc50d7b87811c96b8cc0072a605f1d24cc01061951b0f6acc314a0cfa2f45b8f2e2125e0f1896fa63c1d97d8f74245c169bbea5c768383168e385d895007f3eba4ecfbcadef26305449a76b2440465e3d", - "credential_response": "200bcd11d44e9a10541a465ed3b130d4d10632dd7433965578e33d181e321113ce8202d2438b73cfe23d5f7bccc172ee6a354d690c1770ef07f4f269978bb0dbcc6f726f243b5a331e2a5b420866413d0e8b82f391bc4183361508a9f6c1b700e5f182630556f732e466976c2797cc5b05163ee4bb6ce39b1db500f03fe365009e359199926fad26726e438722c45f11beccc0e32e45fc24732f85d1aa9543e1d7c30248a20aad34efe89f8af3e8578071aa362564b5faba808fba9a66a78a26b018aa7067155ce9bb6d2fdbc163e706888d8e0cdff1e47f45073556abc8da5a3b9470912a8c10a2bede335ddbc1198d706acca69ae6ff0a72e195d2575f5b27b32d6099439ef55837e6e817def5ee8230ffb6fcd66d0f23f7169ab49eecfa8d134f2d6db9de03c51034b3a129f84c261234429cc34dfb7afdf3e392b7962b78", - "credential_finalization": "f4133b65451a2b8f7a9cbfaca3f7c06211912fc669ffbe7cd554905b9f4e82a0e841cc97c70c8b964e02d6f665a136db0ad83b249d4f36be4c4944c4596ac696", - "client_registration_state": "d36ed47358b72a28796b5b0fc4f9301a294659da94d394f227e6e9b8ea277c0bb889d6957f21a33951637b12f12007efc50d7b87811c96b8cc0072a605f1d24c", - "client_login_state": "d36ed47358b72a28796b5b0fc4f9301a294659da94d394f227e6e9b8ea277c0bb889d6957f21a33951637b12f12007efc50d7b87811c96b8cc0072a605f1d24cc01061951b0f6acc314a0cfa2f45b8f2e2125e0f1896fa63c1d97d8f74245c169bbea5c768383168e385d895007f3eba4ecfbcadef26305449a76b2440465e3d388fac72f9c2e9aeeb189963015f7af1692a4a31fefaf06b4ecb66d066d9fe43c01061951b0f6acc314a0cfa2f45b8f2e2125e0f1896fa63c1d97d8f74245c16", - "server_login_state": "b87047afce3cb9166d7f96a992d423f3eebb931413775c5373dc18abd6a42f919de37ca5643454b07d84440d77d364c7dd4c9029fb481aa7e34d91f061c38c2b5ba9c3260c4eb1bdfd6ef65e1415b8e227631985d979f0c5860d3076bd8f22a0e009dd6efb4359c414257678101fe91560f15b16461ca79618c09d26f346b0e9776d5589e16dc1d9466d5aa901db05d5cbeb73c2672da3b954046b170f514ce50282b8bccc1d542e902af8486fd37f886f555e56b2f34cc91d658996651eb8b8", - "password_file": "79d14f4164e722a8dcabffd4a341104e217d1597eeb414d4e4597d7c4376bf3b23ed2104a05b3ff4a12160f73172bbb195a3a399489bc4092e471e181a524b6c7fb6f955cacb8f8d0db54b89287b496e48b34b1a6204960925469d712c793bd89055cba6082b86d8856b8ac3720c16a7ca07ff3303874149a0b5656e391bb05a9490086c367c3705a0a46a497c797de7e67c0c7d1803e17e1cfd78d949c7b8558fa46da9fb3445bdef5e285a561e04518919387726a1b73660e687bda8a14256", - "export_key": "9b728dbe104caf7ea3d52a167c74408770b89f883c4ee280ee053fd9ad5aabc62bbe78cbc6bc9230819819ea75d40b8411f914095d4101c1e0d92c71b4e5b29f", - "session_key": "776d5589e16dc1d9466d5aa901db05d5cbeb73c2672da3b954046b170f514ce50282b8bccc1d542e902af8486fd37f886f555e56b2f34cc91d658996651eb8b8" + "registration_request": "68eefa968ee3ad0c69319a8f52f056df368826669cce82ad64462bc24da0787f", + "registration_response": "863ca6ef30989bec1e7411a940d589fa3e8fa3d76c8281ebb2714a6b9b3d4072f261e911ebecac75b1a192acaf393a3541ca13572ad81d3d2729ba48718d0c77", + "registration_upload": "1f658d31ac18d2d1ec1507bfd2b33c9dc5a5ec3840a87c35445be002156da95162c91ab0e7daae9e6e569e2c4ac115f770920043425e2fc941804049da6837c9537a455f91f45fd8c972a0087ec03ba8482773a0ba7dc0cb0690e94c3dabb5f7b4a46dc06b981100c15529e4675babe4ed05444de2fd4fc7dba6d3aaf9fca40a3d5d7de871613d47281ca2c105eba79f925d46b52dfd3448f9ec6acbb71e7280f8cab44110cd1ca7e0a58b25245840e6f9c8856e43c6a23aa073d23c9fcae22f", + "credential_request": "68eefa968ee3ad0c69319a8f52f056df368826669cce82ad64462bc24da0787f18492200ec40f425a8593c6b3f57d966785abef2e7ec77cc16dbc0112c10eb00a84b03fbedd2fcb1ba2b36a851028d6c3c8ad1c1a46e770efe50564ed619b216", + "credential_response": "863ca6ef30989bec1e7411a940d589fa3e8fa3d76c8281ebb2714a6b9b3d4072c1b2ae7f568e055153527c75972a111525cbb50328eb90f0ed2f2a4cb770c3931ccd09a010a76585634ae8baf2e45e1ca487e2dd695c3daac811c750da634d99307533885e23206c2ca5ad643833dad6a37312f453c84d79001b46331f14d73607da4693d6b613c9b8bb51cad8d771cbad5fcbd54742ad81df4249d2367e708027e5a52043afb985128b4050653a7028babc04234f50941ca75dbbfe9ba2556b58231100ea33e00550de7ba3b1865dceaaba3835c2ca1ef22365af068590636bed31200d916f6fa10eb164338687773d1cea70b3676973fad7c9829c3384a54bb810bd56074fa055b2f5888c9a82f4fb0771acca2e6d6934cdb5d68c480529cb110bd0c0c446680a6b0ddf3760ee9a7953931c999386f42f6df55b9c9bcd8060", + "credential_finalization": "5ba9411a863d372c2cca0e8ba1301aaa20e0ee1a68632773ca8546077409c20e10b2381aad9eae1064e1e4f40a56149da7c4e1c951245988315063b883ec659b", + "client_registration_state": "18492200ec40f425a8593c6b3f57d966785abef2e7ec77cc16dbc0112c10eb0068eefa968ee3ad0c69319a8f52f056df368826669cce82ad64462bc24da0787f", + "client_login_state": "18492200ec40f425a8593c6b3f57d966785abef2e7ec77cc16dbc0112c10eb0068eefa968ee3ad0c69319a8f52f056df368826669cce82ad64462bc24da0787f18492200ec40f425a8593c6b3f57d966785abef2e7ec77cc16dbc0112c10eb00a84b03fbedd2fcb1ba2b36a851028d6c3c8ad1c1a46e770efe50564ed619b2164a217cb91a5ecc09d5a2441dfa664c800fcb4fb5eb939ee374ddea2d1bbff10f18492200ec40f425a8593c6b3f57d966785abef2e7ec77cc16dbc0112c10eb00", + "server_login_state": "5a0ee75063406f272b70ca918fc7a3be5446007a697b77c1a1759ec0fe06879bbcb744aa60a641bead6d41877c9f4726f265a8341091f0accf54452759008e70ccf25aa19221560a3d3c4f929d6d30f2c037c9134996e1352e695152172d147c72753c5884f981f66d991c9361082950eb8d71e2ca05b1218abf9623a63a91874f1112b861943faacbedd26dcbd6b589a7db3bcc1a8f2ad9fea08e929d65f08220ec74edb26b1e8d79844cb6b452b3f163608d700061ff5d42bc7fc04eb0b954", + "password_file": "1f658d31ac18d2d1ec1507bfd2b33c9dc5a5ec3840a87c35445be002156da95162c91ab0e7daae9e6e569e2c4ac115f770920043425e2fc941804049da6837c9537a455f91f45fd8c972a0087ec03ba8482773a0ba7dc0cb0690e94c3dabb5f7b4a46dc06b981100c15529e4675babe4ed05444de2fd4fc7dba6d3aaf9fca40a3d5d7de871613d47281ca2c105eba79f925d46b52dfd3448f9ec6acbb71e7280f8cab44110cd1ca7e0a58b25245840e6f9c8856e43c6a23aa073d23c9fcae22f", + "export_key": "4b66b395cc1f92fbf6ba7b6f2b4005d8a922cf712eda153d6c71e475dbbef5dd82558f229c64d214329df488a28926cd9d2908c96c932c1d2857888bbcf5cc62", + "session_key": "4f1112b861943faacbedd26dcbd6b589a7db3bcc1a8f2ad9fea08e929d65f08220ec74edb26b1e8d79844cb6b452b3f163608d700061ff5d42bc7fc04eb0b954" } "#; #[cfg(feature = "x25519")] static TEST_VECTOR_X25519_P256: &str = r#" { - "client_s_pk": "54ad295308e561e9549d2662a79a18228784bca512b50a6fd161595dbfa18f54", - "client_s_sk": "20f9d6b90a9463e8432780c647b2dd7f4becf8d174c92a8023f395d01f16515b", - "client_e_pk": "07cb52b7d96fcdcdec4ec1da39dab5210c6abca838af870886a391caf1cc9d7a", - "client_e_sk": "20bdb5e9d5d98fcd9ba5634e03eba34fc728753369ce0234c9826aa88047c259", - "server_s_pk": "4923a63bd059263cb2a69fd3a528191986d9c1f470bfe240d470af628adec277", - "server_s_sk": "88b9fbacb0d38394f61c35408fe05c6734a1a63c5e6a16684095d9cc2f82cb4d", - "server_e_pk": "e8a420fd6ff116cf865035321f91e211609b4a0f013ffd0798ea68bd04267c7a", - "server_e_sk": "20eed40939abf897bdba6d7649893a617762fb3b94e04c247a086dc48448f361", - "fake_sk": "4847b46ae57fa21f9bdf38bb4ee08ed12f64141b21707743ce3bf203cf36416b", + "client_s_pk": "17e8c950fde734deb4468ecb619023a005cba3a85cbbd4a8f43f37101add7279", + "client_s_sk": "393df095fff0eb7249abe3d15416b8c362598be68e28f89456f783d37f54fe02", + "client_e_pk": "99e2464eb85ce67f2e0711036f7ca99022cb73d787c0dc3861d1990dda716649", + "client_e_sk": "f91411fceac1ffc2f86508018c4a3769381b5f778d4c281fe702a24465ff5e0b", + "server_s_pk": "e375d12756de75aaea657cf51cc2db0ebbb4cc63c1bde12def0e37b1f13fa363", + "server_s_sk": "8471298bfe02864e59eecf68a5f1269617e94fe9127f34c1fd69f45b4577cc01", + "server_e_pk": "9bfae7621089efc01944b79a6d112ead2cf4129f1ae34edfe7fe14885f25131b", + "server_e_sk": "ce684f66a099edc3b83ebbe67f8d745e6332f2c5953fa7b2d359a02fcd5e030e", + "fake_sk": "9d3aa4990006276d206c94e0882e28579e65f027f355f9aa6eccbf037e036a00", "credential_identifier": "637265644964656e746966696572", "id_u": "696455", "id_s": "696453", "password": "70617373776f7264", - "blinding_factor": "1ca386b0d0a0c390c68d8eab341787260fa3ee2a94059d7887ec687eba80ceee", - "oprf_seed": "b78f0138ef05a3df5aef410e7dda3b4972600e4d9f1e3ffa9376778cf31337ad", - "masking_nonce": "669d7a5f0b410805b4a48d81d86e821d925341c5a634581d43225b1f0820d3c13a3633d70a1eb6982b12dbca41db7718f12db87a0896034bc4c3c7c54ac4d647", - "envelope_nonce": "b57ed3206fb154fcfccb1e5effd873e9bce098af031674524c24572116061cc1", - "client_nonce": "f7e2cf7311f3bd310e331dc24a94f319c0dc5f1ae2d3a039b5da60bac9ef6099", - "server_nonce": "daad4ea374a85431b05253e53c5c69f67e0fc8067eaa1d492f8ff045659fe377", + "blinding_factor": "5110d33a36d039bb8ca1329b39993a2366024dec83671bf195a2997f054b5505", + "oprf_seed": "fc9afbdfca56e6b467001ac8263340e1cac82f7f2ccea776d22ba179df0f8538", + "masking_nonce": "cbb2380130d6f4a80f8d1e3f9bde4e431c6e3105aac77a0076dfe6e8e887287074c00fe8180a70d09ccac389331b4b4a0a2702f3239a452ba85b5a1b98c05ac2", + "envelope_nonce": "33d328f8f869e6898c7c1036b29dc94fa14647742e4a10678c2f84836d040a44", + "client_nonce": "18ee6d17f22eb48701ce46967e0b55864ae88b124a43403dfb1d71e4681f5b30", + "server_nonce": "7e868983e4a2f9cc909287d255e3cc94b467c4701d938de643a795fec393e12c", "context": "636f6e74657874", - "registration_request": "023741a9f45d763159b728738cde140058e6bc3ead289e74b9df6cf2317dc50a36", - "registration_response": "023e084f135edff464f60468dcc18c779ea7cea99daec254499ed082ed086bfe7d4923a63bd059263cb2a69fd3a528191986d9c1f470bfe240d470af628adec277", - "registration_upload": "fee1e2438d269807b7e8b07c5b078f553bab065deb2943ac95119ec04857dc2a8a2e3934463798e276d13a0b3456eb2a98c87968d90c4ae0a51d311fe1655d5f20f9d6b90a9463e8432780c647b2dd7f4becf8d174c92a8023f395d01f16515bc4ddd82e83589cbe9c3b6fdea12acedef29aa7784a2ce0b65685dc352b66c142", - "credential_request": "023741a9f45d763159b728738cde140058e6bc3ead289e74b9df6cf2317dc50a36f7e2cf7311f3bd310e331dc24a94f319c0dc5f1ae2d3a039b5da60bac9ef609907cb52b7d96fcdcdec4ec1da39dab5210c6abca838af870886a391caf1cc9d7a", - "credential_response": "023e084f135edff464f60468dcc18c779ea7cea99daec254499ed082ed086bfe7d669d7a5f0b410805b4a48d81d86e821d925341c5a634581d43225b1f0820d3c15a700199e8446adf51b7f027b5c59ef0847b6e43ab72a6d6de4cf0eb3fe3a2093bdf8d3a50013795f094d651dcd7e9f597904e4940a3629166c2f3f4905e88c3e1f6db8f5244feebd435e5664bd395e9ba78aa93bd7e93863aa052765d4911b420eed40939abf897bdba6d7649893a617762fb3b94e04c247a086dc48448f3618e2b6d1e406e0695a0a7f32f296e45990186c54ab76a3562e7d70faf66ff99759118020c29faab346283f6e0221f7de81def8dc79c6904b5075b098a35c6a50e", - "credential_finalization": "4a6e76c08153d2c07ab695030c6fd3a6f531338e3dc85f75b0af56ee54874e2e", - "client_registration_state": "1ca386b0d0a0c390c68d8eab341787260fa3ee2a94059d7887ec687eba80ceee023741a9f45d763159b728738cde140058e6bc3ead289e74b9df6cf2317dc50a36", - "client_login_state": "1ca386b0d0a0c390c68d8eab341787260fa3ee2a94059d7887ec687eba80ceee023741a9f45d763159b728738cde140058e6bc3ead289e74b9df6cf2317dc50a36f7e2cf7311f3bd310e331dc24a94f319c0dc5f1ae2d3a039b5da60bac9ef609907cb52b7d96fcdcdec4ec1da39dab5210c6abca838af870886a391caf1cc9d7a20bdb5e9d5d98fcd9ba5634e03eba34fc728753369ce0234c9826aa88047c259f7e2cf7311f3bd310e331dc24a94f319c0dc5f1ae2d3a039b5da60bac9ef6099", - "server_login_state": "a4177b3ddccd8634ea0ad95dc9d7287f701fc5354ff53c84cb6205bff831fdeb49b5196d9330ab791ca1eb475a8eb04937430ef87776a7d1c7c4102231e7a1a89c599288d589338b0c99688a2db39f693d5d6f57cee46dc77f3d66af027fed3e", - "password_file": "fee1e2438d269807b7e8b07c5b078f553bab065deb2943ac95119ec04857dc2a8a2e3934463798e276d13a0b3456eb2a98c87968d90c4ae0a51d311fe1655d5f20f9d6b90a9463e8432780c647b2dd7f4becf8d174c92a8023f395d01f16515bc4ddd82e83589cbe9c3b6fdea12acedef29aa7784a2ce0b65685dc352b66c142", - "export_key": "fae7cd4aa438eeaa5f83b0a181ce29d18c9de4eecfd778a42511014c8b536f89", - "session_key": "9c599288d589338b0c99688a2db39f693d5d6f57cee46dc77f3d66af027fed3e" + "registration_request": "028d69a2c03f2edf8f389563c1cc78a3b95a67a20c894bce4359412b210ea52d0f", + "registration_response": "03fc2889add67eeaec390775befef78d8cee5d93bc9ac1186260f809dfe0b639e9e375d12756de75aaea657cf51cc2db0ebbb4cc63c1bde12def0e37b1f13fa363", + "registration_upload": "cef21bd371ce71c76aafd21821509b59ec5faa9b53a8e21bfaa58186d020a812a894afae522fc4e6e251e6a72b832dfdea2284d1e38e1d4356a7ec47449c0a6d393df095fff0eb7249abe3d15416b8c362598be68e28f89456f783d37f54fe02bc8aca098df28e6548308a5cf921fe5a71a5f2b6f85976dd2f1e37fcf5d69126", + "credential_request": "028d69a2c03f2edf8f389563c1cc78a3b95a67a20c894bce4359412b210ea52d0f5110d33a36d039bb8ca1329b39993a2366024dec83671bf195a2997f054b550560761872baf7ae0caa9da19604217d845623437af461d10b78202f1545c3d34b", + "credential_response": "03fc2889add67eeaec390775befef78d8cee5d93bc9ac1186260f809dfe0b639e9cbb2380130d6f4a80f8d1e3f9bde4e431c6e3105aac77a0076dfe6e8e887287099a0886cd4da8ec29e54cde0d14b25d4532e28692acd7a45b751314c08ddc8b14b1d80772fd4a81c35185f8e9a0b89f81ca97cfc0d295caf71cb91f4930c2edb9fe42b1a69fa4f007735ddcb47061a766de2c7321fca1a3fcd6b7f5b3d36b8807e868983e4a2f9cc909287d255e3cc94b467c4701d938de643a795fec393e12c161d7a9bb4eb6a3d914c3dfe7bfcce7c483c54555cb344a8c97694a2eea7fa4019abb329e92ed77475d70d2c016e0cf9fe6f68974d175a0461848c4994d73c43", + "credential_finalization": "273ea776d1e67645fd9e21179032a02fc340087bc2621920be0a960f7a3ef25b", + "client_registration_state": "5110d33a36d039bb8ca1329b39993a2366024dec83671bf195a2997f054b5505028d69a2c03f2edf8f389563c1cc78a3b95a67a20c894bce4359412b210ea52d0f", + "client_login_state": "5110d33a36d039bb8ca1329b39993a2366024dec83671bf195a2997f054b5505028d69a2c03f2edf8f389563c1cc78a3b95a67a20c894bce4359412b210ea52d0f5110d33a36d039bb8ca1329b39993a2366024dec83671bf195a2997f054b550560761872baf7ae0caa9da19604217d845623437af461d10b78202f1545c3d34be546de1f4ded2ab52dc0abf00f500b927ee1033aafc0f3a3e5d2634cd52112005110d33a36d039bb8ca1329b39993a2366024dec83671bf195a2997f054b5505", + "server_login_state": "05a413df0fa949e0308ad3bfffacb7d45bb9edd74314a5015e7b743a22192744504abe829295e3ae661d6ed30dc49d2f44f6ca934412fe6ee773d6514f8247f2082fdd36d18d86c40d32141d4b2e4db654d9c3ce718df531a8c5431e4ba9d292", + "password_file": "cef21bd371ce71c76aafd21821509b59ec5faa9b53a8e21bfaa58186d020a812a894afae522fc4e6e251e6a72b832dfdea2284d1e38e1d4356a7ec47449c0a6d393df095fff0eb7249abe3d15416b8c362598be68e28f89456f783d37f54fe02bc8aca098df28e6548308a5cf921fe5a71a5f2b6f85976dd2f1e37fcf5d69126", + "export_key": "1150751e9cfcf72bcbce59a472957fd06ed79f60ae9db04354bb2d10d3707c26", + "session_key": "082fdd36d18d86c40d32141d4b2e4db654d9c3ce718df531a8c5431e4ba9d292" } "#; @@ -634,13 +634,13 @@ where let credential_finalization_bytes = client_login_finish_result.message.serialize(); Ok(TestVectorParameters { - client_s_pk: client_s_kp.public().to_bytes().to_vec(), + client_s_pk: client_s_kp.public().serialize().to_vec(), client_s_sk: client_s_kp.private().serialize().to_vec(), - client_e_pk: client_e_kp.public().to_bytes().to_vec(), + client_e_pk: client_e_kp.public().serialize().to_vec(), client_e_sk: client_e_kp.private().serialize().to_vec(), - server_s_pk: server_s_kp.public().to_bytes().to_vec(), + server_s_pk: server_s_kp.public().serialize().to_vec(), server_s_sk: server_s_kp.private().serialize().to_vec(), - server_e_pk: server_e_kp.public().to_bytes().to_vec(), + server_e_pk: server_e_kp.public().serialize().to_vec(), server_e_sk: server_e_kp.private().serialize().to_vec(), fake_sk, credential_identifier: credential_identifier.to_vec(), @@ -741,8 +741,6 @@ fn test_registration_request() -> Result<(), ProtocolError> { #[cfg(feature = "serde")] #[test] fn test_serialization() -> Result<(), ProtocolError> { - use core::mem; - fn inner(test_vector: &str) -> Result<(), ProtocolError> where as OutputSizeUser>::OutputSize: @@ -762,7 +760,7 @@ fn test_serialization() -> Result<(), ProtocolError> { bincode::serialize(&client_registration_start_result.message).unwrap(); assert_eq!( registration_request.len(), - RegistrationRequestLen::::USIZE + mem::size_of::() + RegistrationRequestLen::::USIZE ); let registration_request: RegistrationRequest = bincode::deserialize(®istration_request).unwrap(); @@ -1107,7 +1105,7 @@ fn test_credential_finalization() -> Result<(), ProtocolError> { assert_eq!( hex::encode(¶meters.server_s_pk), - hex::encode(&client_login_finish_result.server_s_pk.to_bytes()) + hex::encode(&client_login_finish_result.server_s_pk.serialize()) ); assert_eq!( hex::encode(¶meters.session_key), @@ -1417,7 +1415,7 @@ fn test_zeroize_server_registration_finish() -> Result<(), ProtocolError> { #[test] fn test_zeroize_client_login_start() -> Result<(), ProtocolError> { - fn inner>() -> Result<(), ProtocolError> + fn inner>() -> Result<(), ProtocolError> where as OutputSizeUser>::OutputSize: IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, @@ -1537,7 +1535,7 @@ fn test_zeroize_server_login_start() -> Result<(), ProtocolError> { #[test] fn test_zeroize_client_login_finish() -> Result<(), ProtocolError> { - fn inner>() -> Result<(), ProtocolError> + fn inner>() -> Result<(), ProtocolError> where as OutputSizeUser>::OutputSize: IsLess + IsLessOrEqual< as BlockSizeUser>::BlockSize>, diff --git a/src/tests/test_opaque_vectors.rs b/src/tests/test_opaque_vectors.rs index c194790..d3e3876 100644 --- a/src/tests/test_opaque_vectors.rs +++ b/src/tests/test_opaque_vectors.rs @@ -24,13 +24,13 @@ use crate::errors::*; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::KeGroup; use crate::key_exchange::traits::{Ke1MessageLen, Ke2MessageLen}; -use crate::key_exchange::tripledh::{NonceLen, TripleDH}; +use crate::key_exchange::tripledh::{NonceLen, TripleDh}; +use crate::ksf::Identity; use crate::messages::{ CredentialRequestLen, CredentialResponseLen, CredentialResponseWithoutKeLen, RegistrationResponseLen, RegistrationUploadLen, }; use crate::opaque::*; -use crate::slow_hash::NoOpHash; use crate::tests::mock_rng::CycleRng; use crate::*; @@ -110,7 +110,7 @@ where dummy_private_key: { match decode(values, "client_private_key") { Some(value) => value, - None => CS::KeGroup::serialize_sk(&CS::KeGroup::random_sk(&mut OsRng)).to_vec(), + None => CS::KeGroup::serialize_sk(CS::KeGroup::random_sk(&mut OsRng)).to_vec(), } }, dummy_masking_key: { @@ -209,62 +209,54 @@ fn tests() -> Result<(), ProtocolError> { #[cfg(feature = "ristretto255")] { - struct Ristretto255Sha512NoSlowHash; - impl CipherSuite for Ristretto255Sha512NoSlowHash { - type OprfGroup = crate::Ristretto255; + struct Ristretto255Sha512NoKsf; + impl CipherSuite for Ristretto255Sha512NoKsf { + type OprfCs = crate::Ristretto255; type KeGroup = crate::Ristretto255; - type KeyExchange = TripleDH; - type SlowHash = NoOpHash; + type KeyExchange = TripleDh; + type Ksf = Identity; } - let ristretto_real_tvs = json_to_test_vectors!( - rfc, - "Real", - "ristretto255, SHA512", - Ristretto255Sha512NoSlowHash - ); + let ristretto_real_tvs = + json_to_test_vectors!(rfc, "Real", "ristretto255, SHA512", Ristretto255Sha512NoKsf); - let ristretto_fake_tvs = json_to_test_vectors!( - rfc, - "Fake", - "ristretto255, SHA512", - Ristretto255Sha512NoSlowHash - ); + let ristretto_fake_tvs = + json_to_test_vectors!(rfc, "Fake", "ristretto255, SHA512", Ristretto255Sha512NoKsf); assert!( !(ristretto_real_tvs.is_empty() || ristretto_fake_tvs.is_empty()), "Parsing error" ); - test_registration_request::(&ristretto_real_tvs)?; - test_registration_response::(&ristretto_real_tvs)?; - test_registration_upload::(&ristretto_real_tvs)?; - test_ke1::(&ristretto_real_tvs)?; - test_ke2::(&ristretto_real_tvs)?; - test_ke3::(&ristretto_real_tvs)?; - test_server_login_finish::(&ristretto_real_tvs)?; - test_fake_vectors::(&ristretto_fake_tvs)?; + test_registration_request::(&ristretto_real_tvs)?; + test_registration_response::(&ristretto_real_tvs)?; + test_registration_upload::(&ristretto_real_tvs)?; + test_ke1::(&ristretto_real_tvs)?; + test_ke2::(&ristretto_real_tvs)?; + test_ke3::(&ristretto_real_tvs)?; + test_server_login_finish::(&ristretto_real_tvs)?; + test_fake_vectors::(&ristretto_fake_tvs)?; } - struct P256Sha256NoSlowHash; - impl CipherSuite for P256Sha256NoSlowHash { - type OprfGroup = p256::NistP256; + struct P256Sha256NoKsf; + impl CipherSuite for P256Sha256NoKsf { + type OprfCs = p256::NistP256; type KeGroup = p256::NistP256; - type KeyExchange = TripleDH; - type SlowHash = NoOpHash; + type KeyExchange = TripleDh; + type Ksf = Identity; } let p256_real_tvs = json_to_test_vectors!( rfc, "Real", "P256_XMD:SHA-256_SSWU_RO_, SHA256", - P256Sha256NoSlowHash + P256Sha256NoKsf ); let p256_fake_tvs = json_to_test_vectors!( rfc, "Fake", "P256_XMD:SHA-256_SSWU_RO_, SHA256", - P256Sha256NoSlowHash + P256Sha256NoKsf ); assert!( @@ -272,14 +264,14 @@ fn tests() -> Result<(), ProtocolError> { "Parsing error" ); - test_registration_request::(&p256_real_tvs)?; - test_registration_response::(&p256_real_tvs)?; - test_registration_upload::(&p256_real_tvs)?; - test_ke1::(&p256_real_tvs)?; - test_ke2::(&p256_real_tvs)?; - test_ke3::(&p256_real_tvs)?; - test_server_login_finish::(&p256_real_tvs)?; - test_fake_vectors::(&p256_fake_tvs)?; + test_registration_request::(&p256_real_tvs)?; + test_registration_response::(&p256_real_tvs)?; + test_registration_upload::(&p256_real_tvs)?; + test_ke1::(&p256_real_tvs)?; + test_ke2::(&p256_real_tvs)?; + test_ke3::(&p256_real_tvs)?; + test_server_login_finish::(&p256_real_tvs)?; + test_fake_vectors::(&p256_fake_tvs)?; Ok(()) } diff --git a/taplo.toml b/taplo.toml index 7653be7..410aaa1 100644 --- a/taplo.toml +++ b/taplo.toml @@ -1,3 +1,3 @@ [formatting] -reorder_keys = true allowed_blank_lines = 1 +reorder_keys = true