General Improvements (#268)

* Move `elliptic-curve` implementation to points to allow `Zeroize`

* Simplify `Ristretto255::random_scalar` implementation

* Fix `Ristretto255` deserialization

* Remove unnecessary check in `Ristretto255::random_scalar`

* Base `X25519` implementation on `curve25519-dalek`

* Constrain public and secret key to `Copy`

* Replace manual `ZeroizeOnDrop` implementation with `derive`

* Update dependencies

* Add `warn(unused_crate_dependencies)`

* Sync crate feature naming with `voprf`

* Remove unnecessary dependency crate features

* Never produce a zero scalar

* Rename `OprfGroup` to `OprfCs`

* Rename `TripleDH` to `TripleDh`

* Remove `slow-hash` crate feature

* Rename `NoOpHash` to `Identity`

* Rename `SlowHash` to `Ksf`

* Move `KeyExchange` type definitions down

* Deserialize secret and public keys from slices

* Remove `PrivateKey::from_bytes`

* Rename `From/ToBytes` to `De/Serialize`

* Re-export `serde_` as `serde`

* Custom `De/Serialize` implementation for keys

* Remove custom `De/Serialize` implementation

* Run Taplo v0.6
This commit is contained in:
daxpedda
2022-04-01 16:10:00 -07:00
committed by GitHub
parent f952a26e29
commit 384207acbb
25 changed files with 849 additions and 1109 deletions
+91 -89
View File
@@ -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 = "<CS::KeGroup as KeGroup>::Pk: serde_::Deserialize<'de>, <CS::KeGroup \
as KeGroup>::Sk: serde_::Deserialize<'de>, S: serde_::Deserialize<'de>",
serialize = "<CS::KeGroup as KeGroup>::Pk: serde_::Serialize, <CS::KeGroup as \
KeGroup>::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<CS::OprfGroup>,
voprf::BlindedElement<CS::OprfGroup>,
voprf::NonVerifiableClient<CS::OprfCs>,
voprf::BlindedElement<CS::OprfCs>,
)]
pub struct ClientRegistration<CS: CipherSuite>
where
@@ -102,19 +105,16 @@ where
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
pub(crate) oprf_client: voprf::NonVerifiableClient<CS::OprfGroup>,
pub(crate) blinded_element: voprf::BlindedElement<CS::OprfGroup>,
pub(crate) oprf_client: voprf::NonVerifiableClient<CS::OprfCs>,
pub(crate) blinded_element: voprf::BlindedElement<CS::OprfCs>,
}
impl_serialize_and_deserialize_for!(
ClientRegistration
where
// ClientRegistration: KgSk + KgPk
<OprfGroup<CS> as Group>::ScalarLen: Add<<OprfGroup<CS> as Group>::ElemLen>,
ClientRegistrationLen<CS>: ArrayLength<u8>,
);
/// 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; <CS::KeGroup as KeGroup>::Pk)]
pub struct ServerRegistration<CS: CipherSuite>(pub(crate) RegistrationUpload<CS>)
@@ -126,25 +126,27 @@ where
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero;
impl_serialize_and_deserialize_for!(
ServerRegistration
where
// Envelope: Nonce + Hash
NonceLen: Add<OutputSize<OprfHash<CS>>>,
EnvelopeLen<CS>: ArrayLength<u8>,
// RegistrationUpload: (KePk + Hash) + Envelope
<CS::KeGroup as KeGroup>::PkLen: Add<OutputSize<OprfHash<CS>>>,
Sum<<CS::KeGroup as KeGroup>::PkLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> | Add<EnvelopeLen<CS>>,
RegistrationUploadLen<CS>: ArrayLength<u8>,
// 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::KeyExchange as KeyExchange<OprfHash<CS>, \
CS::KeGroup>>::KE1Message: serde::Deserialize<'de>, <CS::KeyExchange \
as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE1State: \
serde::Deserialize<'de>",
serialize = "<CS::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE1Message: \
serde::Serialize, <CS::KeyExchange as KeyExchange<OprfHash<CS>, \
CS::KeGroup>>::KE1State: serde::Serialize"
),
crate = "serde"
)
)]
#[derive_where(Clone, ZeroizeOnDrop)]
#[derive_where(
Debug, Eq, Hash, PartialEq;
voprf::NonVerifiableClient<CS::OprfGroup>,
voprf::NonVerifiableClient<CS::OprfCs>,
<CS::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE1State,
CredentialRequest<CS>,
)]
@@ -157,25 +159,25 @@ where
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
pub(crate) oprf_client: voprf::NonVerifiableClient<CS::OprfGroup>,
pub(crate) oprf_client: voprf::NonVerifiableClient<CS::OprfCs>,
pub(crate) ke1_state: <CS::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE1State,
pub(crate) credential_request: CredentialRequest<CS>,
}
impl_serialize_and_deserialize_for!(
ClientLogin
where
// CredentialRequest: KgPk + Ke1Message
<OprfGroup<CS> as Group>::ElemLen: Add<Ke1MessageLen<CS>>,
CredentialRequestLen<CS>: ArrayLength<u8>,
// ClientLogin: KgSk + CredentialRequest + Ke1State
<OprfGroup<CS> as Group>::ScalarLen: Add<CredentialRequestLen<CS>>,
Sum<<OprfGroup<CS> as Group>::ScalarLen, CredentialRequestLen<CS>>:
ArrayLength<u8> | Add<Ke1StateLen<CS>>,
ClientLoginLen<CS>: ArrayLength<u8>,
);
/// The state elements the server holds to record a login
#[cfg_attr(
feature = "serde",
derive(serde::Deserialize, serde::Serialize),
serde(
bound(
deserialize = "<CS::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE2State: \
serde::Deserialize<'de>",
serialize = "<CS::KeyExchange as KeyExchange<OprfHash<CS>, 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::KeyExchange as KeyExchange<OprfHash<CS>, 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::<OprfHash<CS>>::default();
@@ -450,7 +450,7 @@ where
credential_identifier: &[u8],
) -> Result<ServerRegistrationStartResult<CS>, ProtocolError> {
let oprf_key =
oprf_key_from_seed::<CS::OprfGroup>(&server_setup.oprf_seed, credential_identifier)?;
oprf_key_from_seed::<CS::OprfCs>(&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::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE1State::from_bytes(
<CS::KeyExchange as KeyExchange<OprfHash<CS>, 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::<OprfHash<CS>>::default();
@@ -638,7 +638,7 @@ where
let blinded_element =
OprfGroup::<CS>::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::<CS>::serialize_iter(&blinded_element, &ke1_message);
@@ -682,14 +682,14 @@ where
{
/// Serialization into bytes
pub fn serialize(&self) -> GenericArray<u8, Ke2StateLen<CS>> {
self.ke2_state.to_bytes()
self.ke2_state.serialize()
}
/// Deserialization from bytes
pub fn deserialize(bytes: &[u8]) -> Result<Self, ProtocolError> {
Ok(Self {
ke2_state:
<CS::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE2State::from_bytes(
<CS::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE2State::deserialize(
bytes,
)?,
})
@@ -744,19 +744,19 @@ where
let (id_u, id_s) = bytestrings_from_identifiers::<CS::KeGroup>(
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::<CS>::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::<CS>::serialize_iter(&blinded_element, &ke1_message);
let oprf_key =
oprf_key_from_seed::<CS::OprfGroup>(&server_setup.oprf_seed, credential_identifier)
oprf_key_from_seed::<CS::OprfCs>(&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<<<OprfHash<CS> 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<CS::OprfGroup>,
voprf::EvaluationElement<CS::OprfCs>,
<CS::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE2Message,
<CS::KeyExchange as KeyExchange<OprfHash<CS>, CS::KeGroup>>::KE2State,
)]
@@ -1097,9 +1094,9 @@ where
#[allow(clippy::type_complexity)]
fn get_password_derived_key<CS: CipherSuite>(
input: &[u8],
oprf_client: voprf::NonVerifiableClient<CS::OprfGroup>,
evaluation_element: voprf::EvaluationElement<CS::OprfGroup>,
slow_hash: Option<&CS::SlowHash>,
oprf_client: voprf::NonVerifiableClient<CS::OprfCs>,
evaluation_element: voprf::EvaluationElement<CS::OprfCs>,
ksf: Option<&CS::Ksf>,
) -> Result<(Output<OprfHash<CS>>, Hkdf<OprfHash<CS>>), ProtocolError>
where
<OprfHash<CS> 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<CS: CipherSuite>
@@ -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<KG: KeGroup>(
ids: Identifiers,
client_s_pk: GenericArray<u8, KG::PkLen>,
server_s_pk: GenericArray<u8, KG::PkLen>,
) -> Result<(Serialize<U2, KG::PkLen>, Serialize<U2, KG::PkLen>), ProtocolError> {
) -> Result<(Input<U2, KG::PkLen>, Input<U2, KG::PkLen>), ProtocolError> {
let client_identity = if let Some(client) = ids.client {
Serialize::<U2, _>::from(client)?
Input::<U2, _>::from(client)?
} else {
Serialize::<U2, _>::from_owned(client_s_pk)?
Input::<U2, _>::from_owned(client_s_pk)?
};
let server_identity = if let Some(server) = ids.server {
Serialize::<U2, _>::from(server)?
Input::<U2, _>::from(server)?
} else {
Serialize::<U2, _>::from_owned(server_s_pk)?
Input::<U2, _>::from_owned(server_s_pk)?
};
Ok((client_identity, server_identity))
@@ -1308,7 +1310,7 @@ pub(crate) fn bytestrings_from_identifiers<KG: KeGroup>(
fn blind<CS: CipherSuite, R: RngCore + CryptoRng>(
rng: &mut R,
password: &[u8],
) -> Result<voprf::NonVerifiableClientBlindResult<CS::OprfGroup>, voprf::Error>
) -> Result<voprf::NonVerifiableClientBlindResult<CS::OprfCs>, voprf::Error>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,