Introduce PrivateKey associated type to CipherSuite
This commit is contained in:
@@ -32,6 +32,7 @@ use std::process::exit;
|
|||||||
|
|
||||||
use opaque_ke::{
|
use opaque_ke::{
|
||||||
ciphersuite::CipherSuite,
|
ciphersuite::CipherSuite,
|
||||||
|
keypair::PrivateKey,
|
||||||
rand::{rngs::OsRng, RngCore},
|
rand::{rngs::OsRng, RngCore},
|
||||||
ClientLogin, ClientLoginFinishParameters, ClientRegistration,
|
ClientLogin, ClientLoginFinishParameters, ClientRegistration,
|
||||||
ClientRegistrationFinishParameters, CredentialFinalization, CredentialRequest,
|
ClientRegistrationFinishParameters, CredentialFinalization, CredentialRequest,
|
||||||
@@ -48,6 +49,7 @@ impl CipherSuite for Default {
|
|||||||
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
type Hash = sha2::Sha512;
|
type Hash = sha2::Sha512;
|
||||||
type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
type PrivateKey = PrivateKey<Self::Group>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Locker {
|
struct Locker {
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ use std::collections::HashMap;
|
|||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use opaque_ke::{
|
use opaque_ke::{
|
||||||
ciphersuite::CipherSuite, rand::rngs::OsRng, ClientLogin, ClientLoginFinishParameters,
|
ciphersuite::CipherSuite, keypair::PrivateKey, rand::rngs::OsRng, ClientLogin,
|
||||||
ClientRegistration, ClientRegistrationFinishParameters, CredentialFinalization,
|
ClientLoginFinishParameters, ClientRegistration, ClientRegistrationFinishParameters,
|
||||||
CredentialRequest, CredentialResponse, RegistrationRequest, RegistrationResponse,
|
CredentialFinalization, CredentialRequest, CredentialResponse, RegistrationRequest,
|
||||||
RegistrationUpload, ServerLogin, ServerLoginStartParameters, ServerRegistration, ServerSetup,
|
RegistrationResponse, RegistrationUpload, ServerLogin, ServerLoginStartParameters,
|
||||||
|
ServerRegistration, ServerSetup,
|
||||||
};
|
};
|
||||||
|
|
||||||
// The ciphersuite trait allows to specify the underlying primitives
|
// The ciphersuite trait allows to specify the underlying primitives
|
||||||
@@ -41,6 +42,7 @@ impl CipherSuite for Default {
|
|||||||
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
type Hash = sha2::Sha512;
|
type Hash = sha2::Sha512;
|
||||||
type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
type PrivateKey = PrivateKey<Self::Group>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Password-based registration between a client and server
|
// Password-based registration between a client and server
|
||||||
|
|||||||
+4
-2
@@ -6,8 +6,8 @@
|
|||||||
//! Defines the CipherSuite trait to specify the underlying primitives for OPAQUE
|
//! Defines the CipherSuite trait to specify the underlying primitives for OPAQUE
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hash::Hash, key_exchange::traits::KeyExchange, map_to_curve::GroupWithMapToCurve,
|
hash::Hash, key_exchange::traits::KeyExchange, keypair::SecretKey,
|
||||||
slow_hash::SlowHash,
|
map_to_curve::GroupWithMapToCurve, slow_hash::SlowHash,
|
||||||
};
|
};
|
||||||
use digest::Digest;
|
use digest::Digest;
|
||||||
|
|
||||||
@@ -31,4 +31,6 @@ pub trait CipherSuite {
|
|||||||
type Hash: Hash;
|
type Hash: Hash;
|
||||||
/// A slow hashing function, typically used for password hashing
|
/// A slow hashing function, typically used for password hashing
|
||||||
type SlowHash: SlowHash<Self::Hash>;
|
type SlowHash: SlowHash<Self::Hash>;
|
||||||
|
/// A private key container, allows remote key implementations
|
||||||
|
type PrivateKey: SecretKey<Self::Group>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
errors::{PakeError, ProtocolError},
|
errors::{PakeError, ProtocolError},
|
||||||
group::Group,
|
group::Group,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
keypair::{PrivateKey, PublicKey},
|
keypair::{PrivateKey, PublicKey, SecretKey},
|
||||||
};
|
};
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
@@ -25,13 +25,13 @@ pub trait KeyExchange<D: Hash, G: Group> {
|
|||||||
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>;
|
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>;
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||||
fn generate_ke2<R: RngCore + CryptoRng>(
|
fn generate_ke2<R: RngCore + CryptoRng, S: SecretKey<G>>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
l1_bytes: Vec<u8>,
|
l1_bytes: Vec<u8>,
|
||||||
l2_bytes: Vec<u8>,
|
l2_bytes: Vec<u8>,
|
||||||
ke1_message: Self::KE1Message,
|
ke1_message: Self::KE1Message,
|
||||||
client_s_pk: PublicKey<G>,
|
client_s_pk: PublicKey<G>,
|
||||||
server_s_sk: PrivateKey<G>,
|
server_s_sk: S,
|
||||||
id_u: Vec<u8>,
|
id_u: Vec<u8>,
|
||||||
id_s: Vec<u8>,
|
id_s: Vec<u8>,
|
||||||
context: Vec<u8>,
|
context: Vec<u8>,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use crate::{
|
|||||||
group::Group,
|
group::Group,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
key_exchange::traits::{FromBytes, KeyExchange, ToBytes, ToBytesWithPointers},
|
key_exchange::traits::{FromBytes, KeyExchange, ToBytes, ToBytesWithPointers},
|
||||||
keypair::{KeyPair, PrivateKey, PublicKey, SizedBytesExt},
|
keypair::{KeyPair, PrivateKey, PublicKey, SecretKey, SizedBytesExt},
|
||||||
serialization::serialize,
|
serialization::serialize,
|
||||||
};
|
};
|
||||||
use digest::{Digest, FixedOutput};
|
use digest::{Digest, FixedOutput};
|
||||||
@@ -70,13 +70,13 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn generate_ke2<R: RngCore + CryptoRng>(
|
fn generate_ke2<R: RngCore + CryptoRng, S: SecretKey<G>>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
serialized_credential_request: Vec<u8>,
|
serialized_credential_request: Vec<u8>,
|
||||||
l2_bytes: Vec<u8>,
|
l2_bytes: Vec<u8>,
|
||||||
ke1_message: Self::KE1Message,
|
ke1_message: Self::KE1Message,
|
||||||
client_s_pk: PublicKey<G>,
|
client_s_pk: PublicKey<G>,
|
||||||
server_s_sk: PrivateKey<G>,
|
server_s_sk: S,
|
||||||
id_u: Vec<u8>,
|
id_u: Vec<u8>,
|
||||||
id_s: Vec<u8>,
|
id_s: Vec<u8>,
|
||||||
context: Vec<u8>,
|
context: Vec<u8>,
|
||||||
@@ -94,7 +94,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
|||||||
.chain(&server_nonce[..])
|
.chain(&server_nonce[..])
|
||||||
.chain(&server_e_kp.public().to_arr());
|
.chain(&server_e_kp.public().to_arr());
|
||||||
|
|
||||||
let (session_key, km2, km3) = derive_3dh_keys::<D, G>(
|
let (session_key, km2, km3) = derive_3dh_keys::<D, G, S>(
|
||||||
TripleDHComponents {
|
TripleDHComponents {
|
||||||
pk1: ke1_message.client_e_pk.clone(),
|
pk1: ke1_message.client_e_pk.clone(),
|
||||||
sk1: server_e_kp.private().clone(),
|
sk1: server_e_kp.private().clone(),
|
||||||
@@ -148,7 +148,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
|||||||
.chain(&l2_component[..])
|
.chain(&l2_component[..])
|
||||||
.chain(&ke2_message.to_bytes_without_info_or_mac());
|
.chain(&ke2_message.to_bytes_without_info_or_mac());
|
||||||
|
|
||||||
let (session_key, km2, km3) = derive_3dh_keys::<D, G>(
|
let (session_key, km2, km3) = derive_3dh_keys::<D, G, PrivateKey<G>>(
|
||||||
TripleDHComponents {
|
TripleDHComponents {
|
||||||
pk1: ke2_message.server_e_pk.clone(),
|
pk1: ke2_message.server_e_pk.clone(),
|
||||||
sk1: ke1_state.client_e_sk.clone(),
|
sk1: ke1_state.client_e_sk.clone(),
|
||||||
@@ -408,11 +408,11 @@ impl<G: Group, HashLen: ArrayLength<u8>> FromBytes for Ke2Message<G, HashLen> {
|
|||||||
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
// The triple of public and private components used in the 3DH computation
|
// The triple of public and private components used in the 3DH computation
|
||||||
struct TripleDHComponents<G: Group> {
|
struct TripleDHComponents<G: Group, S: SecretKey<G>> {
|
||||||
pk1: PublicKey<G>,
|
pk1: PublicKey<G>,
|
||||||
sk1: PrivateKey<G>,
|
sk1: PrivateKey<G>,
|
||||||
pk2: PublicKey<G>,
|
pk2: PublicKey<G>,
|
||||||
sk2: PrivateKey<G>,
|
sk2: S,
|
||||||
pk3: PublicKey<G>,
|
pk3: PublicKey<G>,
|
||||||
sk3: PrivateKey<G>,
|
sk3: PrivateKey<G>,
|
||||||
}
|
}
|
||||||
@@ -453,14 +453,14 @@ impl<HashLen: ArrayLength<u8>> FromBytes for Ke3Message<HashLen> {
|
|||||||
|
|
||||||
// Internal function which takes the public and private components of the client and server keypairs, along
|
// Internal function which takes the public and private components of the client and server keypairs, along
|
||||||
// with some auxiliary metadata, to produce the session key and two MAC keys
|
// with some auxiliary metadata, to produce the session key and two MAC keys
|
||||||
fn derive_3dh_keys<D: Hash, G: Group>(
|
fn derive_3dh_keys<D: Hash, G: Group, S: SecretKey<G>>(
|
||||||
dh: TripleDHComponents<G>,
|
dh: TripleDHComponents<G, S>,
|
||||||
hashed_derivation_transcript: &[u8],
|
hashed_derivation_transcript: &[u8],
|
||||||
) -> Result<TripleDHDerivationResult<D>, ProtocolError> {
|
) -> Result<TripleDHDerivationResult<D>, ProtocolError> {
|
||||||
let ikm: Vec<u8> = [
|
let ikm: Vec<u8> = [
|
||||||
&KeyPair::<G>::diffie_hellman(dh.pk1, dh.sk1)?[..],
|
&dh.sk1.diffie_hellman(dh.pk1)?[..],
|
||||||
&KeyPair::<G>::diffie_hellman(dh.pk2, dh.sk2)?[..],
|
&dh.sk2.diffie_hellman(dh.pk2)?[..],
|
||||||
&KeyPair::<G>::diffie_hellman(dh.pk3, dh.sk3)?[..],
|
&dh.sk3.diffie_hellman(dh.pk3)?[..],
|
||||||
]
|
]
|
||||||
.concat();
|
.concat();
|
||||||
|
|
||||||
|
|||||||
+101
-51
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use crate::errors::InternalPakeError;
|
use crate::errors::{InternalPakeError, PakeError, ProtocolError};
|
||||||
use crate::group::Group;
|
use crate::group::Group;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use generic_array::typenum::Unsigned;
|
use generic_array::typenum::Unsigned;
|
||||||
@@ -37,65 +37,74 @@ impl<T> SizedBytesExt for T where T: SizedBytes {}
|
|||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
derive(serde::Deserialize, serde::Serialize),
|
derive(serde::Deserialize, serde::Serialize),
|
||||||
serde(bound = "")
|
serde(bound(
|
||||||
|
deserialize = "S: serde::Deserialize<'de>",
|
||||||
|
serialize = "S: serde::Serialize"
|
||||||
|
))
|
||||||
)]
|
)]
|
||||||
pub struct KeyPair<G: Group> {
|
pub struct KeyPair<G: Group, S: SecretKey<G> = PrivateKey<G>> {
|
||||||
pk: PublicKey<G>,
|
pk: PublicKey<G>,
|
||||||
sk: PrivateKey<G>,
|
sk: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_clone_for!(
|
impl<G: Group, S: SecretKey<G>> Clone for KeyPair<G, S> {
|
||||||
struct KeyPair<G: Group>,
|
fn clone(&self) -> Self {
|
||||||
[pk, sk],
|
Self {
|
||||||
);
|
pk: self.pk.clone(),
|
||||||
impl_debug_eq_hash_for!(
|
sk: self.sk.clone(),
|
||||||
struct KeyPair<G: Group>,
|
}
|
||||||
[pk, sk],
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
|
impl<G: Group, S: SecretKey<G> + Debug> Debug for KeyPair<G, S> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("KeyPair")
|
||||||
|
.field("pk", &self.pk)
|
||||||
|
.field("sk", &self.sk)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: Group, S: SecretKey<G> + PartialEq> PartialEq for KeyPair<G, S> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.pk.eq(&other.pk) && self.sk.eq(&other.sk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: Group, S: SecretKey<G> + Eq> Eq for KeyPair<G, S> {}
|
||||||
|
|
||||||
|
impl<G: Group, S: SecretKey<G> + std::hash::Hash> std::hash::Hash for KeyPair<G, S> {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.pk.hash(state);
|
||||||
|
self.sk.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This can't be derived because of the use of a generic parameter
|
// This can't be derived because of the use of a generic parameter
|
||||||
impl<G: Group> Zeroize for KeyPair<G> {
|
impl<G: Group, S: SecretKey<G>> Zeroize for KeyPair<G, S> {
|
||||||
fn zeroize(&mut self) {
|
fn zeroize(&mut self) {
|
||||||
self.pk.zeroize();
|
self.pk.zeroize();
|
||||||
self.sk.zeroize();
|
self.sk.zeroize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> Drop for KeyPair<G> {
|
impl<G: Group, S: SecretKey<G>> Drop for KeyPair<G, S> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.zeroize();
|
self.zeroize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> KeyPair<G> {
|
impl<G: Group, S: SecretKey<G>> KeyPair<G, S> {
|
||||||
/// The public key component
|
/// The public key component
|
||||||
pub fn public(&self) -> &PublicKey<G> {
|
pub fn public(&self) -> &PublicKey<G> {
|
||||||
&self.pk
|
&self.pk
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The private key component
|
/// The private key component
|
||||||
pub fn private(&self) -> &PrivateKey<G> {
|
pub fn private(&self) -> &S {
|
||||||
&self.sk
|
&self.sk
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generating a random key pair given a cryptographic rng
|
|
||||||
pub(crate) fn generate_random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
|
||||||
let sk = G::random_nonzero_scalar(rng);
|
|
||||||
let sk_bytes = G::scalar_as_bytes(sk);
|
|
||||||
let pk = G::base_point().mult_by_slice(&sk_bytes);
|
|
||||||
Self {
|
|
||||||
pk: PublicKey(Key(pk.to_arr())),
|
|
||||||
sk: PrivateKey(Key(sk_bytes)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtaining a public key from secret bytes. At all times, we should have
|
|
||||||
/// &public_from_private(self.private()) == self.public()
|
|
||||||
pub(crate) fn public_from_private(bytes: &PrivateKey<G>) -> PublicKey<G> {
|
|
||||||
let bytes_data = GenericArray::<u8, G::ScalarLen>::from_slice(&bytes.0[..]);
|
|
||||||
PublicKey(Key(G::base_point().mult_by_slice(bytes_data).to_arr()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check whether a public key is valid. This is meant to be applied on
|
/// Check whether a public key is valid. This is meant to be applied on
|
||||||
/// material provided through the network which fits the key
|
/// material provided through the network which fits the key
|
||||||
/// representation (i.e. can be mapped to a curve point), but presents
|
/// representation (i.e. can be mapped to a curve point), but presents
|
||||||
@@ -104,23 +113,25 @@ impl<G: Group> KeyPair<G> {
|
|||||||
G::from_element_slice(GenericArray::from_slice(&key.0)).map(|_| key)
|
G::from_element_slice(GenericArray::from_slice(&key.0)).map(|_| key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the diffie hellman function on a public key and private key
|
|
||||||
pub(crate) fn diffie_hellman(
|
|
||||||
pk: PublicKey<G>,
|
|
||||||
sk: PrivateKey<G>,
|
|
||||||
) -> Result<Vec<u8>, InternalPakeError> {
|
|
||||||
let pk_data = GenericArray::<u8, G::ElemLen>::from_slice(&pk.0[..]);
|
|
||||||
let point = G::from_element_slice(pk_data)?;
|
|
||||||
let secret_data = GenericArray::<u8, G::ScalarLen>::from_slice(&sk.0[..]);
|
|
||||||
Ok(G::mult_by_slice(&point, secret_data).to_arr().to_vec())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtains a KeyPair from a slice representing the private key
|
/// Obtains a KeyPair from a slice representing the private key
|
||||||
pub fn from_private_key_slice(input: &[u8]) -> Result<Self, InternalPakeError> {
|
pub fn from_private_key_slice(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||||
let sk = PrivateKey(Key(GenericArray::clone_from_slice(input)));
|
let sk = S::deserialize(input)?;
|
||||||
let pk = Self::public_from_private(&sk);
|
let pk = sk.public_key()?;
|
||||||
Ok(Self { pk, sk })
|
Ok(Self { pk, sk })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: Group> KeyPair<G> {
|
||||||
|
/// Generating a random key pair given a cryptographic rng
|
||||||
|
pub(crate) fn generate_random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
||||||
|
let sk = G::random_nonzero_scalar(rng);
|
||||||
|
let sk_bytes = G::scalar_as_bytes(sk);
|
||||||
|
let pk = G::base_point().mult_by_slice(&sk_bytes);
|
||||||
|
Self {
|
||||||
|
pk: PublicKey(Key(pk.to_arr())),
|
||||||
|
sk: PrivateKey(Key(sk_bytes)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
|
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
|
||||||
@@ -263,6 +274,45 @@ impl<G: Group> SizedBytes for PrivateKey<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait specifying the requirements for a private key container
|
||||||
|
pub trait SecretKey<G: Group>: Clone + Sized + Zeroize {
|
||||||
|
/// Diffie-Hellman key exchange implementation
|
||||||
|
fn diffie_hellman(&self, pk: PublicKey<G>) -> Result<Vec<u8>, InternalPakeError>;
|
||||||
|
|
||||||
|
/// Returns public key from private key
|
||||||
|
fn public_key(&self) -> Result<PublicKey<G>, InternalPakeError>;
|
||||||
|
|
||||||
|
/// Serialization into bytes
|
||||||
|
fn serialize(&self) -> Vec<u8>;
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
fn deserialize(input: &[u8]) -> Result<Self, ProtocolError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: Group> SecretKey<G> for PrivateKey<G> {
|
||||||
|
fn diffie_hellman(&self, pk: PublicKey<G>) -> Result<Vec<u8>, InternalPakeError> {
|
||||||
|
let pk_data = GenericArray::<u8, G::ElemLen>::from_slice(&pk.0[..]);
|
||||||
|
let point = G::from_element_slice(pk_data)?;
|
||||||
|
let secret_data = GenericArray::<u8, G::ScalarLen>::from_slice(&self.0[..]);
|
||||||
|
Ok(G::mult_by_slice(&point, secret_data).to_arr().to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn public_key(&self) -> Result<PublicKey<G>, InternalPakeError> {
|
||||||
|
let bytes_data = GenericArray::<u8, G::ScalarLen>::from_slice(&self.0[..]);
|
||||||
|
Ok(PublicKey(Key(G::base_point()
|
||||||
|
.mult_by_slice(bytes_data)
|
||||||
|
.to_arr())))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self) -> Vec<u8> {
|
||||||
|
self.to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||||
|
PrivateKey::from_bytes(input).map_err(|_| PakeError::SerializationError.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper around a Key to enforce that it's a public one.
|
/// Wrapper around a Key to enforce that it's a public one.
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@@ -364,15 +414,15 @@ mod tests {
|
|||||||
fn test_ristretto_pub_from_priv(kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
fn test_ristretto_pub_from_priv(kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||||
let pk = kp.public();
|
let pk = kp.public();
|
||||||
let sk = kp.private();
|
let sk = kp.private();
|
||||||
prop_assert_eq!(&KeyPair::<RistrettoPoint>::public_from_private(sk), pk);
|
prop_assert_eq!(&sk.public_key()?, pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ristretto_dh(kp1 in KeyPair::<RistrettoPoint>::uniform_keypair_strategy(),
|
fn test_ristretto_dh(kp1 in KeyPair::<RistrettoPoint>::uniform_keypair_strategy(),
|
||||||
kp2 in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
kp2 in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||||
|
|
||||||
let dh1 = KeyPair::<RistrettoPoint>::diffie_hellman(kp1.public().clone(), kp2.private().clone())?;
|
let dh1 = kp2.private().diffie_hellman(kp1.public().clone())?;
|
||||||
let dh2 = KeyPair::<RistrettoPoint>::diffie_hellman(kp2.public().clone(), kp1.private().clone())?;
|
let dh2 = kp1.private().diffie_hellman(kp2.public().clone())?;
|
||||||
|
|
||||||
prop_assert_eq!(dh1, dh2);
|
prop_assert_eq!(dh1, dh2);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
@@ -26,6 +26,7 @@
|
|||||||
//! type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! type Hash = sha2::Sha512;
|
//! type Hash = sha2::Sha512;
|
||||||
//! type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//! See [examples/simple_login.rs](https://github.com/novifinancial/opaque-ke/blob/master/examples/simple_login.rs)
|
//! See [examples/simple_login.rs](https://github.com/novifinancial/opaque-ke/blob/master/examples/simple_login.rs)
|
||||||
@@ -47,6 +48,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! use rand::{rngs::OsRng, RngCore};
|
//! use rand::{rngs::OsRng, RngCore};
|
||||||
//! let mut rng = OsRng;
|
//! let mut rng = OsRng;
|
||||||
@@ -79,6 +81,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! use opaque_ke::ClientRegistration;
|
//! use opaque_ke::ClientRegistration;
|
||||||
//! use rand::{rngs::OsRng, RngCore};
|
//! use rand::{rngs::OsRng, RngCore};
|
||||||
@@ -109,6 +112,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -146,6 +150,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -184,6 +189,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -226,6 +232,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! use opaque_ke::ClientLogin;
|
//! use opaque_ke::ClientLogin;
|
||||||
@@ -259,6 +266,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -312,6 +320,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -357,6 +366,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -432,6 +442,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -509,6 +520,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -574,6 +586,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -611,6 +624,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
@@ -660,6 +674,7 @@
|
|||||||
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
//! # type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
|
||||||
//! # type Hash = sha2::Sha512;
|
//! # type Hash = sha2::Sha512;
|
||||||
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
//! # type SlowHash = opaque_ke::slow_hash::NoOpHash;
|
||||||
|
//! # type PrivateKey = opaque_ke::keypair::PrivateKey<Self::Group>;
|
||||||
//! # }
|
//! # }
|
||||||
//! # use rand::{rngs::OsRng, RngCore};
|
//! # use rand::{rngs::OsRng, RngCore};
|
||||||
//! # let mut client_rng = OsRng;
|
//! # let mut client_rng = OsRng;
|
||||||
|
|||||||
+17
-8
@@ -12,7 +12,7 @@ use crate::{
|
|||||||
group::Group,
|
group::Group,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
key_exchange::traits::{FromBytes, KeyExchange, ToBytesWithPointers},
|
key_exchange::traits::{FromBytes, KeyExchange, ToBytesWithPointers},
|
||||||
keypair::{KeyPair, PrivateKey, PublicKey},
|
keypair::{KeyPair, PrivateKey, PublicKey, SecretKey},
|
||||||
map_to_curve::GroupWithMapToCurve,
|
map_to_curve::GroupWithMapToCurve,
|
||||||
oprf,
|
oprf,
|
||||||
serialization::{serialize, tokenize},
|
serialization::{serialize, tokenize},
|
||||||
@@ -37,14 +37,21 @@ const STR_OPAQUE_DERIVE_KEY_PAIR: &[u8] = b"OPAQUE-DeriveKeyPair";
|
|||||||
// ============
|
// ============
|
||||||
|
|
||||||
/// 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))]
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
derive(serde::Deserialize, serde::Serialize),
|
||||||
|
serde(bound(
|
||||||
|
deserialize = "KeyPair<CS::Group, CS::PrivateKey>: serde::Deserialize<'de>",
|
||||||
|
serialize = "KeyPair<CS::Group, CS::PrivateKey>: 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, CS::PrivateKey>,
|
||||||
pub(crate) fake_keypair: KeyPair<CS::Group>,
|
pub(crate) fake_keypair: KeyPair<CS::Group>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CS: CipherSuite> ServerSetup<CS> {
|
impl<CS: CipherSuite<Group = G, PrivateKey = PrivateKey<G>>, G: Group> ServerSetup<CS> {
|
||||||
/// Generate a new instance of server setup
|
/// Generate a new instance of server setup
|
||||||
pub fn new<R: CryptoRng + RngCore>(rng: &mut R) -> Self {
|
pub fn new<R: CryptoRng + RngCore>(rng: &mut R) -> Self {
|
||||||
let mut seed = vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()];
|
let mut seed = vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()];
|
||||||
@@ -56,13 +63,15 @@ impl<CS: CipherSuite> ServerSetup<CS> {
|
|||||||
fake_keypair: KeyPair::<CS::Group>::generate_random(rng),
|
fake_keypair: KeyPair::<CS::Group>::generate_random(rng),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> ServerSetup<CS> {
|
||||||
/// Serialization into bytes
|
/// Serialization into bytes
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
[
|
[
|
||||||
self.oprf_seed.to_vec(),
|
self.oprf_seed.to_vec(),
|
||||||
self.keypair.private().to_arr().to_vec(),
|
self.keypair.private().serialize(),
|
||||||
self.fake_keypair.private().to_arr().to_vec(),
|
self.fake_keypair.private().serialize(),
|
||||||
]
|
]
|
||||||
.concat()
|
.concat()
|
||||||
}
|
}
|
||||||
@@ -81,7 +90,7 @@ impl<CS: CipherSuite> ServerSetup<CS> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the keypair
|
/// Returns the keypair
|
||||||
pub fn keypair(&self) -> &KeyPair<CS::Group> {
|
pub fn keypair(&self) -> &KeyPair<CS::Group, CS::PrivateKey> {
|
||||||
&self.keypair
|
&self.keypair
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -775,7 +784,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let server_s_sk = server_setup.keypair.private();
|
let server_s_sk = server_setup.keypair.private();
|
||||||
let server_s_pk = KeyPair::<CS::Group>::public_from_private(server_s_sk);
|
let server_s_pk = server_s_sk.public_key()?;
|
||||||
|
|
||||||
let mut masking_nonce = vec![0u8; 32];
|
let mut masking_nonce = vec![0u8; 32];
|
||||||
rng.fill_bytes(&mut masking_nonce);
|
rng.fill_bytes(&mut masking_nonce);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use crate::{
|
|||||||
traits::{FromBytes, KeyExchange, ToBytes},
|
traits::{FromBytes, KeyExchange, ToBytes},
|
||||||
tripledh::{NonceLen, TripleDH},
|
tripledh::{NonceLen, TripleDH},
|
||||||
},
|
},
|
||||||
keypair::{KeyPair, PublicKey},
|
keypair::{KeyPair, PrivateKey, PublicKey},
|
||||||
serialization::{i2osp, os2ip, serialize},
|
serialization::{i2osp, os2ip, serialize},
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
@@ -31,6 +31,7 @@ impl CipherSuite for Default {
|
|||||||
type KeyExchange = TripleDH;
|
type KeyExchange = TripleDH;
|
||||||
type Hash = sha2::Sha512;
|
type Hash = sha2::Sha512;
|
||||||
type SlowHash = crate::slow_hash::NoOpHash;
|
type SlowHash = crate::slow_hash::NoOpHash;
|
||||||
|
type PrivateKey = PrivateKey<RistrettoPoint>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HASH_SIZE: usize = 64; // Because of SHA512
|
const HASH_SIZE: usize = 64; // Because of SHA512
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::{
|
|||||||
errors::*,
|
errors::*,
|
||||||
group::Group,
|
group::Group,
|
||||||
key_exchange::tripledh::{NonceLen, TripleDH},
|
key_exchange::tripledh::{NonceLen, TripleDH},
|
||||||
keypair::KeyPair,
|
keypair::{KeyPair, PrivateKey},
|
||||||
opaque::*,
|
opaque::*,
|
||||||
slow_hash::NoOpHash,
|
slow_hash::NoOpHash,
|
||||||
tests::mock_rng::CycleRng,
|
tests::mock_rng::CycleRng,
|
||||||
@@ -33,6 +33,7 @@ impl CipherSuite for RistrettoSha5123dhNoSlowHash {
|
|||||||
type KeyExchange = TripleDH;
|
type KeyExchange = TripleDH;
|
||||||
type Hash = sha2::Sha512;
|
type Hash = sha2::Sha512;
|
||||||
type SlowHash = NoOpHash;
|
type SlowHash = NoOpHash;
|
||||||
|
type PrivateKey = PrivateKey<RistrettoPoint>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestVectorParameters {
|
pub struct TestVectorParameters {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ impl CipherSuite for Ristretto255Sha512NoSlowHash {
|
|||||||
type KeyExchange = TripleDH;
|
type KeyExchange = TripleDH;
|
||||||
type Hash = sha2::Sha512;
|
type Hash = sha2::Sha512;
|
||||||
type SlowHash = NoOpHash;
|
type SlowHash = NoOpHash;
|
||||||
|
type PrivateKey = PrivateKey<RistrettoPoint>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
|||||||
Reference in New Issue
Block a user