Crypto in vc
This commit is contained in:
+42
-10
@@ -2,9 +2,9 @@ use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
use anyhow::Context;
|
||||
use ed25519_dalek::VerifyingKey;
|
||||
use tokio::net::UdpSocket;
|
||||
use tokio::{net::UdpSocket, sync::Mutex};
|
||||
|
||||
use crate::{protocol::ClientMethod, server::Server};
|
||||
use crate::{crypto::SessionCipher, protocol::ClientMethod, server::Server};
|
||||
|
||||
use tokio::time::Instant;
|
||||
|
||||
@@ -31,16 +31,18 @@ impl Server {
|
||||
let pin_bytes: [u8; 8] = buf[..8].try_into().unwrap();
|
||||
let pin = u64::from_be_bytes(pin_bytes);
|
||||
|
||||
let (sender_pubkey, channel_id, payload) = {
|
||||
// is_first_packet distinguishes the plaintext pin-bootstrap packet
|
||||
// from subsequent encrypted audio packets.
|
||||
let (sender_pubkey, channel_id, payload, is_first_packet) = {
|
||||
let mut pins = self.voice_pins.lock().await;
|
||||
|
||||
if let Some((pubkey, channel_id)) = pins.remove(&pin) {
|
||||
(pubkey, channel_id, &buf[8..len])
|
||||
(pubkey, channel_id, &buf[8..len], true)
|
||||
} else {
|
||||
drop(pins);
|
||||
|
||||
match self.find_voice_sender(&addr).await {
|
||||
Some((pubkey, channel_id)) => (pubkey, channel_id, &buf[..]),
|
||||
Some((pubkey, channel_id)) => (pubkey, channel_id, &buf[..len], false),
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
@@ -69,8 +71,31 @@ impl Server {
|
||||
|
||||
drop(voice);
|
||||
|
||||
self.relay_voice(&sender_pubkey, &channel_id, payload)
|
||||
.await?;
|
||||
// The pin-bearing bootstrap packet carries no payload to decrypt —
|
||||
// it's purely "here's my pin, bind my address." Everything after
|
||||
// this first packet is the real, encrypted audio stream.
|
||||
if is_first_packet {
|
||||
continue;
|
||||
}
|
||||
|
||||
let decrypted_payload = match user.cihper.lock().await.decrypt(payload) {
|
||||
Ok(pt) => pt,
|
||||
Err(e) => {
|
||||
eprintln!("[vc] dropping packet: decryption failed: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let s = self.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = s
|
||||
.relay_voice(&sender_pubkey, &channel_id, &decrypted_payload)
|
||||
.await
|
||||
{
|
||||
eprintln!("{e}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +150,7 @@ impl Server {
|
||||
continue;
|
||||
}
|
||||
|
||||
let _ = self.udp_send_to(&voice.addr, payload).await;
|
||||
let _ = self.udp_send_to(&user.cihper, &voice.addr, payload).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -137,10 +162,17 @@ impl Server {
|
||||
.context("Failed to get voice socket")
|
||||
}
|
||||
|
||||
pub async fn udp_send_to(&self, addr: &SocketAddr, payload: &[u8]) -> anyhow::Result<()> {
|
||||
pub async fn udp_send_to(
|
||||
&self,
|
||||
cipher: &Arc<Mutex<SessionCipher>>,
|
||||
addr: &SocketAddr,
|
||||
payload: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
let socket = self.get_voice_socket()?;
|
||||
|
||||
socket.send_to(payload, addr).await?;
|
||||
socket
|
||||
.send_to(&cipher.lock().await.encrypt(payload)?, addr)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user