support encryption (#60)

This commit is contained in:
Sijie.Sun
2024-04-27 13:44:59 +08:00
committed by GitHub
parent 69651ae3fd
commit fcc73159b3
23 changed files with 489 additions and 81 deletions

View File

@@ -1,3 +1,5 @@
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use std::{net::SocketAddr, pin::Pin, sync::Arc};
use async_trait::async_trait;
@@ -197,3 +199,17 @@ impl TunnelUrl {
})
}
}
pub fn generate_digest_from_str(str1: &str, str2: &str, digest: &mut [u8]) {
let mut hasher = DefaultHasher::new();
hasher.write(str1.as_bytes());
hasher.write(str2.as_bytes());
assert_eq!(digest.len() % 8, 0, "digest length must be multiple of 8");
let shard_count = digest.len() / 8;
for i in 0..shard_count {
digest[i * 8..(i + 1) * 8].copy_from_slice(&hasher.finish().to_be_bytes());
hasher.write(&digest[..(i + 1) * 8]);
}
}

View File

@@ -56,16 +56,53 @@ pub enum PacketType {
Route = 7,
}
bitflags::bitflags! {
struct PeerManagerHeaderFlags: u8 {
const ENCRYPTED = 0b0000_0001;
}
}
#[repr(C, packed)]
#[derive(AsBytes, FromBytes, FromZeroes, Clone, Debug, Default)]
pub struct PeerManagerHeader {
pub from_peer_id: U32<DefaultEndian>,
pub to_peer_id: U32<DefaultEndian>,
pub packet_type: u8,
pub flags: u8,
reserved: U16<DefaultEndian>,
pub len: U32<DefaultEndian>,
}
pub const PEER_MANAGER_HEADER_SIZE: usize = std::mem::size_of::<PeerManagerHeader>();
impl PeerManagerHeader {
pub fn is_encrypted(&self) -> bool {
PeerManagerHeaderFlags::from_bits(self.flags)
.unwrap()
.contains(PeerManagerHeaderFlags::ENCRYPTED)
}
pub fn set_encrypted(&mut self, encrypted: bool) {
let mut flags = PeerManagerHeaderFlags::from_bits(self.flags).unwrap();
if encrypted {
flags.insert(PeerManagerHeaderFlags::ENCRYPTED);
} else {
flags.remove(PeerManagerHeaderFlags::ENCRYPTED);
}
self.flags = flags.bits();
}
}
// reserve the space for aes tag and nonce
#[repr(C, packed)]
#[derive(AsBytes, FromBytes, FromZeroes, Clone, Debug, Default)]
pub struct AesGcmTail {
pub tag: [u8; 16],
pub nonce: [u8; 12],
}
pub const AES_GCM_ENCRYPTION_RESERVED: usize = std::mem::size_of::<AesGcmTail>();
pub const TAIL_RESERVED_SIZE: usize = AES_GCM_ENCRYPTION_RESERVED;
const fn max(a: usize, b: usize) -> usize {
[a, b][(a < b) as usize]
}
@@ -308,6 +345,7 @@ impl ZCPacket {
hdr.from_peer_id.set(from_peer_id);
hdr.to_peer_id.set(to_peer_id);
hdr.packet_type = packet_type;
hdr.flags = 0;
hdr.len.set(payload_len as u32);
}

View File

@@ -1,7 +1,5 @@
use std::{
collections::hash_map::DefaultHasher,
fmt::{Debug, Formatter},
hash::Hasher,
net::SocketAddr,
pin::Pin,
sync::{atomic::AtomicBool, Arc},
@@ -33,6 +31,7 @@ use crate::{
use super::{
check_scheme_and_get_socket_addr,
common::{setup_sokcet2, setup_sokcet2_ext, wait_for_connect_futures},
generate_digest_from_str,
packet_def::{ZCPacketType, PEER_MANAGER_HEADER_SIZE},
ring::create_ring_tunnel_pair,
Tunnel, TunnelError, TunnelListener, TunnelUrl, ZCPacketSink, ZCPacketStream,
@@ -62,16 +61,7 @@ pub struct WgConfig {
impl WgConfig {
pub fn new_from_network_identity(network_name: &str, network_secret: &str) -> Self {
let mut my_sec = [0u8; 32];
let mut hasher = DefaultHasher::new();
hasher.write(network_name.as_bytes());
hasher.write(network_secret.as_bytes());
my_sec[0..8].copy_from_slice(&hasher.finish().to_be_bytes());
hasher.write(&my_sec[0..8]);
my_sec[8..16].copy_from_slice(&hasher.finish().to_be_bytes());
hasher.write(&my_sec[0..16]);
my_sec[16..24].copy_from_slice(&hasher.finish().to_be_bytes());
hasher.write(&my_sec[0..24]);
my_sec[24..32].copy_from_slice(&hasher.finish().to_be_bytes());
generate_digest_from_str(network_name, network_secret, &mut my_sec);
let my_secret_key = StaticSecret::from(my_sec);
let my_public_key = PublicKey::from(&my_secret_key);
@@ -491,6 +481,7 @@ impl WgTunnelListener {
let mut buf = vec![0u8; MAX_PACKET];
loop {
tracing::info!("Waiting for incoming UDP packet");
let Ok((n, addr)) = socket.recv_from(&mut buf).await else {
tracing::error!("Failed to receive from UDP socket");
break;