PassiveHandshake

Struct PassiveHandshake 

Source
pub struct PassiveHandshake { /* private fields */ }
Expand description

Provides the passive part of the handshake.

The passive part of the handshake only really responds to the stuff the active part tells it. This includes the enabled features, which cannot be configured here but will be part of the setup sent from the active part. We’re currently expecting the other side to initialize a handshake, but this is technically not required. How you deal with that is up to you.

An example exchange could look like this:

let mut passive = PassiveHandshake::default();
// The active side will create an initialization, which will be sent to the passive side.
// We simply plug that information into our procedure. For now, we assume they're setting up
// encryption as well, so we simply `unwrap()` everything here.
let (value_key, value_b) = passive.initialize(init.encryption_seed).unwrap().unwrap();
// These two values should then be sent to the active side again. That side will then respond
// with a challenge for us, to verify everything went fine.
passive.finish(challenge).unwrap();
// We then need to complete the handshake, which we should signal to the active part as well.
// `finish` and `done` are separate things, because if the active part does not actually send
// encryption information we can't call `finish`. We'd instead just call `done`.
let encryption = passive.done().expect("Handshake should have completed.");

Implementations§

Source§

impl PassiveHandshake

Source

pub fn initialize( &mut self, init: Option<PassiveEncryptionInitializationData>, ) -> Result<Option<(u64, u32)>, SilkroadSecurityError>

Initialize the handshake with the data from the active side.

We have received the initialization data from the active handshake side and want to initialize our side as well. Depending on the security features selected by the active side, the initialization data may actually be None, which is why this accepts and Option. Technically, if you haven’t received any encryption initialization data, you can simply call PassiveHandshake::done and complete the handshake - there’s nothing more to be exchanged. This is essentially a convenience to stay more consistent with what we receive from the active part.

This may error if we’re already initialized, returning SilkroadSecurityError::InitializationUnfinished.

Source

pub fn finish(&mut self, challenge: u64) -> Result<(), SilkroadSecurityError>

Complete the handshake by verifying the challenge.

After we have sent our initialization data to the active part, they provide us with a sort of challenge. If we can verify the challenge with what we internally calculated, we know the key exchange was successful, and we now have a shared secret. At this point, the handshake is essentially completed. This should be signaled to the active side by switching to an encrypted channel.

Source

pub fn done(self) -> Result<Option<SilkroadEncryption>, SilkroadSecurityError>

Return the resulting encryption from the handshake.

If the selected security features of the active handshake part included setting up the encryption, the final result will be returned. If it didn’t contain that feature, it will return None instead.

Will return SilkroadSecurityError::InitializationUnfinished if we haven’t completed the handshake yet.

Trait Implementations§

Source§

impl Default for PassiveHandshake

Source§

fn default() -> PassiveHandshake

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V