Isabelle's Lazy Message Protocol
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

283 satır
7.8 KiB

  1. //! # Isabelle's Lazy Message Protocol
  2. //!
  3. //! ### network packet protocol
  4. //!
  5. //! I don't know whether or not this is a super practical way of doing things
  6. //! but i'm lazy and it seems to work so gonna roll with it lol
  7. //!
  8. //! | segment size | usage |
  9. //! |--------------|--------------------------------------------|
  10. //! | 1 byte | u8 packet kind |
  11. //! | 1 byte | u8 encrypt kind |
  12. //! | 8 byte | u64 length of the packet contents |
  13. //! | 4 byte | CRC32 packet contents checksum |
  14. //! | 32 byte | SHA256 packet contents integrity check |
  15. //! | `u64::MAX` | packet contents |
  16. //!
  17. mod message;
  18. pub use message::Message;
  19. mod asymmetric_key;
  20. pub use asymmetric_key::AsymmetricKey;
  21. use futures_util::io::{AsyncReadExt, AsyncWriteExt};
  22. use ring::{rand, signature::{self, KeyPair},digest};
  23. use std::convert::TryInto;
  24. use std::marker::Unpin;
  25. use thiserror::Error;
  26. pub type Result<T> = std::result::Result<T, IlmpError>;
  27. struct NetworkPacket(Vec<u8>);
  28. /// a type of data that can be sent
  29. pub trait Sendable: Sized {
  30. fn to_packet(&self, encrypt_kind: EncryptKind) -> Result<Packet>;
  31. fn from_packet(packet: Packet) -> Result<Self>;
  32. }
  33. /// data to be sent
  34. pub struct Packet {
  35. pub kind: PacketKind,
  36. pub encrypt_kind: EncryptKind,
  37. integrity_hash: Vec<u8>,
  38. contents: Vec<u8>,
  39. }
  40. impl Packet {
  41. /// create a new `Packet`
  42. pub fn new(kind: PacketKind, contents: Vec<u8>, encrypt_kind: EncryptKind) -> Packet {
  43. let integrity_hash = digest::digest(&digest::SHA256, &contents).as_ref().to_vec();
  44. Packet { kind, integrity_hash, contents, encrypt_kind }
  45. }
  46. // generate a checksum from the packet
  47. fn generate_checksum(&self) -> u32 {
  48. // combine integrity hash and contents
  49. let mut hash_and_contents = self.integrity_hash.clone();
  50. hash_and_contents.extend_from_slice(&self.contents);
  51. // generate checksum
  52. let mut hasher = crc32fast::Hasher::new();
  53. hasher.update(hash_and_contents.as_ref());
  54. hasher.finalize()
  55. }
  56. fn to_network_packet(&self) -> NetworkPacket {
  57. let mut contents: Vec<u8> = Vec::new();
  58. // write packet kind byte
  59. contents.push(self.kind as u8);
  60. // write encrypt kind byte
  61. contents.push(self.encrypt_kind as u8);
  62. // write the packet length
  63. let contents_length = self.contents.len() as u64;
  64. contents.extend_from_slice(&contents_length.to_le_bytes());
  65. // write checksum
  66. let checksum = self.generate_checksum();
  67. contents.extend_from_slice(&checksum.to_le_bytes());
  68. // write hash and contents
  69. contents.extend_from_slice(&self.integrity_hash);
  70. contents.extend_from_slice(&self.contents);
  71. NetworkPacket(contents)
  72. }
  73. /// verifies SHA256 integrity
  74. pub fn verify_integrity(&self) -> Result<()> {
  75. let expected = digest::digest(&digest::SHA256, &self.contents).as_ref().to_vec();
  76. if expected == self.integrity_hash {
  77. Ok(())
  78. } else {
  79. println!("bad integrity");
  80. Err(IlmpError::BadHashIntegrity { found: self.integrity_hash.clone(), expected }.into())
  81. }
  82. }
  83. /// verifies CRC32 checksum
  84. pub fn verify_checksum(&self, expected: u32) -> Result<()> {
  85. let found = self.generate_checksum();
  86. if found == expected {
  87. Ok(())
  88. } else {
  89. println!("bad checksum");
  90. Err(IlmpError::BadChecksumIntegrity { expected, found })
  91. }
  92. }
  93. }
  94. /// kinds of packets that can be sent
  95. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  96. #[repr(u8)]
  97. pub enum PacketKind {
  98. Message = 0x00,
  99. AsymmetricKey = 0xff,
  100. }
  101. impl PacketKind {
  102. /// returns `Option<PacketKind> given valid matching variant
  103. pub fn from_u8(kind: u8) -> Option<PacketKind> {
  104. match kind {
  105. 0x00 => Some(PacketKind::Message),
  106. 0xff => Some(PacketKind::AsymmetricKey),
  107. _ => None,
  108. }
  109. }
  110. }
  111. pub trait Encryption {
  112. fn kind(&self) -> EncryptKind;
  113. fn key(&self) -> Option<Vec<u8>>;
  114. }
  115. pub struct AsymmetricEncrypt(Vec<u8>);
  116. impl Encryption for AsymmetricEncrypt {
  117. fn kind(&self) -> EncryptKind {
  118. EncryptKind::Asymmetric
  119. }
  120. fn key(&self) -> Option<Vec<u8>> {
  121. Some(self.0.clone())
  122. }
  123. }
  124. impl AsymmetricEncrypt {
  125. pub fn new(key: Vec<u8>) -> AsymmetricEncrypt {
  126. AsymmetricEncrypt(key)
  127. }
  128. }
  129. pub struct SymmetricEncrypt(Vec<u8>);
  130. impl Encryption for SymmetricEncrypt {
  131. fn kind(&self) -> EncryptKind {
  132. EncryptKind::Symmetric
  133. }
  134. fn key(&self) -> Option<Vec<u8>> {
  135. Some(self.0.clone())
  136. }
  137. }
  138. impl SymmetricEncrypt {
  139. pub fn new(key: Vec<u8>) -> SymmetricEncrypt {
  140. SymmetricEncrypt(key)
  141. }
  142. }
  143. pub struct NoEncrypt;
  144. impl Encryption for NoEncrypt {
  145. fn kind(&self) -> EncryptKind {
  146. EncryptKind::None
  147. }
  148. fn key(&self) -> Option<Vec<u8>> {
  149. None
  150. }
  151. }
  152. impl NoEncrypt {
  153. pub fn new() -> NoEncrypt {
  154. NoEncrypt
  155. }
  156. }
  157. /// encryption kind
  158. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  159. #[repr(u8)]
  160. pub enum EncryptKind {
  161. None = 0x00,
  162. Asymmetric = 0x80,
  163. Symmetric = 0xff,
  164. }
  165. impl EncryptKind {
  166. /// returns `EncryptKind` from u8 if returned value is valid
  167. pub fn from_u8(kind: u8) -> Option<EncryptKind> {
  168. match kind {
  169. 0x00 => Some(EncryptKind::None),
  170. 0x80 => Some(EncryptKind::Asymmetric),
  171. 0xff => Some(EncryptKind::Symmetric),
  172. _ => None,
  173. }
  174. }
  175. }
  176. /// ilmp's error type
  177. #[derive(Error, Debug)]
  178. pub enum IlmpError {
  179. #[error("checksum integrity check failed: (expected {expected:?} found {found:?})")]
  180. BadChecksumIntegrity { expected: u32, found: u32 },
  181. #[error("hash integrity check failed: (expected {expected:?} found {found:?})")]
  182. BadHashIntegrity { expected: Vec<u8>, found: Vec<u8> },
  183. // external error conversions
  184. #[error("std::io error")]
  185. StdIo(#[from] std::io::Error),
  186. #[error("serde_json error")]
  187. SerdeJson(#[from] serde_json::error::Error),
  188. #[error("string parsing error")]
  189. StringParse(#[from] std::string::FromUtf8Error),
  190. }
  191. /// reads a `Packet` from a stream
  192. ///
  193. /// if `Ok(None)` is returned the stream has been disconnected.
  194. pub async fn read<S>(stream: &mut S) -> Result<Option<Packet>>
  195. where
  196. S: AsyncReadExt + Unpin,
  197. {
  198. let mut info_buf = [0u8; 14];
  199. let check = stream.read(&mut info_buf).await?;
  200. if check == 0 {
  201. return Ok(None);
  202. }
  203. let kind = PacketKind::from_u8(info_buf[0]).unwrap();
  204. let encrypt_kind = EncryptKind::from_u8(info_buf[1]).unwrap();
  205. let length = u64::from_le_bytes(info_buf[2..10].try_into().unwrap()) as usize;
  206. let checksum = u32::from_le_bytes(info_buf[10..14].try_into().unwrap());
  207. let mut integrity_hash: Vec<u8> = vec![0; 32];
  208. stream.read(&mut integrity_hash).await?;
  209. let mut contents: Vec<u8> = vec![0; length];
  210. stream.read(&mut contents).await?;
  211. let packet = Packet { kind, contents, integrity_hash, encrypt_kind };
  212. packet.verify_checksum(checksum)?;
  213. packet.verify_integrity()?;
  214. Ok(Some(packet))
  215. }
  216. /// writes a `Sendable` packet to a stream
  217. pub async fn write<S, P, E>(stream: &mut S, packet: P, encryption: E) -> Result<()>
  218. where
  219. S: AsyncWriteExt + Unpin,
  220. P: Sendable,
  221. E: Encryption,
  222. {
  223. match encryption.kind() {
  224. EncryptKind::None => {
  225. let network_packet = packet.to_packet(encryption.kind())?.to_network_packet();
  226. stream.write(&network_packet.0).await?;
  227. Ok(())
  228. }
  229. EncryptKind::Asymmetric => {
  230. let
  231. let mut packet = packet;
  232. packet.contents
  233. },
  234. EncryptKind::Symmetric => todo!(),
  235. }
  236. }