base64 encode payloads (allows the use of msg delimiters)

This commit is contained in:
17ms 2023-03-29 20:20:47 +03:00
parent e5b038dc91
commit 3c3cb50c86
2 changed files with 61 additions and 17 deletions

43
src/comms.rs Normal file → Executable file
View File

@ -1,5 +1,6 @@
use crate::crypto; use crate::crypto;
use aes_gcm::{aead::consts::U12, aes::Aes256, AesGcm}; use aes_gcm::{aead::consts::U12, aes::Aes256, AesGcm};
use base64::{engine::general_purpose, Engine};
use rand::rngs::OsRng; use rand::rngs::OsRng;
use std::error::Error; use std::error::Error;
use tokio::{ use tokio::{
@ -7,29 +8,49 @@ use tokio::{
net::tcp::{ReadHalf, WriteHalf}, net::tcp::{ReadHalf, WriteHalf},
}; };
pub async fn send_bytes( pub async fn send(
writer: &mut BufWriter<WriteHalf<'_>>, writer: &mut BufWriter<WriteHalf<'_>>,
enc: Option<(&mut AesGcm<Aes256, U12>, &mut OsRng)>, cipher: Option<&mut AesGcm<Aes256, U12>>,
rng: Option<&mut OsRng>,
data: &Vec<u8>, data: &Vec<u8>,
) -> Result<(), Box<dyn Error + Send + Sync>> { ) -> Result<(), Box<dyn Error + Send + Sync>> {
let data = enc.map_or(Ok(data.clone()), |enc| { let enc: Vec<u8>;
crypto::aes_encrypt(data, enc.0, enc.1) if let (Some(cipher), Some(rng)) = (cipher, rng) {
})?; enc = crypto::aes_encrypt(data, cipher, rng)?;
writer.write_all(&data).await?; } else {
enc = data.clone();
}
let mut encoded = general_purpose::STANDARD_NO_PAD
.encode(enc)
.as_bytes()
.to_vec();
encoded.push(b':');
writer.write_all(&encoded).await?;
writer.flush().await?; writer.flush().await?;
Ok(()) Ok(())
} }
pub async fn recv_bytes( pub async fn recv(
reader: &mut BufReader<ReadHalf<'_>>, reader: &mut BufReader<ReadHalf<'_>>,
cipher: Option<&mut AesGcm<Aes256, U12>>, cipher: Option<&mut AesGcm<Aes256, U12>>,
buf: &mut Vec<u8>, buf: &mut Vec<u8>,
) -> Result<(), Box<dyn Error + Send + Sync>> { ) -> Result<(), Box<dyn Error + Send + Sync>> {
let recv_bytes = reader.read_until(b'\n', buf).await?; let n = reader.read_until(b':', buf).await?;
*buf = cipher.map_or(Ok(buf.clone()), |c| crypto::aes_decrypt(&buf, c))?;
if recv_bytes == 0 { if n == 0 {
todo!("ERROR: No message received or client <xyz> crashed"); todo!("error: connection closed unexpectedly");
}
buf.pop();
*buf = general_purpose::STANDARD_NO_PAD.decode(&buf)?.to_vec();
if let Some(cipher) = cipher {
*buf = crypto::aes_decrypt(&buf, cipher)?;
} else {
*buf = buf.clone();
} }
Ok(()) Ok(())

35
src/crypto.rs Normal file → Executable file
View File

@ -13,6 +13,7 @@ use tokio::{
use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret}; use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret};
const AES_NONCE_SIZE: usize = 12; const AES_NONCE_SIZE: usize = 12;
const DH_PBK_SIZE: usize = 32;
pub async fn edh( pub async fn edh(
reader: &mut BufReader<ReadHalf<'_>>, reader: &mut BufReader<ReadHalf<'_>>,
@ -22,18 +23,19 @@ pub async fn edh(
) -> Result<SharedSecret, Box<dyn Error + Send + Sync>> { ) -> Result<SharedSecret, Box<dyn Error + Send + Sync>> {
let own_sec = EphemeralSecret::new(OsRng); let own_sec = EphemeralSecret::new(OsRng);
let own_pbk = PublicKey::from(&own_sec); let own_pbk = PublicKey::from(&own_sec);
let msg = own_pbk.as_bytes().to_vec();
if go_first { if go_first {
comms::send_bytes(writer, None, &own_pbk.as_bytes().to_vec()).await?; comms::send(writer, None, None, &msg).await?;
comms::recv_bytes(reader, None, buf).await?; comms::recv(reader, None, buf).await?;
} else { } else {
comms::recv_bytes(reader, None, buf).await?; comms::recv(reader, None, buf).await?;
comms::send_bytes(writer, None, &own_pbk.as_bytes().to_vec()).await?; comms::send(writer, None, None, &msg).await?;
} }
let sliced_buf: [u8; 32] = buf[..32].try_into()?; let slice: [u8; DH_PBK_SIZE] = buf[..DH_PBK_SIZE].try_into()?;
let recv_pbk = PublicKey::from(sliced_buf);
buf.clear(); buf.clear();
let recv_pbk = PublicKey::from(slice);
Ok(own_sec.diffie_hellman(&recv_pbk)) Ok(own_sec.diffie_hellman(&recv_pbk))
} }
@ -75,3 +77,24 @@ pub fn aes_decrypt(
Ok(decrypted) Ok(decrypted)
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_aes() {
use aes_gcm::aead;
let mut gen_rng = aead::OsRng;
let key = Aes256Gcm::generate_key(&mut gen_rng);
let mut cipher = Aes256Gcm::new(&key);
let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let mut aes_rng = OsRng;
let enc = aes_encrypt(&data, &mut cipher, &mut aes_rng).unwrap();
let dec = aes_decrypt(&enc, &mut cipher).unwrap();
assert_eq!(data, dec);
}
}