From 7c30f2691ad6fbc4f23ead47609e1316c5803bbf Mon Sep 17 00:00:00 2001 From: lubeilin <1791778603@qq.com> Date: Sat, 29 Jul 2023 18:09:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9D=A1=E4=BB=B6=E7=BC=96?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnt-cli/Cargo.toml | 13 +-- vnt/Cargo.toml | 8 +- vnt/src/cipher/aes_gcm_cipher.rs | 115 ++++++++++++++++++++++++++ vnt/src/cipher/mod.rs | 138 ++----------------------------- vnt/src/cipher/ring_cipher.rs | 132 +++++++++++++++++++++++++++++ 5 files changed, 270 insertions(+), 136 deletions(-) create mode 100644 vnt/src/cipher/aes_gcm_cipher.rs create mode 100644 vnt/src/cipher/ring_cipher.rs diff --git a/vnt-cli/Cargo.toml b/vnt-cli/Cargo.toml index 829ab322..558599d3 100644 --- a/vnt-cli/Cargo.toml +++ b/vnt-cli/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -vnt = {path="../vnt"} -common = {path="../common"} +vnt = { path = "../vnt", package = "vnt", optional = true } +common = { path = "../common" } tokio = { version = "1.28.1", features = ["full"] } getopts = "0.2.21" console = "0.15.2" @@ -19,7 +19,7 @@ log = "0.4.17" [dependencies.uuid] version = "1.4.1" features = [ - "v4", # Lets you generate random UUIDs + "v4", # Lets you generate random UUIDs ] [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] @@ -27,9 +27,12 @@ sudo = "0.6.0" [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] } + [features] -default = [] -mini = [] +default = ["normal"] +normal = ["vnt"] +ring-cipher = ["vnt/ring-cipher"] + [build-dependencies] embed-manifest = "1.4.0" \ No newline at end of file diff --git a/vnt/Cargo.toml b/vnt/Cargo.toml index 1251f99e..66212df3 100644 --- a/vnt/Cargo.toml +++ b/vnt/Cargo.toml @@ -15,11 +15,12 @@ crossbeam-skiplist = "0.1" parking_lot = "0.12.1" rand = "0.8.5" sha2 = { version = "0.10.6", features = ["oid"] } -ring = "0.16.20" thiserror = "1.0.37" protobuf = "3.2.0" socket2 ={ version = "0.5.2", features = ["all"] } tokio = { version = "1.28.1", features = ["full"] } +aes-gcm = {version="0.10.2", optional = true} +ring = {version="0.16.20", optional = true} [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] tun = { path = "./rust-tun" } @@ -32,3 +33,8 @@ libloading = "0.7.4" protobuf-codegen = "3.2.0" protoc-bin-vendored = "3.0.0" +[features] +default=["aes-gcm"] +ring-cipher=["ring"] + + diff --git a/vnt/src/cipher/aes_gcm_cipher.rs b/vnt/src/cipher/aes_gcm_cipher.rs new file mode 100644 index 00000000..f3d9f7d2 --- /dev/null +++ b/vnt/src/cipher/aes_gcm_cipher.rs @@ -0,0 +1,115 @@ +use std::io; + +use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, Nonce, Tag,KeyInit}; +use aes_gcm::aead::consts::{U12, U16}; +use aes_gcm::aead::generic_array::GenericArray; +use sha2::Digest; + +use crate::protocol; +use crate::protocol::{ip_turn_packet, NetPacket}; + +#[derive(Clone)] +pub enum Cipher { + AesGCM128(Aes128Gcm), + AesGCM256(Aes256Gcm), + None, +} + +impl Cipher { + pub fn new(password: Option) -> Self { + if let Some(password) = password { + let mut hasher = sha2::Sha256::new(); + hasher.update(password.as_bytes()); + let key: [u8; 32] = hasher.finalize().into(); + if password.len() < 8 { + let key: &Key = key[..16].into(); + Cipher::AesGCM128(Aes128Gcm::new(&key)) + } else { + let key: &Key = &key.into(); + Cipher::AesGCM256(Aes256Gcm::new(&key)) + } + } else { + Cipher::None + } + } + pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { + match &self { + Cipher::None => { + return Ok(None); + } + _ => {} + } + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + } + if net_packet.payload().len() < 16 { + log::error!("数据异常,长度小于16"); + return Err(io::Error::new(io::ErrorKind::Other, "data err")); + } + let mut nonce = [0; 12]; + nonce[0..4].copy_from_slice(&net_packet.source().octets()); + nonce[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce[8] = protocol::Protocol::IpTurn.into(); + nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); + let nonce: &GenericArray = Nonce::from_slice(&nonce); + let payload_len = net_packet.payload().len() - 16; + let tag: GenericArray = Tag::clone_from_slice(&net_packet.payload()[payload_len..]); + let rs = match &self { + Cipher::AesGCM128(cipher) => { + cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag) + } + Cipher::AesGCM256(cipher) => { + cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag) + } + Cipher::None => { + return Ok(None); + } + }; + if let Err(e) = rs { + return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e))); + } + return Ok(Some(payload_len)); + } + /// net_packet 必须预留足够长度 + /// data_len是有效载荷的长度 + /// 返回加密后载荷的长度 + pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { + match &self { + Cipher::None => { + return Ok(None); + } + _ => {} + } + let mut nonce = [0; 12]; + nonce[0..4].copy_from_slice(&net_packet.source().octets()); + nonce[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce[8] = protocol::Protocol::IpTurn.into(); + nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); + let nonce: &GenericArray = Nonce::from_slice(&nonce); + let rs = match &self { + Cipher::AesGCM128(cipher) => { + cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len]) + } + Cipher::AesGCM256(cipher) => { + cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len]) + } + Cipher::None => { + return Ok(None); + } + }; + return match rs { + Ok(tag) => { + if tag.len() != 16 { + return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len()))); + } + net_packet.set_encrypt_flag(true); + net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag.as_slice()); + Ok(Some(payload_len + 16)) + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e))) + } + }; + } +} \ No newline at end of file diff --git a/vnt/src/cipher/mod.rs b/vnt/src/cipher/mod.rs index 6eb9f355..21022ded 100644 --- a/vnt/src/cipher/mod.rs +++ b/vnt/src/cipher/mod.rs @@ -1,130 +1,8 @@ -use std::io; -use ring::aead; -use ring::aead::{LessSafeKey, UnboundKey}; -use sha2::Digest; - -use crate::protocol; -use crate::protocol::{ip_turn_packet, NetPacket}; - -pub enum Cipher { - AesGCM128(LessSafeKey, [u8; 16]), - AesGCM256(LessSafeKey, [u8; 32]), - None, -} - -impl Clone for Cipher { - fn clone(&self) -> Self { - match &self { - Cipher::AesGCM128(_, key) => { - let c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap()); - Cipher::AesGCM128(c, *key) - } - Cipher::AesGCM256(_, key) => { - let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap()); - Cipher::AesGCM256(c, *key) - } - Cipher::None => { - Cipher::None - } - } - } -} - -impl Cipher { - pub fn new(password: Option) -> Self { - if let Some(password) = password { - let mut hasher = sha2::Sha256::new(); - hasher.update(password.as_bytes()); - let key: [u8; 32] = hasher.finalize().into(); - if password.len() < 8 { - let c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key[..16]).unwrap()); - Cipher::AesGCM128(c, key[..16].try_into().unwrap()) - } else { - let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap()); - Cipher::AesGCM256(c, key) - } - } else { - Cipher::None - } - } - pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { - match &self { - Cipher::None => { - return Ok(None); - } - _ => {} - } - if !net_packet.is_encrypt() { - //未加密的数据直接丢弃 - return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); - } - if net_packet.payload().len() < 16 { - log::error!("数据异常,长度小于16"); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); - } - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&net_packet.source().octets()); - nonce[4..8].copy_from_slice(&net_packet.destination().octets()); - nonce[8] = protocol::Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce = aead::Nonce::assume_unique_for_key(nonce); - let payload_len = net_packet.payload().len() - 16; - let rs = match &self { - Cipher::AesGCM128(cipher, _) => { - cipher.open_in_place(nonce, aead::Aad::empty(), net_packet.payload_mut()) - } - Cipher::AesGCM256(cipher, _) => { - cipher.open_in_place(nonce, aead::Aad::empty(), net_packet.payload_mut()) - } - Cipher::None => { - return Ok(None); - } - }; - if let Err(e) = rs { - return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e))); - } - return Ok(Some(payload_len)); - } - /// net_packet 必须预留足够长度 - /// data_len是有效载荷的长度 - /// 返回加密后载荷的长度 - pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { - match &self { - Cipher::None => { - return Ok(None); - } - _ => {} - } - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&net_packet.source().octets()); - nonce[4..8].copy_from_slice(&net_packet.destination().octets()); - nonce[8] = protocol::Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce = aead::Nonce::assume_unique_for_key(nonce); - let rs = match &self { - Cipher::AesGCM128(cipher, _) => { - cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut net_packet.payload_mut()[..payload_len]) - } - Cipher::AesGCM256(cipher, _) => { - cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut net_packet.payload_mut()[..payload_len]) - } - Cipher::None => { - return Ok(None); - } - }; - return match rs { - Ok(tag) => { - let tag = tag.as_ref(); - if tag.len() != 16 { - return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len()))); - } - net_packet.set_encrypt_flag(true); - net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag); - Ok(Some(payload_len + 16)) - } - Err(e) => { - Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e))) - } - }; - } -} \ No newline at end of file +#[cfg(feature = "ring-cipher")] +mod ring_cipher; +#[cfg(feature = "ring-cipher")] +pub use ring_cipher::Cipher; +#[cfg(not(feature = "ring-cipher"))] +mod aes_gcm_cipher; +#[cfg(not(feature = "ring-cipher"))] +pub use aes_gcm_cipher::Cipher; \ No newline at end of file diff --git a/vnt/src/cipher/ring_cipher.rs b/vnt/src/cipher/ring_cipher.rs new file mode 100644 index 00000000..fc7abfcd --- /dev/null +++ b/vnt/src/cipher/ring_cipher.rs @@ -0,0 +1,132 @@ + + +use std::io; +use ring::aead; +use ring::aead::{LessSafeKey, UnboundKey}; +use sha2::Digest; + +use crate::protocol; +use crate::protocol::{ip_turn_packet, NetPacket}; + +pub enum Cipher { + AesGCM128(LessSafeKey, [u8; 16]), + AesGCM256(LessSafeKey, [u8; 32]), + None, +} + +impl Clone for Cipher { + fn clone(&self) -> Self { + match &self { + Cipher::AesGCM128(_, key) => { + let c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap()); + Cipher::AesGCM128(c, *key) + } + Cipher::AesGCM256(_, key) => { + let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap()); + Cipher::AesGCM256(c, *key) + } + Cipher::None => { + Cipher::None + } + } + } +} + +impl Cipher { + pub fn new(password: Option) -> Self { + if let Some(password) = password { + let mut hasher = sha2::Sha256::new(); + hasher.update(password.as_bytes()); + let key: [u8; 32] = hasher.finalize().into(); + if password.len() < 8 { + let c = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key[..16]).unwrap()); + Cipher::AesGCM128(c, key[..16].try_into().unwrap()) + } else { + let c = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap()); + Cipher::AesGCM256(c, key) + } + } else { + Cipher::None + } + } + pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { + match &self { + Cipher::None => { + return Ok(None); + } + _ => {} + } + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + } + if net_packet.payload().len() < 16 { + log::error!("数据异常,长度小于16"); + return Err(io::Error::new(io::ErrorKind::Other, "data err")); + } + let mut nonce = [0; 12]; + nonce[0..4].copy_from_slice(&net_packet.source().octets()); + nonce[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce[8] = protocol::Protocol::IpTurn.into(); + nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); + let nonce = aead::Nonce::assume_unique_for_key(nonce); + let payload_len = net_packet.payload().len() - 16; + let rs = match &self { + Cipher::AesGCM128(cipher, _) => { + cipher.open_in_place(nonce, aead::Aad::empty(), net_packet.payload_mut()) + } + Cipher::AesGCM256(cipher, _) => { + cipher.open_in_place(nonce, aead::Aad::empty(), net_packet.payload_mut()) + } + Cipher::None => { + return Ok(None); + } + }; + if let Err(e) = rs { + return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e))); + } + return Ok(Some(payload_len)); + } + /// net_packet 必须预留足够长度 + /// data_len是有效载荷的长度 + /// 返回加密后载荷的长度 + pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { + match &self { + Cipher::None => { + return Ok(None); + } + _ => {} + } + let mut nonce = [0; 12]; + nonce[0..4].copy_from_slice(&net_packet.source().octets()); + nonce[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce[8] = protocol::Protocol::IpTurn.into(); + nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); + let nonce = aead::Nonce::assume_unique_for_key(nonce); + let rs = match &self { + Cipher::AesGCM128(cipher, _) => { + cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut net_packet.payload_mut()[..payload_len]) + } + Cipher::AesGCM256(cipher, _) => { + cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut net_packet.payload_mut()[..payload_len]) + } + Cipher::None => { + return Ok(None); + } + }; + return match rs { + Ok(tag) => { + let tag = tag.as_ref(); + if tag.len() != 16 { + return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len()))); + } + net_packet.set_encrypt_flag(true); + net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag); + Ok(Some(payload_len + 16)) + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e))) + } + }; + } +} \ No newline at end of file