From 18b3c7c1e4990524b6670c0717e57d7680284603 Mon Sep 17 00:00:00 2001 From: Isabelle L Date: Thu, 14 May 2020 20:42:02 -0500 Subject: [PATCH] added CRC32 checksum and a justfile --- Cargo.toml | 1 + README.md | 14 +++++---- justfile | 4 +++ src/lib.rs | 77 +++++++++++++++++++++++++++++++++++--------------- src/message.rs | 4 +-- 5 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 justfile diff --git a/Cargo.toml b/Cargo.toml index 5ffc9a1..604fa8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ chrono = "0.4.11" ring = "0.16.13" anyhow = "1.0.30" thiserror = "1.0.17" +crc32fast = "1.2.0" diff --git a/README.md b/README.md index b1628d2..3771e83 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,11 @@ I don't know whether or not this is a super practical way of doing things but i'm lazy and it seems to work so gonna roll with it lol -| segment size | usage | -|--------------|-------------------------------------| -| 1 byte | u8 signifies the type of packet | -| 8 byte | u64 length of the packet contents | -| 32 byte | SHA256 packet contents checksum | -| `u64::MAX` | packet contents | \ No newline at end of file +| segment size | usage | +|--------------|--------------------------------------------| +| 1 byte | u8 signifies the type of packet | +| 8 byte | u64 length of the packet contents | +| 4 byte | CRC32 packet contents checksum | +| 32 byte | SHA256 packet contents integrity check | +| `u64::MAX` | packet contents | + diff --git a/justfile b/justfile new file mode 100644 index 0000000..a7b3827 --- /dev/null +++ b/justfile @@ -0,0 +1,4 @@ +alias b := build + +build: + cargo build \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 23a2ce2..316f8f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,12 +5,13 @@ //! I don't know whether or not this is a super practical way of doing things //! but i'm lazy and it seems to work so gonna roll with it lol //! -//! | segment size | usage | -//! |--------------|-------------------------------------| -//! | 1 byte | u8 signifies the type of packet | -//! | 8 byte | u64 length of the packet contents | -//! | 32 byte | SHA256 packet contents checksum | -//! | `u64::MAX` | packet contents | +//! | segment size | usage | +//! |--------------|--------------------------------------------| +//! | 1 byte | u8 signifies the type of packet | +//! | 8 byte | u64 length of the packet contents | +//! | 4 byte | CRC32 packet contents checksum | +//! | 32 byte | SHA256 packet contents integrity check | +//! | `u64::MAX` | packet contents | //! use futures_util::io::{AsyncReadExt, AsyncWriteExt}; @@ -35,21 +36,33 @@ pub trait Sendable: Sized { /// data to be sent pub struct Packet { kind: PacketKind, - checksum: Vec, + integrity_hash: Vec, contents: Vec, } impl Packet { /// create a new `Packet` pub fn new(kind: PacketKind, contents: Vec) -> Packet { - let checksum = digest::digest(&digest::SHA256, &contents).as_ref().to_vec(); + let integrity_hash = digest::digest(&digest::SHA256, &contents).as_ref().to_vec(); Packet { kind, - checksum, + integrity_hash, contents, } } + // generate a checksum from the packet + fn generate_checksum(&self) -> u32 { + // combine integrity hash and contents + let mut hash_and_contents = self.integrity_hash.clone(); + hash_and_contents.extend_from_slice(&self.contents); + + // generate checksum + let mut hasher = crc32fast::Hasher::new(); + hasher.update(hash_and_contents.as_ref()); + hasher.finalize() + } + fn to_network_packet(&self) -> NetworkPacket { let mut contents: Vec = Vec::new(); @@ -61,29 +74,43 @@ impl Packet { contents.extend_from_slice(&contents_length.to_le_bytes()); // write checksum - contents.extend_from_slice(&self.checksum.as_ref()); + let checksum = self.generate_checksum(); + contents.extend_from_slice(&checksum.to_le_bytes()); - // write contents + // write hash and contents + contents.extend_from_slice(&self.integrity_hash); contents.extend_from_slice(&self.contents); NetworkPacket(contents) } - /// verifies SHA256 checksum + /// verifies SHA256 integrity pub fn verify_integrity(&self) -> Result<()> { - let found = digest::digest(&digest::SHA256, &self.contents) + let expected = digest::digest(&digest::SHA256, &self.contents) .as_ref() .to_vec(); - if found == self.checksum { + + if expected == self.integrity_hash { Ok(()) } else { - Err(IlmpError::BadChecksumIntegrity { - expected: self.checksum.clone(), - found, + Err(IlmpError::BadHashIntegrity { + found: self.integrity_hash.clone(), + expected, } .into()) } } + + /// verifies CRC32 checksum + pub fn verify_checksum(&self, expected: u32) -> Result<()> { + let found = self.generate_checksum(); + + if found == expected { + Ok(()) + } else { + Err(IlmpError::BadChecksumIntegrity { expected, found }) + } + } } /// kinds of packets that can be sent @@ -108,7 +135,9 @@ impl PacketKind { #[derive(Error, Debug)] pub enum IlmpError { #[error("checksum integrity check failed: (expected {expected:?} found {found:?})")] - BadChecksumIntegrity { expected: Vec, found: Vec }, + BadChecksumIntegrity { expected: u32, found: u32 }, + #[error("hash integrity check failed: (expected {expected:?} found {found:?})")] + BadHashIntegrity { expected: Vec, found: Vec }, #[error("std::io error")] // external error conversions StdIo(#[from] std::io::Error), @@ -125,17 +154,18 @@ pub async fn read(stream: &mut S) -> Result> where S: AsyncReadExt + Unpin, { - let mut info_buf = [0u8; 9]; + let mut info_buf = [0u8; 13]; let check = stream.read(&mut info_buf).await?; if check == 0 { return Ok(None); } let kind = PacketKind::from_u8(info_buf[0]).unwrap(); - let length = u32::from_le_bytes(info_buf[1..9].try_into().unwrap()) as usize; + let length = u64::from_le_bytes(info_buf[1..9].try_into().unwrap()) as usize; + let checksum = u32::from_le_bytes(info_buf[10..14].try_into().unwrap()); - let mut checksum: Vec = vec![0; 32]; - stream.read(&mut checksum).await?; + let mut integrity_hash: Vec = vec![0; 32]; + stream.read(&mut integrity_hash).await?; let mut contents: Vec = vec![0; length]; stream.read(&mut contents).await?; @@ -143,9 +173,10 @@ where let packet = Packet { kind, contents, - checksum, + integrity_hash, }; packet.verify_integrity()?; + packet.verify_checksum(checksum)?; Ok(Some(packet)) } diff --git a/src/message.rs b/src/message.rs index 082055a..57c2b1e 100644 --- a/src/message.rs +++ b/src/message.rs @@ -31,12 +31,12 @@ impl Message { impl crate::Sendable for Message { fn to_packet(&self) -> Result { let contents: Vec = serde_json::to_string(&self)?.into_bytes(); - let checksum = digest::digest(&digest::SHA256, &contents).as_ref().to_vec(); + let integrity_hash = digest::digest(&digest::SHA256, &contents).as_ref().to_vec(); let kind = PacketKind::Message; Ok(Packet { kind, - checksum, + integrity_hash, contents, }) }