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 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
35
src/crypto.rs
Normal file → Executable 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user