Crypto in vc

This commit is contained in:
2026-08-28 15:20:08 +02:00
parent a60979579a
commit 281238f8e1
+42 -10
View File
@@ -2,9 +2,9 @@ use std::{net::SocketAddr, sync::Arc};
use anyhow::Context; use anyhow::Context;
use ed25519_dalek::VerifyingKey; 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; use tokio::time::Instant;
@@ -31,16 +31,18 @@ impl Server {
let pin_bytes: [u8; 8] = buf[..8].try_into().unwrap(); let pin_bytes: [u8; 8] = buf[..8].try_into().unwrap();
let pin = u64::from_be_bytes(pin_bytes); 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; let mut pins = self.voice_pins.lock().await;
if let Some((pubkey, channel_id)) = pins.remove(&pin) { if let Some((pubkey, channel_id)) = pins.remove(&pin) {
(pubkey, channel_id, &buf[8..len]) (pubkey, channel_id, &buf[8..len], true)
} else { } else {
drop(pins); drop(pins);
match self.find_voice_sender(&addr).await { 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 => { None => {
continue; continue;
} }
@@ -69,8 +71,31 @@ impl Server {
drop(voice); drop(voice);
self.relay_voice(&sender_pubkey, &channel_id, payload) // The pin-bearing bootstrap packet carries no payload to decrypt —
.await?; // 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; continue;
} }
let _ = self.udp_send_to(&voice.addr, payload).await; let _ = self.udp_send_to(&user.cihper, &voice.addr, payload).await;
} }
Ok(()) Ok(())
@@ -137,10 +162,17 @@ impl Server {
.context("Failed to get voice socket") .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()?; let socket = self.get_voice_socket()?;
socket.send_to(payload, addr).await?; socket
.send_to(&cipher.lock().await.encrypt(payload)?, addr)
.await?;
Ok(()) Ok(())
} }