Crypto in vc
This commit is contained in:
+42
-10
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user