浏览代码

added CRC32 checksum and a justfile

master
Isabelle L. 5 年前
父节点
当前提交
18b3c7c1e4
共有 5 个文件被更改,包括 69 次插入31 次删除
  1. +1
    -0
      Cargo.toml
  2. +8
    -6
      README.md
  3. +4
    -0
      justfile
  4. +54
    -23
      src/lib.rs
  5. +2
    -2
      src/message.rs

+ 1
- 0
Cargo.toml 查看文件

@@ -14,3 +14,4 @@ chrono = "0.4.11"
ring = "0.16.13" ring = "0.16.13"
anyhow = "1.0.30" anyhow = "1.0.30"
thiserror = "1.0.17" thiserror = "1.0.17"
crc32fast = "1.2.0"

+ 8
- 6
README.md 查看文件

@@ -5,9 +5,11 @@
I don't know whether or not this is a super practical way of doing things 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 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 |


+ 4
- 0
justfile 查看文件

@@ -0,0 +1,4 @@
alias b := build

build:
cargo build

+ 54
- 23
src/lib.rs 查看文件

@@ -5,12 +5,13 @@
//! I don't know whether or not this is a super practical way of doing things //! 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 //! 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}; use futures_util::io::{AsyncReadExt, AsyncWriteExt};
@@ -35,21 +36,33 @@ pub trait Sendable: Sized {
/// data to be sent /// data to be sent
pub struct Packet { pub struct Packet {
kind: PacketKind, kind: PacketKind,
checksum: Vec<u8>,
integrity_hash: Vec<u8>,
contents: Vec<u8>, contents: Vec<u8>,
} }


impl Packet { impl Packet {
/// create a new `Packet` /// create a new `Packet`
pub fn new(kind: PacketKind, contents: Vec<u8>) -> Packet { pub fn new(kind: PacketKind, contents: Vec<u8>) -> 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 { Packet {
kind, kind,
checksum,
integrity_hash,
contents, 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 { fn to_network_packet(&self) -> NetworkPacket {
let mut contents: Vec<u8> = Vec::new(); let mut contents: Vec<u8> = Vec::new();


@@ -61,29 +74,43 @@ impl Packet {
contents.extend_from_slice(&contents_length.to_le_bytes()); contents.extend_from_slice(&contents_length.to_le_bytes());


// write checksum // 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); contents.extend_from_slice(&self.contents);


NetworkPacket(contents) NetworkPacket(contents)
} }


/// verifies SHA256 checksum
/// verifies SHA256 integrity
pub fn verify_integrity(&self) -> Result<()> { pub fn verify_integrity(&self) -> Result<()> {
let found = digest::digest(&digest::SHA256, &self.contents)
let expected = digest::digest(&digest::SHA256, &self.contents)
.as_ref() .as_ref()
.to_vec(); .to_vec();
if found == self.checksum {

if expected == self.integrity_hash {
Ok(()) Ok(())
} else { } else {
Err(IlmpError::BadChecksumIntegrity {
expected: self.checksum.clone(),
found,
Err(IlmpError::BadHashIntegrity {
found: self.integrity_hash.clone(),
expected,
} }
.into()) .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 /// kinds of packets that can be sent
@@ -108,7 +135,9 @@ impl PacketKind {
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum IlmpError { pub enum IlmpError {
#[error("checksum integrity check failed: (expected {expected:?} found {found:?})")] #[error("checksum integrity check failed: (expected {expected:?} found {found:?})")]
BadChecksumIntegrity { expected: Vec<u8>, found: Vec<u8> },
BadChecksumIntegrity { expected: u32, found: u32 },
#[error("hash integrity check failed: (expected {expected:?} found {found:?})")]
BadHashIntegrity { expected: Vec<u8>, found: Vec<u8> },
#[error("std::io error")] #[error("std::io error")]
// external error conversions // external error conversions
StdIo(#[from] std::io::Error), StdIo(#[from] std::io::Error),
@@ -125,17 +154,18 @@ pub async fn read<S>(stream: &mut S) -> Result<Option<Packet>>
where where
S: AsyncReadExt + Unpin, S: AsyncReadExt + Unpin,
{ {
let mut info_buf = [0u8; 9];
let mut info_buf = [0u8; 13];
let check = stream.read(&mut info_buf).await?; let check = stream.read(&mut info_buf).await?;
if check == 0 { if check == 0 {
return Ok(None); return Ok(None);
} }


let kind = PacketKind::from_u8(info_buf[0]).unwrap(); 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<u8> = vec![0; 32];
stream.read(&mut checksum).await?;
let mut integrity_hash: Vec<u8> = vec![0; 32];
stream.read(&mut integrity_hash).await?;


let mut contents: Vec<u8> = vec![0; length]; let mut contents: Vec<u8> = vec![0; length];
stream.read(&mut contents).await?; stream.read(&mut contents).await?;
@@ -143,9 +173,10 @@ where
let packet = Packet { let packet = Packet {
kind, kind,
contents, contents,
checksum,
integrity_hash,
}; };
packet.verify_integrity()?; packet.verify_integrity()?;
packet.verify_checksum(checksum)?;


Ok(Some(packet)) Ok(Some(packet))
} }


+ 2
- 2
src/message.rs 查看文件

@@ -31,12 +31,12 @@ impl Message {
impl crate::Sendable for Message { impl crate::Sendable for Message {
fn to_packet(&self) -> Result<Packet> { fn to_packet(&self) -> Result<Packet> {
let contents: Vec<u8> = serde_json::to_string(&self)?.into_bytes(); let contents: Vec<u8> = 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; let kind = PacketKind::Message;


Ok(Packet { Ok(Packet {
kind, kind,
checksum,
integrity_hash,
contents, contents,
}) })
} }


正在加载...
取消
保存