use std::num::NonZeroU64;
use hiss::curve::Curve;
use hiss::noise::HandshakeError;
use hiss::provider::{CryptoKeyProvider, DhProvider};
use crate::constants;
use crate::packet::Channel;
pub type PublicKeyFor<C> = <<C as Channel>::Curve as Curve>::PublicKey;
pub type PskFor<C> = <C as Handshake>::Psk;
pub trait Handshake: Channel {
type Initiator<P: DhProvider<Self::Curve>>;
type InitiatorSent<P: DhProvider<Self::Curve>>;
type Responder<P: DhProvider<Self::Curve>>;
type Msg1Intro<P: DhProvider<Self::Curve>>;
type ResponderRead<P: DhProvider<Self::Curve>>;
type Psk;
type Transport;
type Seal;
type Open;
fn initiator<P: DhProvider<Self::Curve>>(
provider: P,
prologue: &[u8],
remote_static: PublicKeyFor<Self>,
) -> Self::Initiator<P>;
fn write_msg1<P: DhProvider<Self::Curve>>(
state: Self::Initiator<P>,
static_key: <P as CryptoKeyProvider<Self::Curve>>::PrivateKey,
psk: &Self::Psk,
payload: &[u8; constants::MSG1_PAYLOAD_LEN],
) -> Result<(Vec<u8>, Self::InitiatorSent<P>), HandshakeError>;
fn read_msg2<P: DhProvider<Self::Curve>>(
state: Self::InitiatorSent<P>,
msg2: &[u8],
) -> Result<Self::Transport, HandshakeError>;
fn responder<P: DhProvider<Self::Curve>>(
provider: P,
prologue: &[u8],
static_key: <P as CryptoKeyProvider<Self::Curve>>::PrivateKey,
) -> Result<Self::Responder<P>, HandshakeError>;
fn read_msg1_intro<P: DhProvider<Self::Curve>>(
state: Self::Responder<P>,
msg1: &[u8],
) -> Result<(PublicKeyFor<Self>, Self::Msg1Intro<P>), HandshakeError>;
fn complete<P: DhProvider<Self::Curve>>(
mid: Self::Msg1Intro<P>,
psk: &Self::Psk,
) -> Result<([u8; constants::MSG1_PAYLOAD_LEN], Self::ResponderRead<P>), HandshakeError>;
fn write_msg2<P: DhProvider<Self::Curve>>(
state: Self::ResponderRead<P>,
) -> Result<(Vec<u8>, Self::Transport), HandshakeError>;
fn into_datagram(
transport: Self::Transport,
epoch_size: NonZeroU64,
) -> (Self::Seal, Self::Open);
fn next_counter(seal: &Self::Seal) -> u64;
fn session_id(seal: &Self::Seal) -> &::hiss::noise::SessionId;
fn seal(
seal: &mut Self::Seal,
ad: &[u8],
plaintext: &[u8],
out: &mut [u8],
) -> Result<(u64, usize), HandshakeError>;
fn open(
open: &mut Self::Open,
counter: u64,
ad: &[u8],
ciphertext: &[u8],
out: &mut [u8],
) -> Result<usize, HandshakeError>;
}