base64 encode payloads (allows the use of msg delimiters)
This commit is contained in:
parent
e5b038dc91
commit
3c3cb50c86
43
src/comms.rs
Normal file → Executable file
43
src/comms.rs
Normal file → Executable file
@ -1,5 +1,6 @@
|
||||
use crate::crypto;
|
||||
use aes_gcm::{aead::consts::U12, aes::Aes256, AesGcm};
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use rand::rngs::OsRng;
|
||||
use std::error::Error;
|
||||
use tokio::{
|
||||
@ -7,29 +8,49 @@ use tokio::{
|
||||
net::tcp::{ReadHalf, WriteHalf},
|
||||
};
|
||||
|
||||
pub async fn send_bytes(
|
||||
pub async fn send(
|
||||
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>,
|
||||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
let data = enc.map_or(Ok(data.clone()), |enc| {
|
||||
crypto::aes_encrypt(data, enc.0, enc.1)
|
||||
})?;
|
||||
writer.write_all(&data).await?;
|
||||
let enc: Vec<u8>;
|
||||
if let (Some(cipher), Some(rng)) = (cipher, rng) {
|
||||
enc = crypto::aes_encrypt(data, cipher, rng)?;
|
||||
} 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?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn recv_bytes(
|
||||
pub async fn recv(
|
||||
reader: &mut BufReader<ReadHalf<'_>>,
|
||||
cipher: Option<&mut AesGcm<Aes256, U12>>,
|
||||
buf: &mut Vec<u8>,
|
||||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
let recv_bytes = reader.read_until(b'\n', buf).await?;
|
||||
*buf = cipher.map_or(Ok(buf.clone()), |c| crypto::aes_decrypt(&buf, c))?;
|
||||
if recv_bytes == 0 {
|
||||
todo!("ERROR: No message received or client <xyz> crashed");
|
||||
let n = reader.read_until(b':', buf).await?;
|
||||
|
||||
if n == 0 {
|
||||
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(())
|
||||
|
35
src/crypto.rs
Normal file → Executable file
35
src/crypto.rs
Normal file → Executable file
@ -13,6 +13,7 @@ use tokio::{
|
||||
use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret};
|
||||
|
||||
const AES_NONCE_SIZE: usize = 12;
|
||||
const DH_PBK_SIZE: usize = 32;
|
||||
|
||||
pub async fn edh(
|
||||
reader: &mut BufReader<ReadHalf<'_>>,
|
||||
@ -22,18 +23,19 @@ pub async fn edh(
|
||||
) -> Result<SharedSecret, Box<dyn Error + Send + Sync>> {
|
||||
let own_sec = EphemeralSecret::new(OsRng);
|
||||
let own_pbk = PublicKey::from(&own_sec);
|
||||
let msg = own_pbk.as_bytes().to_vec();
|
||||
|
||||
if go_first {
|
||||
comms::send_bytes(writer, None, &own_pbk.as_bytes().to_vec()).await?;
|
||||
comms::recv_bytes(reader, None, buf).await?;
|
||||
comms::send(writer, None, None, &msg).await?;
|
||||
comms::recv(reader, None, buf).await?;
|
||||
} else {
|
||||
comms::recv_bytes(reader, None, buf).await?;
|
||||
comms::send_bytes(writer, None, &own_pbk.as_bytes().to_vec()).await?;
|
||||
comms::recv(reader, None, buf).await?;
|
||||
comms::send(writer, None, None, &msg).await?;
|
||||
}
|
||||
|
||||
let sliced_buf: [u8; 32] = buf[..32].try_into()?;
|
||||
let recv_pbk = PublicKey::from(sliced_buf);
|
||||
let slice: [u8; DH_PBK_SIZE] = buf[..DH_PBK_SIZE].try_into()?;
|
||||
buf.clear();
|
||||
let recv_pbk = PublicKey::from(slice);
|
||||
|
||||
Ok(own_sec.diffie_hellman(&recv_pbk))
|
||||
}
|
||||
@ -75,3 +77,24 @@ pub fn aes_decrypt(
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user