diff --git a/src/agreement.rs b/src/agreement.rs index 817f2c2..508923e 100644 --- a/src/agreement.rs +++ b/src/agreement.rs @@ -1,8 +1,11 @@ +// namespacing use crate::{Packet, PacketKind, Result}; use chrono::prelude::*; use serde::{Deserialize, Serialize}; use uuid::Uuid; +/// packet to be used when server/client are coming to an agreement on +/// encryption key material #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Agreement { pub timestamp: i64, @@ -11,10 +14,15 @@ pub struct Agreement { } impl Agreement { + /// creates a new agreement packet from a public key pub fn new(public_key: Vec) -> Agreement { let timestamp = Utc::now().timestamp(); let message_id = Uuid::new_v4().as_u128(); - Agreement { timestamp, message_id, public_key } + Agreement { + timestamp, + message_id, + public_key, + } } } diff --git a/src/encrypt.rs b/src/encrypt.rs index d5b6555..5b4889a 100644 --- a/src/encrypt.rs +++ b/src/encrypt.rs @@ -1,13 +1,20 @@ +// namespacing use crate::Packet; use crate::Result; use orion::aead::{self, SecretKey}; +use ring::digest; /// trait that allows for me to be lazy pub trait Encryption { + /// return the encryption kind fn kind(&self) -> EncryptKind; + /// returns Option fn key(&self) -> Option<&SecretKey>; - fn encrypt(&self, packet: Packet) -> Packet; - fn decrypt(&self, packet: Packet) -> Packet; + /// encrypts the packet contents and updates the integrity hash + fn encrypt(&self, packet: &mut Packet) -> Result<()>; + /// decrypts the packet contents, should only be used after integrity is + /// validated + fn decrypt(&self, packet: &mut Packet) -> Result<()>; } /// uses ring's aead module @@ -22,20 +29,27 @@ impl Encryption for SymmetricEncrypt { Some(&self.0) } - fn encrypt(&self, _packet: Packet) -> Packet { - todo!() + fn encrypt(&self, packet: &mut Packet) -> Result<()> { + packet.contents = aead::seal(self.key().unwrap(), &packet.contents)?; + packet.integrity_hash = digest::digest(&digest::SHA256, &packet.contents) + .as_ref() + .to_vec(); + Ok(()) } - fn decrypt(&self, _packet: Packet) -> Packet { - todo!() + fn decrypt(&self, packet: &mut Packet) -> Result<()> { + packet.contents = aead::open(self.key().unwrap(), &packet.contents)?; + Ok(()) } } impl SymmetricEncrypt { + /// creates a new symmetric encryption key wrapper struct pub fn new(key: SecretKey) -> SymmetricEncrypt { SymmetricEncrypt(key) } + #[doc(hidden)] /// dear future izzy, this is a really bad idea pub fn clone(&self) -> Result { Ok(SymmetricEncrypt::new(aead::SecretKey::from_slice( @@ -47,6 +61,13 @@ impl SymmetricEncrypt { /// literally not encryption whatsoever pub struct NoEncrypt; +impl NoEncrypt { + /// why + pub fn new() -> NoEncrypt { + NoEncrypt + } +} + impl Encryption for NoEncrypt { fn kind(&self) -> EncryptKind { EncryptKind::None @@ -58,19 +79,13 @@ impl Encryption for NoEncrypt { } // lol - fn encrypt(&self, packet: Packet) -> Packet { - packet + fn encrypt(&self, _packet: &mut Packet) -> Result<()> { + Ok(()) } // lol - fn decrypt(&self, packet: Packet) -> Packet { - packet - } -} - -impl NoEncrypt { - pub fn new() -> NoEncrypt { - NoEncrypt + fn decrypt(&self, _packet: &mut Packet) -> Result<()> { + Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 47feba5..beee67f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ //! | `u64::MAX` | packet contents | //! +// modules mod message; pub use message::Message; mod agreement; @@ -22,16 +23,18 @@ pub use agreement::Agreement; /// encryption types and functions pub mod encrypt; +// namespacing use encrypt::{EncryptKind, Encryption}; use futures_util::io::{AsyncReadExt, AsyncWriteExt}; -use orion::aead; use ring::digest; use std::convert::TryInto; use std::marker::Unpin; use thiserror::Error; +/// simple result pub type Result = std::result::Result; +// packet that should be streamable struct NetworkPacket(Vec); /// a type of data that can be sent @@ -73,6 +76,7 @@ impl Packet { hasher.finalize() } + // converts a to a network packet to be streamed fn to_network_packet(&self) -> NetworkPacket { let mut contents: Vec = Vec::new(); @@ -168,15 +172,17 @@ pub enum IlmpError { /// reads a `Packet` from a stream /// /// if `Ok(None)` is returned the stream has been disconnected. -pub async fn read(stream: &mut S) -> Result> +pub async fn read(stream: &mut S, encryption: &E) -> Result> where S: AsyncReadExt + Unpin, + E: Encryption, { let mut info_buf = [0u8; 14]; let check = stream.read(&mut info_buf).await?; if check == 0 { return Ok(None); } + print!("reading packet... "); let kind = PacketKind::from_u8(info_buf[0]).unwrap(); let encrypt_kind = EncryptKind::from_u8(info_buf[1]).unwrap(); @@ -189,7 +195,7 @@ where let mut contents: Vec = vec![0; length]; stream.read(&mut contents).await?; - let packet = Packet { + let mut packet = Packet { kind, contents, integrity_hash, @@ -199,6 +205,10 @@ where packet.verify_checksum(checksum)?; packet.verify_integrity()?; + if packet.encrypt_kind == EncryptKind::Symmetric { + encryption.decrypt(&mut packet)?; + } + println!("[ Ok ]"); Ok(Some(packet)) } @@ -209,20 +219,20 @@ where P: Sendable, E: Encryption, { + print!("sending packet... "); match encryption.kind() { EncryptKind::None => { let network_packet = packet.to_packet(encryption.kind())?.to_network_packet(); stream.write(&network_packet.0).await?; + println!("[ Ok ]"); Ok(()) } EncryptKind::Symmetric => { let mut packet = packet.to_packet(encryption.kind())?; - packet.contents = aead::seal(encryption.key().unwrap(), &packet.contents)?; - packet.integrity_hash = digest::digest(&digest::SHA256, &packet.contents) - .as_ref() - .to_vec(); + encryption.encrypt(&mut packet)?; let network_packet = packet.to_network_packet(); stream.write(&network_packet.0).await?; + println!("[ Ok ]"); Ok(()) } }