Merge pull request #51 from huitseeker/over_simplification

Make KeyExchange generic in KeyFormat
This commit is contained in:
François Garillot
2020-09-21 15:21:33 -04:00
committed by GitHub
2 changed files with 38 additions and 32 deletions
+2 -2
View File
@@ -6,13 +6,13 @@
use crate::{
errors::{InternalPakeError, ProtocolError},
hash::Hash,
keypair::{Key, KeyPair},
keypair::KeyPair,
};
use rand_core::{CryptoRng, RngCore};
use std::convert::TryFrom;
pub trait KeyExchange<D: Hash, KeyFormat: KeyPair<Repr = Key>> {
pub trait KeyExchange<D: Hash, KeyFormat: KeyPair> {
type KE1State: TryFrom<Vec<u8>, Error = InternalPakeError> + ToBytes;
type KE2State: TryFrom<Vec<u8>, Error = ProtocolError> + ToBytes;
type KE1Message: TryFrom<Vec<u8>, Error = InternalPakeError> + ToBytes;
+36 -30
View File
@@ -8,7 +8,7 @@ use crate::{
errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError},
hash::Hash,
key_exchange::traits::{KeyExchange, ToBytes},
keypair::{Key, KeyPair, SizedBytes},
keypair::{KeyPair, SizedBytes},
};
use digest::{Digest, FixedOutput};
use generic_array::{
@@ -31,11 +31,11 @@ static STR_3DH: &[u8] = b"3DH keys";
/// The Triple Diffie-Hellman key exchange implementation
pub struct TripleDH;
impl<D: Hash, KeyFormat: KeyPair<Repr = Key>> KeyExchange<D, KeyFormat> for TripleDH {
type KE1State = KE1State<<D as FixedOutput>::OutputSize>;
impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
type KE1State = KE1State<<D as FixedOutput>::OutputSize, KeyFormat>;
type KE2State = KE2State<<D as FixedOutput>::OutputSize>;
type KE1Message = KE1Message;
type KE2Message = KE2Message<<D as FixedOutput>::OutputSize>;
type KE1Message = KE1Message<KeyFormat>;
type KE2Message = KE2Message<<D as FixedOutput>::OutputSize, KeyFormat>;
type KE3Message = KE3Message<<D as FixedOutput>::OutputSize>;
fn generate_ke1<R: RngCore + CryptoRng>(
@@ -158,7 +158,7 @@ impl<D: Hash, KeyFormat: KeyPair<Repr = Key>> KeyExchange<D, KeyFormat> for Trip
&ke1_state.hashed_l1[..],
&l2_component[..],
&ke2_message.server_nonce[..],
&ke2_message.server_e_pk[..],
&ke2_message.server_e_pk.to_arr(),
]
.concat();
@@ -216,20 +216,22 @@ impl<D: Hash, KeyFormat: KeyPair<Repr = Key>> KeyExchange<D, KeyFormat> for Trip
/// The client state produced after the first key exchange message
#[derive(PartialEq, Eq)]
pub struct KE1State<HashLen: ArrayLength<u8>> {
client_e_sk: Key,
pub struct KE1State<HashLen: ArrayLength<u8>, KeyFormat: KeyPair> {
client_e_sk: KeyFormat::Repr,
client_nonce: GenericArray<u8, NonceLen>,
hashed_l1: GenericArray<u8, HashLen>,
}
/// The first key exchange message
#[derive(PartialEq, Eq)]
pub struct KE1Message {
pub struct KE1Message<KeyFormat: KeyPair> {
pub(crate) client_nonce: GenericArray<u8, NonceLen>,
pub(crate) client_e_pk: Key,
pub(crate) client_e_pk: KeyFormat::Repr,
}
impl<HashLen: ArrayLength<u8>> TryFrom<Vec<u8>> for KE1State<HashLen> {
impl<HashLen: ArrayLength<u8>, KeyFormat: KeyPair> TryFrom<Vec<u8>>
for KE1State<HashLen, KeyFormat>
{
type Error = InternalPakeError;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
@@ -240,7 +242,7 @@ impl<HashLen: ArrayLength<u8>> TryFrom<Vec<u8>> for KE1State<HashLen> {
)?;
Ok(Self {
client_e_sk: Key::from_bytes(&checked_bytes[..KEY_LEN])?,
client_e_sk: KeyFormat::Repr::from_bytes(&checked_bytes[..KEY_LEN])?,
client_nonce: GenericArray::clone_from_slice(
&checked_bytes[KEY_LEN..KEY_LEN + NONCE_LEN],
),
@@ -249,7 +251,7 @@ impl<HashLen: ArrayLength<u8>> TryFrom<Vec<u8>> for KE1State<HashLen> {
}
}
impl<HashLen: ArrayLength<u8>> ToBytes for KE1State<HashLen> {
impl<HashLen: ArrayLength<u8>, KeyFormat: KeyPair> ToBytes for KE1State<HashLen, KeyFormat> {
fn to_bytes(&self) -> Vec<u8> {
let output: Vec<u8> = [
&self.client_e_sk.to_arr(),
@@ -261,13 +263,13 @@ impl<HashLen: ArrayLength<u8>> ToBytes for KE1State<HashLen> {
}
}
impl ToBytes for KE1Message {
impl<KeyFormat: KeyPair> ToBytes for KE1Message<KeyFormat> {
fn to_bytes(&self) -> Vec<u8> {
[&self.client_nonce[..], &self.client_e_pk.to_arr()].concat()
}
}
impl TryFrom<Vec<u8>> for KE1Message {
impl<KeyFormat: KeyPair> TryFrom<Vec<u8>> for KE1Message<KeyFormat> {
type Error = InternalPakeError;
fn try_from(ke1_message_bytes: Vec<u8>) -> Result<Self, Self::Error> {
@@ -276,7 +278,7 @@ impl TryFrom<Vec<u8>> for KE1Message {
Ok(Self {
client_nonce: GenericArray::clone_from_slice(&checked_bytes[..NONCE_LEN]),
client_e_pk: Key::from_bytes(&checked_bytes[NONCE_LEN..])?,
client_e_pk: KeyFormat::Repr::from_bytes(&checked_bytes[NONCE_LEN..])?,
})
}
}
@@ -289,9 +291,9 @@ pub struct KE2State<HashLen: ArrayLength<u8>> {
}
/// The second key exchange message
pub struct KE2Message<HashLen: ArrayLength<u8>> {
pub struct KE2Message<HashLen: ArrayLength<u8>, KeyFormat: KeyPair> {
server_nonce: GenericArray<u8, NonceLen>,
server_e_pk: Key,
server_e_pk: KeyFormat::Repr,
mac: GenericArray<u8, HashLen>,
}
@@ -321,7 +323,7 @@ impl<HashLen: ArrayLength<u8>> TryFrom<Vec<u8>> for KE2State<HashLen> {
}
}
impl<HashLen: ArrayLength<u8>> ToBytes for KE2Message<HashLen> {
impl<HashLen: ArrayLength<u8>, KeyFormat: KeyPair> ToBytes for KE2Message<HashLen, KeyFormat> {
fn to_bytes(&self) -> Vec<u8> {
let output: Vec<u8> = [
&self.server_nonce[..],
@@ -333,7 +335,9 @@ impl<HashLen: ArrayLength<u8>> ToBytes for KE2Message<HashLen> {
}
}
impl<HashLen: ArrayLength<u8>> TryFrom<Vec<u8>> for KE2Message<HashLen> {
impl<HashLen: ArrayLength<u8>, KeyFormat: KeyPair> TryFrom<Vec<u8>>
for KE2Message<HashLen, KeyFormat>
{
type Error = ProtocolError;
fn try_from(ke2_message_bytes: Vec<u8>) -> Result<Self, Self::Error> {
@@ -342,20 +346,22 @@ impl<HashLen: ArrayLength<u8>> TryFrom<Vec<u8>> for KE2Message<HashLen> {
Ok(Self {
server_nonce: GenericArray::clone_from_slice(&checked_bytes[..NONCE_LEN]),
server_e_pk: Key::from_bytes(&checked_bytes[NONCE_LEN..NONCE_LEN + KEY_LEN])?,
server_e_pk: KeyFormat::Repr::from_bytes(
&checked_bytes[NONCE_LEN..NONCE_LEN + KEY_LEN],
)?,
mac: GenericArray::clone_from_slice(&checked_bytes[NONCE_LEN + KEY_LEN..]),
})
}
}
// The triple of public and private components used in the 3DH computation
struct TripleDHComponents {
pk1: Key,
sk1: Key,
pk2: Key,
sk2: Key,
pk3: Key,
sk3: Key,
struct TripleDHComponents<KeyFormat: KeyPair> {
pk1: KeyFormat::Repr,
sk1: KeyFormat::Repr,
pk2: KeyFormat::Repr,
sk2: KeyFormat::Repr,
pk3: KeyFormat::Repr,
sk3: KeyFormat::Repr,
}
// Consists of a shared secret, followed by two mac keys
@@ -367,8 +373,8 @@ type TripleDHDerivationResult<D> = (
// Internal function which takes the public and private components of the client and server keypairs, along
// with some auxiliary metadata, to produce the shared secret and two MAC keys
fn derive_3dh_keys<KeyFormat: KeyPair<Repr = Key>, D: Hash>(
dh: TripleDHComponents,
fn derive_3dh_keys<KeyFormat: KeyPair, D: Hash>(
dh: TripleDHComponents<KeyFormat>,
client_nonce: &GenericArray<u8, NonceLen>,
server_nonce: &GenericArray<u8, NonceLen>,
client_s_pk: KeyFormat::Repr,