Make KeyExchange generic in KeyFormat
This commit is contained in:
@@ -6,13 +6,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{InternalPakeError, ProtocolError},
|
errors::{InternalPakeError, ProtocolError},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
keypair::{Key, KeyPair},
|
keypair::KeyPair,
|
||||||
};
|
};
|
||||||
use rand_core::{CryptoRng, RngCore};
|
use rand_core::{CryptoRng, RngCore};
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
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 KE1State: TryFrom<Vec<u8>, Error = InternalPakeError> + ToBytes;
|
||||||
type KE2State: TryFrom<Vec<u8>, Error = ProtocolError> + ToBytes;
|
type KE2State: TryFrom<Vec<u8>, Error = ProtocolError> + ToBytes;
|
||||||
type KE1Message: TryFrom<Vec<u8>, Error = InternalPakeError> + ToBytes;
|
type KE1Message: TryFrom<Vec<u8>, Error = InternalPakeError> + ToBytes;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError},
|
errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
key_exchange::traits::{KeyExchange, ToBytes},
|
key_exchange::traits::{KeyExchange, ToBytes},
|
||||||
keypair::{Key, KeyPair, SizedBytes},
|
keypair::{KeyPair, SizedBytes},
|
||||||
};
|
};
|
||||||
use digest::{Digest, FixedOutput};
|
use digest::{Digest, FixedOutput};
|
||||||
use generic_array::{
|
use generic_array::{
|
||||||
@@ -31,11 +31,11 @@ static STR_3DH: &[u8] = b"3DH keys";
|
|||||||
/// The Triple Diffie-Hellman key exchange implementation
|
/// The Triple Diffie-Hellman key exchange implementation
|
||||||
pub struct TripleDH;
|
pub struct TripleDH;
|
||||||
|
|
||||||
impl<D: Hash, KeyFormat: KeyPair<Repr = Key>> KeyExchange<D, KeyFormat> for TripleDH {
|
impl<D: Hash, KeyFormat: KeyPair> KeyExchange<D, KeyFormat> for TripleDH {
|
||||||
type KE1State = KE1State<<D as FixedOutput>::OutputSize>;
|
type KE1State = KE1State<<D as FixedOutput>::OutputSize, KeyFormat>;
|
||||||
type KE2State = KE2State<<D as FixedOutput>::OutputSize>;
|
type KE2State = KE2State<<D as FixedOutput>::OutputSize>;
|
||||||
type KE1Message = KE1Message;
|
type KE1Message = KE1Message<KeyFormat>;
|
||||||
type KE2Message = KE2Message<<D as FixedOutput>::OutputSize>;
|
type KE2Message = KE2Message<<D as FixedOutput>::OutputSize, KeyFormat>;
|
||||||
type KE3Message = KE3Message<<D as FixedOutput>::OutputSize>;
|
type KE3Message = KE3Message<<D as FixedOutput>::OutputSize>;
|
||||||
|
|
||||||
fn generate_ke1<R: RngCore + CryptoRng>(
|
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[..],
|
&ke1_state.hashed_l1[..],
|
||||||
&l2_component[..],
|
&l2_component[..],
|
||||||
&ke2_message.server_nonce[..],
|
&ke2_message.server_nonce[..],
|
||||||
&ke2_message.server_e_pk[..],
|
&ke2_message.server_e_pk.to_arr(),
|
||||||
]
|
]
|
||||||
.concat();
|
.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
|
/// The client state produced after the first key exchange message
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub struct KE1State<HashLen: ArrayLength<u8>> {
|
pub struct KE1State<HashLen: ArrayLength<u8>, KeyFormat: KeyPair> {
|
||||||
client_e_sk: Key,
|
client_e_sk: KeyFormat::Repr,
|
||||||
client_nonce: GenericArray<u8, NonceLen>,
|
client_nonce: GenericArray<u8, NonceLen>,
|
||||||
hashed_l1: GenericArray<u8, HashLen>,
|
hashed_l1: GenericArray<u8, HashLen>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The first key exchange message
|
/// The first key exchange message
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub struct KE1Message {
|
pub struct KE1Message<KeyFormat: KeyPair> {
|
||||||
pub(crate) client_nonce: GenericArray<u8, NonceLen>,
|
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;
|
type Error = InternalPakeError;
|
||||||
|
|
||||||
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
|
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 {
|
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(
|
client_nonce: GenericArray::clone_from_slice(
|
||||||
&checked_bytes[KEY_LEN..KEY_LEN + NONCE_LEN],
|
&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> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
let output: Vec<u8> = [
|
let output: Vec<u8> = [
|
||||||
&self.client_e_sk.to_arr(),
|
&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> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
[&self.client_nonce[..], &self.client_e_pk.to_arr()].concat()
|
[&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;
|
type Error = InternalPakeError;
|
||||||
|
|
||||||
fn try_from(ke1_message_bytes: Vec<u8>) -> Result<Self, Self::Error> {
|
fn try_from(ke1_message_bytes: Vec<u8>) -> Result<Self, Self::Error> {
|
||||||
@@ -276,7 +278,7 @@ impl TryFrom<Vec<u8>> for KE1Message {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
client_nonce: GenericArray::clone_from_slice(&checked_bytes[..NONCE_LEN]),
|
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
|
/// 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_nonce: GenericArray<u8, NonceLen>,
|
||||||
server_e_pk: Key,
|
server_e_pk: KeyFormat::Repr,
|
||||||
mac: GenericArray<u8, HashLen>,
|
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> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
let output: Vec<u8> = [
|
let output: Vec<u8> = [
|
||||||
&self.server_nonce[..],
|
&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;
|
type Error = ProtocolError;
|
||||||
|
|
||||||
fn try_from(ke2_message_bytes: Vec<u8>) -> Result<Self, Self::Error> {
|
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 {
|
Ok(Self {
|
||||||
server_nonce: GenericArray::clone_from_slice(&checked_bytes[..NONCE_LEN]),
|
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..]),
|
mac: GenericArray::clone_from_slice(&checked_bytes[NONCE_LEN + KEY_LEN..]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
struct TripleDHComponents<KeyFormat: KeyPair> {
|
||||||
pk1: Key,
|
pk1: KeyFormat::Repr,
|
||||||
sk1: Key,
|
sk1: KeyFormat::Repr,
|
||||||
pk2: Key,
|
pk2: KeyFormat::Repr,
|
||||||
sk2: Key,
|
sk2: KeyFormat::Repr,
|
||||||
pk3: Key,
|
pk3: KeyFormat::Repr,
|
||||||
sk3: Key,
|
sk3: KeyFormat::Repr,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consists of a shared secret, followed by two mac keys
|
// 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
|
// 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
|
// with some auxiliary metadata, to produce the shared secret and two MAC keys
|
||||||
fn derive_3dh_keys<KeyFormat: KeyPair<Repr = Key>, D: Hash>(
|
fn derive_3dh_keys<KeyFormat: KeyPair, D: Hash>(
|
||||||
dh: TripleDHComponents,
|
dh: TripleDHComponents<KeyFormat>,
|
||||||
client_nonce: &GenericArray<u8, NonceLen>,
|
client_nonce: &GenericArray<u8, NonceLen>,
|
||||||
server_nonce: &GenericArray<u8, NonceLen>,
|
server_nonce: &GenericArray<u8, NonceLen>,
|
||||||
client_s_pk: KeyFormat::Repr,
|
client_s_pk: KeyFormat::Repr,
|
||||||
|
|||||||
Reference in New Issue
Block a user