Implement common traits
This commit is contained in:
+2
-2
@@ -15,7 +15,7 @@ slow-hash = ["argon2"]
|
|||||||
bench = []
|
bench = []
|
||||||
u64_backend = ["curve25519-dalek/u64_backend"]
|
u64_backend = ["curve25519-dalek/u64_backend"]
|
||||||
u32_backend = ["curve25519-dalek/u32_backend"]
|
u32_backend = ["curve25519-dalek/u32_backend"]
|
||||||
serialize = ["serde", "base64"]
|
serialize = ["serde", "base64", "generic-array/serde", "curve25519-dalek/serde"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
argon2 = { version = "0.2", optional = true }
|
argon2 = { version = "0.2", optional = true }
|
||||||
@@ -28,7 +28,7 @@ generic-bytes = { version = "0.1.0" }
|
|||||||
hkdf = "0.11.0"
|
hkdf = "0.11.0"
|
||||||
hmac = "0.11.0"
|
hmac = "0.11.0"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
serde = { version = "1", optional = true }
|
serde = { version = "1", features = ["derive"], optional = true }
|
||||||
subtle = { version = "2.3.0", default-features = false }
|
subtle = { version = "2.3.0", default-features = false }
|
||||||
thiserror = "1.0.22"
|
thiserror = "1.0.22"
|
||||||
zeroize = { version = "1.1.1", features = ["zeroize_derive"] }
|
zeroize = { version = "1.1.1", features = ["zeroize_derive"] }
|
||||||
|
|||||||
+3
-1
@@ -61,7 +61,7 @@ fn recover_keys_internal<CS: CipherSuite>(
|
|||||||
Ok(client_static_keypair)
|
Ok(client_static_keypair)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Zeroize)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
|
||||||
#[zeroize(drop)]
|
#[zeroize(drop)]
|
||||||
pub(crate) enum InnerEnvelopeMode {
|
pub(crate) enum InnerEnvelopeMode {
|
||||||
Zero = 0,
|
Zero = 0,
|
||||||
@@ -105,6 +105,8 @@ impl<CS: CipherSuite> Clone for Envelope<CS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_debug_eq_hash_for!(struct Envelope<CS: CipherSuite>, [mode, nonce, hmac]);
|
||||||
|
|
||||||
// Note that this struct represents an envelope that has been "opened" with the asssociated
|
// 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
|
// key. This key is also used to derive the export_key parameter, which is technically
|
||||||
// unrelated to the envelope's encrypted and authenticated contents.
|
// unrelated to the envelope's encrypted and authenticated contents.
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
macro_rules! impl_debug_eq_hash_for {
|
||||||
|
(struct $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? std::fmt::Debug for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: std::fmt::Debug,)+)?
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("$name")
|
||||||
|
.field("$field1", &self.$field1)
|
||||||
|
$(.field("$field2", &self.$field2))*
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? Eq for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: Eq,)+)?
|
||||||
|
{}
|
||||||
|
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? PartialEq for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: PartialEq,)+)?
|
||||||
|
{
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
PartialEq::eq(&self.$field1, &other.$field1)
|
||||||
|
$(&& PartialEq::eq(&self.$field2, &other.$field2))*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? std::hash::Hash for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: std::hash::Hash,)+)?
|
||||||
|
{
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
std::hash::Hash::hash(&self.$field1, state);
|
||||||
|
$(std::hash::Hash::hash(&self.$field2, state);)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(tuple $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:tt$(, $field2:tt)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? std::fmt::Debug for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: std::fmt::Debug,)+)?
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_tuple("$name")
|
||||||
|
.field(&self.$field1)
|
||||||
|
$(.field(&self.$field2))*
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? Eq for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: Eq,)+)?
|
||||||
|
{}
|
||||||
|
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? PartialEq for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: PartialEq,)+)?
|
||||||
|
{
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
PartialEq::eq(&self.$field1, &other.$field1)
|
||||||
|
$(&& PartialEq::eq(&self.$field2, &other.$field2))*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? std::hash::Hash for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: std::hash::Hash,)+)?
|
||||||
|
{
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
std::hash::Hash::hash(&self.$field1, state);
|
||||||
|
$(std::hash::Hash::hash(&self.$field2, state);)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_clone_for {
|
||||||
|
(struct $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? Clone for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: Clone,)+)?
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
$field1: self.$field1.clone(),
|
||||||
|
$($field2: self.$field2.clone(),)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(tuple $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:tt$(, $field2:tt)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
|
||||||
|
impl$(<$($gen$(: $bound)?),+>)? Clone for $name$(<$($gen),+>)?
|
||||||
|
$(where $($type: Clone,)+)?
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(
|
||||||
|
self.$field1.clone(),
|
||||||
|
$(self.$field2.clone(),)*
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -207,7 +207,8 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The client state produced after the first key exchange message
|
/// The client state produced after the first key exchange message
|
||||||
#[derive(PartialEq, Eq, Zeroize, Clone)]
|
#[derive(PartialEq, Eq, Debug, Hash, Zeroize, Clone)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[zeroize(drop)]
|
#[zeroize(drop)]
|
||||||
pub struct Ke1State {
|
pub struct Ke1State {
|
||||||
client_e_sk: PrivateKey,
|
client_e_sk: PrivateKey,
|
||||||
@@ -215,7 +216,8 @@ pub struct Ke1State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The first key exchange message
|
/// The first key exchange message
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Ke1Message {
|
pub struct Ke1Message {
|
||||||
pub(crate) client_nonce: GenericArray<u8, NonceLen>,
|
pub(crate) client_nonce: GenericArray<u8, NonceLen>,
|
||||||
pub(crate) client_e_pk: PublicKey,
|
pub(crate) client_e_pk: PublicKey,
|
||||||
@@ -272,7 +274,9 @@ impl FromBytes for Ke1Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// The server state produced after the second key exchange message
|
/// The server state produced after the second key exchange message
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
#[cfg_attr(feature = "serialize", serde(bound = ""))]
|
||||||
pub struct Ke2State<HashLen: ArrayLength<u8>> {
|
pub struct Ke2State<HashLen: ArrayLength<u8>> {
|
||||||
km3: GenericArray<u8, HashLen>,
|
km3: GenericArray<u8, HashLen>,
|
||||||
hashed_transcript: GenericArray<u8, HashLen>,
|
hashed_transcript: GenericArray<u8, HashLen>,
|
||||||
@@ -315,7 +319,9 @@ impl<HashLen: ArrayLength<u8>> ToBytesWithPointers for Ke2State<HashLen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The second key exchange message
|
/// The second key exchange message
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
#[cfg_attr(feature = "serialize", serde(bound = ""))]
|
||||||
pub struct Ke2Message<HashLen: ArrayLength<u8>> {
|
pub struct Ke2Message<HashLen: ArrayLength<u8>> {
|
||||||
server_nonce: GenericArray<u8, NonceLen>,
|
server_nonce: GenericArray<u8, NonceLen>,
|
||||||
server_e_pk: PublicKey,
|
server_e_pk: PublicKey,
|
||||||
@@ -398,7 +404,9 @@ type TripleDHDerivationResult<D> = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// The third key exchange message
|
/// The third key exchange message
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
#[cfg_attr(feature = "serialize", serde(bound = ""))]
|
||||||
pub struct Ke3Message<HashLen: ArrayLength<u8>> {
|
pub struct Ke3Message<HashLen: ArrayLength<u8>> {
|
||||||
mac: GenericArray<u8, HashLen>,
|
mac: GenericArray<u8, HashLen>,
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-4
@@ -35,13 +35,22 @@ pub trait SizedBytesExt: SizedBytes {
|
|||||||
impl<T> SizedBytesExt for T where T: SizedBytes {}
|
impl<T> SizedBytesExt for T where T: SizedBytes {}
|
||||||
|
|
||||||
/// A Keypair trait with public-private verification
|
/// A Keypair trait with public-private verification
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct KeyPair<G> {
|
pub struct KeyPair<G> {
|
||||||
pk: PublicKey,
|
pk: PublicKey,
|
||||||
sk: PrivateKey,
|
sk: PrivateKey,
|
||||||
_g: PhantomData<G>,
|
_g: PhantomData<G>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_clone_for!(
|
||||||
|
struct KeyPair<G>,
|
||||||
|
[pk, sk, _g],
|
||||||
|
);
|
||||||
|
impl_debug_eq_hash_for!(
|
||||||
|
struct KeyPair<G>,
|
||||||
|
[pk, sk, _g],
|
||||||
|
);
|
||||||
|
|
||||||
// This can't be derived because of the use of a phantom parameter
|
// This can't be derived because of the use of a phantom parameter
|
||||||
impl<G> Zeroize for KeyPair<G> {
|
impl<G> Zeroize for KeyPair<G> {
|
||||||
fn zeroize(&mut self) {
|
fn zeroize(&mut self) {
|
||||||
@@ -154,7 +163,8 @@ impl<G: Group + Debug> KeyPair<G> {
|
|||||||
type KeyLen = U32;
|
type KeyLen = U32;
|
||||||
|
|
||||||
/// A minimalist key type built around a \[u8; 32\]
|
/// A minimalist key type built around a \[u8; 32\]
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Zeroize)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash, Zeroize)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
// Ensure Key material is zeroed after use.
|
// Ensure Key material is zeroed after use.
|
||||||
#[zeroize(drop)]
|
#[zeroize(drop)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@@ -181,7 +191,8 @@ impl Key {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wrapper around a Key to enforce that it's a private one.
|
/// Wrapper around a Key to enforce that it's a private one.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Zeroize)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash, Zeroize)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
// Ensure Key material is zeroed after use.
|
// Ensure Key material is zeroed after use.
|
||||||
#[zeroize(drop)]
|
#[zeroize(drop)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@@ -208,7 +219,8 @@ impl SizedBytes for PrivateKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wrapper around a Key to enforce that it's a public one.
|
/// Wrapper around a Key to enforce that it's a public one.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Zeroize)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash, Zeroize)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
// Ensure Key material is zeroed after use.
|
// Ensure Key material is zeroed after use.
|
||||||
#[zeroize(drop)]
|
#[zeroize(drop)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
|||||||
@@ -747,6 +747,8 @@ compile_error!(
|
|||||||
// Error types
|
// Error types
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod impls;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod serialization;
|
mod serialization;
|
||||||
|
|
||||||
|
|||||||
+40
-18
@@ -46,6 +46,8 @@ impl<CS: CipherSuite> Clone for RegistrationRequest<CS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_debug_eq_hash_for!(struct RegistrationRequest<CS: CipherSuite>, [alpha], [CS::Group]);
|
||||||
|
|
||||||
impl<CS: CipherSuite> RegistrationRequest<CS> {
|
impl<CS: CipherSuite> RegistrationRequest<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
@@ -90,6 +92,12 @@ impl<CS: CipherSuite> Clone for RegistrationResponse<CS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_debug_eq_hash_for!(
|
||||||
|
struct RegistrationResponse<CS: CipherSuite>,
|
||||||
|
[beta, server_s_pk],
|
||||||
|
[CS::Group],
|
||||||
|
);
|
||||||
|
|
||||||
impl<CS: CipherSuite> RegistrationResponse<CS> {
|
impl<CS: CipherSuite> RegistrationResponse<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
@@ -136,16 +144,14 @@ pub struct RegistrationUpload<CS: CipherSuite> {
|
|||||||
pub(crate) client_s_pk: PublicKey,
|
pub(crate) client_s_pk: PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot be derived because it would require for CS to be Clone.
|
impl_clone_for!(
|
||||||
impl<CS: CipherSuite> Clone for RegistrationUpload<CS> {
|
struct RegistrationUpload<CS: CipherSuite>,
|
||||||
fn clone(&self) -> Self {
|
[envelope, masking_key, client_s_pk],
|
||||||
Self {
|
);
|
||||||
envelope: self.envelope.clone(),
|
impl_debug_eq_hash_for!(
|
||||||
masking_key: self.masking_key.clone(),
|
struct RegistrationUpload<CS: CipherSuite>,
|
||||||
client_s_pk: self.client_s_pk.clone(),
|
[envelope, masking_key, client_s_pk],
|
||||||
}
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> RegistrationUpload<CS> {
|
impl<CS: CipherSuite> RegistrationUpload<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
@@ -211,6 +217,15 @@ impl<CS: CipherSuite> Clone for CredentialRequest<CS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_debug_eq_hash_for!(
|
||||||
|
struct CredentialRequest<CS: CipherSuite>,
|
||||||
|
[alpha, ke1_message],
|
||||||
|
[
|
||||||
|
CS::Group,
|
||||||
|
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1Message
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
impl<CS: CipherSuite> CredentialRequest<CS> {
|
impl<CS: CipherSuite> CredentialRequest<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
@@ -266,6 +281,15 @@ impl<CS: CipherSuite> Clone for CredentialResponse<CS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_debug_eq_hash_for!(
|
||||||
|
struct CredentialResponse<CS: CipherSuite>,
|
||||||
|
[beta, masking_nonce, masked_response, ke2_message],
|
||||||
|
[
|
||||||
|
CS::Group,
|
||||||
|
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2Message,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
impl<CS: CipherSuite> CredentialResponse<CS> {
|
impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
@@ -336,14 +360,12 @@ pub struct CredentialFinalization<CS: CipherSuite> {
|
|||||||
pub(crate) ke3_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message,
|
pub(crate) ke3_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot be derived because it would require for CS to be Clone.
|
impl_clone_for!(struct CredentialFinalization<CS: CipherSuite>, [ke3_message]);
|
||||||
impl<CS: CipherSuite> Clone for CredentialFinalization<CS> {
|
impl_debug_eq_hash_for!(
|
||||||
fn clone(&self) -> Self {
|
struct CredentialFinalization<CS: CipherSuite>,
|
||||||
Self {
|
[ke3_message],
|
||||||
ke3_message: self.ke3_message.clone(),
|
[<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message],
|
||||||
}
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> CredentialFinalization<CS> {
|
impl<CS: CipherSuite> CredentialFinalization<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
|
|||||||
+42
-33
@@ -36,6 +36,7 @@ const STR_OPRF_KEY: &[u8] = b"OprfKey";
|
|||||||
// ============
|
// ============
|
||||||
|
|
||||||
/// The state elements the server holds upon setup
|
/// The state elements the server holds upon setup
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct ServerSetup<CS: CipherSuite> {
|
pub struct ServerSetup<CS: CipherSuite> {
|
||||||
oprf_seed: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
oprf_seed: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||||
keypair: KeyPair<CS::Group>,
|
keypair: KeyPair<CS::Group>,
|
||||||
@@ -84,6 +85,16 @@ impl<CS: CipherSuite> ServerSetup<CS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cannot be derived because it would require for CS to be bound.
|
||||||
|
impl_clone_for!(
|
||||||
|
struct ServerSetup<CS: CipherSuite>,
|
||||||
|
[oprf_seed, keypair, fake_keypair],
|
||||||
|
);
|
||||||
|
impl_debug_eq_hash_for!(
|
||||||
|
struct ServerSetup<CS: CipherSuite>,
|
||||||
|
[oprf_seed, oprf_seed, fake_keypair],
|
||||||
|
);
|
||||||
|
|
||||||
// Registration
|
// Registration
|
||||||
// ============
|
// ============
|
||||||
|
|
||||||
@@ -93,14 +104,12 @@ pub struct ClientRegistration<CS: CipherSuite> {
|
|||||||
pub(crate) token: oprf::Token<CS::Group>,
|
pub(crate) token: oprf::Token<CS::Group>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot be derived because it would require for CS to be Clone.
|
impl_clone_for!(struct ClientRegistration<CS: CipherSuite>, [token]);
|
||||||
impl<CS: CipherSuite> Clone for ClientRegistration<CS> {
|
impl_debug_eq_hash_for!(
|
||||||
fn clone(&self) -> Self {
|
struct ClientRegistration<CS: CipherSuite>,
|
||||||
Self {
|
[token],
|
||||||
token: self.token.clone(),
|
[oprf::Token<CS::Group>],
|
||||||
}
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> ClientRegistration<CS> {
|
impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
@@ -306,12 +315,11 @@ impl<CS: CipherSuite> Clone for ServerRegistrationStartResult<CS> {
|
|||||||
/// The state elements the server holds to record a registration
|
/// The state elements the server holds to record a registration
|
||||||
pub struct ServerRegistration<CS: CipherSuite>(RegistrationUpload<CS>);
|
pub struct ServerRegistration<CS: CipherSuite>(RegistrationUpload<CS>);
|
||||||
|
|
||||||
// Cannot be derived because it would require for CS to be Clone.
|
impl_clone_for!(tuple ServerRegistration<CS: CipherSuite>, [0]);
|
||||||
impl<CS: CipherSuite> Clone for ServerRegistration<CS> {
|
impl_debug_eq_hash_for!(
|
||||||
fn clone(&self) -> Self {
|
tuple ServerRegistration<CS: CipherSuite>,
|
||||||
Self(self.0.clone())
|
[0],
|
||||||
}
|
);
|
||||||
}
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> ServerRegistration<CS> {
|
impl<CS: CipherSuite> ServerRegistration<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
@@ -377,6 +385,14 @@ impl_serialize_and_deserialize_for!(ServerRegistration);
|
|||||||
// =====
|
// =====
|
||||||
|
|
||||||
/// The state elements the client holds to perform a login
|
/// The state elements the client holds to perform a login
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
serde(bound(
|
||||||
|
deserialize = "oprf::Token<CS::Group>: serde::Deserialize<'de>, <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State: serde::Deserialize<'de>",
|
||||||
|
serialize = "oprf::Token<CS::Group>: serde::Serialize, <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State: serde::Serialize"
|
||||||
|
))
|
||||||
|
)]
|
||||||
pub struct ClientLogin<CS: CipherSuite> {
|
pub struct ClientLogin<CS: CipherSuite> {
|
||||||
/// token containing the client's password and the blinding factor
|
/// token containing the client's password and the blinding factor
|
||||||
token: oprf::Token<CS::Group>,
|
token: oprf::Token<CS::Group>,
|
||||||
@@ -384,16 +400,12 @@ pub struct ClientLogin<CS: CipherSuite> {
|
|||||||
serialized_credential_request: Vec<u8>,
|
serialized_credential_request: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot be derived because it would require for CS to be Clone.
|
impl_clone_for!(struct ClientLogin<CS: CipherSuite>, [token, ke1_state, serialized_credential_request]);
|
||||||
impl<CS: CipherSuite> Clone for ClientLogin<CS> {
|
impl_debug_eq_hash_for!(
|
||||||
fn clone(&self) -> Self {
|
struct ClientLogin<CS: CipherSuite>,
|
||||||
Self {
|
[token, ke1_state, serialized_credential_request],
|
||||||
token: self.token.clone(),
|
[oprf::Token<CS::Group>, <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State],
|
||||||
ke1_state: self.ke1_state.clone(),
|
);
|
||||||
serialized_credential_request: self.serialized_credential_request.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> ClientLogin<CS> {
|
impl<CS: CipherSuite> ClientLogin<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
@@ -627,15 +639,12 @@ pub struct ServerLogin<CS: CipherSuite> {
|
|||||||
_cs: PhantomData<CS>,
|
_cs: PhantomData<CS>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot be derived because it would require for CS to be Clone.
|
impl_clone_for!(struct ServerLogin<CS: CipherSuite>, [ke2_state, _cs]);
|
||||||
impl<CS: CipherSuite> Clone for ServerLogin<CS> {
|
impl_debug_eq_hash_for!(
|
||||||
fn clone(&self) -> Self {
|
struct ServerLogin<CS: CipherSuite>,
|
||||||
Self {
|
[ke2_state, _cs],
|
||||||
ke2_state: self.ke2_state.clone(),
|
[<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2State],
|
||||||
_cs: PhantomData,
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Optional parameters for server login start
|
/// Optional parameters for server login start
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|||||||
+3
-1
@@ -12,12 +12,14 @@ use generic_array::GenericArray;
|
|||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
|
|
||||||
/// Used to store the OPRF input and blinding factor
|
/// Used to store the OPRF input and blinding factor
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Token<Grp: Group> {
|
pub struct Token<Grp: Group> {
|
||||||
pub(crate) data: Vec<u8>,
|
pub(crate) data: Vec<u8>,
|
||||||
pub(crate) blind: Grp::Scalar,
|
pub(crate) blind: Grp::Scalar,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_clone_for!(struct Token<Grp: Group>, [data, blind]);
|
||||||
|
impl_debug_eq_hash_for!(struct Token<Grp: Group>, [data, blind], [Grp::Scalar]);
|
||||||
|
|
||||||
static STR_VOPRF: &[u8] = b"VOPRF06-HashToGroup-";
|
static STR_VOPRF: &[u8] = b"VOPRF06-HashToGroup-";
|
||||||
static STR_VOPRF_FINALIZE: &[u8] = b"VOPRF06-Finalize-";
|
static STR_VOPRF_FINALIZE: &[u8] = b"VOPRF06-Finalize-";
|
||||||
static MODE_BASE: u8 = 0x00;
|
static MODE_BASE: u8 = 0x00;
|
||||||
|
|||||||
Reference in New Issue
Block a user