加密算法可选
This commit is contained in:
+12
-8
@@ -20,16 +20,16 @@ thiserror = "1.0.37"
|
||||
protobuf = "3.2.0"
|
||||
socket2 = { version = "0.5.2", features = ["all"] }
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
aes-gcm = { version = "0.10.2" }
|
||||
aes-gcm = { version = "0.10.2",optional = true }
|
||||
ring = { version = "0.16.20", optional = true }
|
||||
cbc = "0.1.2"
|
||||
ecb = "0.1.2"
|
||||
cbc = {version = "0.1.2",optional = true}
|
||||
ecb = {version = "0.1.2",optional = true}
|
||||
aes = "0.8.3"
|
||||
stun-format = { version = "1.0.1", features = ["fmt", "rfc3489"] }
|
||||
rsa = { version = "0.7.2", features = [] }
|
||||
spki = { version = "0.6.0", features = ["fingerprint", "alloc"] }
|
||||
rsa = { version = "0.7.2", features = [] ,optional = true}
|
||||
spki = { version = "0.6.0", features = ["fingerprint", "alloc"] ,optional = true}
|
||||
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl" ,optional = true}
|
||||
libsm = {git="https://github.com/lbl8603/libsm"}
|
||||
libsm = {git="https://github.com/lbl8603/libsm" ,optional = true}
|
||||
|
||||
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
|
||||
tun = { path = "./rust-tun" }
|
||||
@@ -44,10 +44,14 @@ protobuf-codegen = "3.2.0"
|
||||
protoc-bin-vendored = "3.0.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["server_encrypt","aes_gcm","aes_cbc","aes_ecb","sm4_cbc"]
|
||||
openssl = ["openssl-sys"]
|
||||
# 从源码编译
|
||||
openssl-vendored = ["openssl-sys/vendored"]
|
||||
ring-cipher = ["ring"]
|
||||
|
||||
aes_cbc=["cbc"]
|
||||
aes_ecb=["ecb"]
|
||||
sm4_cbc=["libsm"]
|
||||
aes_gcm=["aes-gcm","ring"]
|
||||
server_encrypt =["rsa","spki"]
|
||||
|
||||
|
||||
+84
-14
@@ -1,25 +1,37 @@
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
||||
use crate::cipher::aes_ecb::AesEcbCipher;
|
||||
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
use crate::cipher::aes_cbc::AesCbcCipher;
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
#[cfg(not(feature = "ring-cipher"))]
|
||||
use crate::cipher::aes_gcm_cipher::AesGcmCipher;
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||
use crate::cipher::openssl_aes_ecb::AesEcbCipher;
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
#[cfg(feature = "ring-cipher")]
|
||||
use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher;
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
use crate::cipher::sm4_cbc::Sm4CbcCipher;
|
||||
use crate::cipher::{aes_cbc, Finger};
|
||||
use crate::cipher::Finger;
|
||||
use crate::protocol::NetPacket;
|
||||
use aes_cbc::AesCbcCipher;
|
||||
use sha2::Digest;
|
||||
use std::io;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum CipherModel {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
AesGcm,
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
AesCbc,
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
AesEcb,
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
Sm4Cbc,
|
||||
None,
|
||||
}
|
||||
|
||||
impl FromStr for CipherModel {
|
||||
@@ -27,20 +39,44 @@ impl FromStr for CipherModel {
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_lowercase().trim() {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
"aes_gcm" => Ok(CipherModel::AesGcm),
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
"aes_cbc" => Ok(CipherModel::AesCbc),
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
"aes_ecb" => Ok(CipherModel::AesEcb),
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
"sm4_cbc" => Ok(CipherModel::Sm4Cbc),
|
||||
_ => Err(format!("not match '{}', enum:aes_gcm/aes_cbc/aes_ecb", s)),
|
||||
_ => {
|
||||
let mut enums = String::new();
|
||||
#[cfg(feature = "aes_gcm")]
|
||||
enums.push_str("/aes_gcm");
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
enums.push_str("/aes_cbc");
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
enums.push_str("/aes_ecb");
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
enums.push_str("/sm4_cbc");
|
||||
let str = if enums.is_empty() {
|
||||
"no encrypt"
|
||||
} else {
|
||||
&enums[1..]
|
||||
};
|
||||
Err(format!("not match '{}', enum:{}", s, str))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Cipher {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
AesGcm((AesGcmCipher, Vec<u8>)),
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
AesCbc(AesCbcCipher),
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
AesEcb(AesEcbCipher),
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
Sm4Cbc(Sm4CbcCipher),
|
||||
None,
|
||||
}
|
||||
@@ -57,6 +93,7 @@ impl Cipher {
|
||||
hasher.update(password.as_bytes());
|
||||
let key: [u8; 32] = hasher.finalize().into();
|
||||
match model {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
CipherModel::AesGcm => {
|
||||
if password.len() < 8 {
|
||||
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
@@ -66,6 +103,7 @@ impl Cipher {
|
||||
Cipher::AesGcm((aes, key.to_vec()))
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
CipherModel::AesCbc => {
|
||||
if password.len() < 8 {
|
||||
let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
@@ -75,6 +113,7 @@ impl Cipher {
|
||||
Cipher::AesCbc(aes)
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
CipherModel::AesEcb => {
|
||||
if password.len() < 8 {
|
||||
let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
@@ -84,10 +123,12 @@ impl Cipher {
|
||||
Cipher::AesEcb(aes)
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
CipherModel::Sm4Cbc => {
|
||||
let aes = Sm4CbcCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
Cipher::Sm4Cbc(aes)
|
||||
}
|
||||
CipherModel::None => Cipher::None,
|
||||
}
|
||||
} else {
|
||||
Cipher::None
|
||||
@@ -96,10 +137,12 @@ impl Cipher {
|
||||
pub fn new_key(key: [u8; 32], token: String) -> io::Result<Self> {
|
||||
let finger = Some(Finger::new(&token));
|
||||
match key.len() {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
16 => {
|
||||
let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger);
|
||||
Ok(Cipher::AesGcm((aes, key[..16].to_vec())))
|
||||
}
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
32 => {
|
||||
let aes = AesGcmCipher::new_256(key, finger);
|
||||
Ok(Cipher::AesGcm((aes, key.to_vec())))
|
||||
@@ -112,9 +155,13 @@ impl Cipher {
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
match self {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.decrypt_ipv4(net_packet),
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
Cipher::AesCbc(aes_cbc) => aes_cbc.decrypt_ipv4(net_packet),
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
Cipher::AesEcb(aes_ecb) => aes_ecb.decrypt_ipv4(net_packet),
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.decrypt_ipv4(net_packet),
|
||||
Cipher::None => {
|
||||
if net_packet.is_encrypt() {
|
||||
@@ -129,32 +176,55 @@ impl Cipher {
|
||||
net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<()> {
|
||||
match self {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet),
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
Cipher::AesCbc(aes_cbc) => aes_cbc.encrypt_ipv4(net_packet),
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
Cipher::AesEcb(aes_ecb) => aes_ecb.encrypt_ipv4(net_packet),
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.encrypt_ipv4(net_packet),
|
||||
Cipher::None => Ok(()),
|
||||
}
|
||||
}
|
||||
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
|
||||
let finger = match self {
|
||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm.finger.as_ref(),
|
||||
Cipher::AesCbc(aes_cbc) => aes_cbc.finger.as_ref(),
|
||||
Cipher::AesEcb(aes_ecb) => aes_ecb.finger.as_ref(),
|
||||
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc.finger.as_ref(),
|
||||
Cipher::None => None,
|
||||
};
|
||||
if let Some(finger) = finger {
|
||||
finger.check_finger(net_packet)
|
||||
} else {
|
||||
Ok(())
|
||||
match self {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
Cipher::AesGcm((aes_gcm, _)) => aes_gcm
|
||||
.finger
|
||||
.as_ref()
|
||||
.map(|f| f.check_finger(net_packet))
|
||||
.unwrap_or(Ok(())),
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
Cipher::AesCbc(aes_cbc) => aes_cbc
|
||||
.finger
|
||||
.as_ref()
|
||||
.map(|f| f.check_finger(net_packet))
|
||||
.unwrap_or(Ok(())),
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
Cipher::AesEcb(aes_ecb) => aes_ecb
|
||||
.finger
|
||||
.as_ref()
|
||||
.map(|f| f.check_finger(net_packet))
|
||||
.unwrap_or(Ok(())),
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
Cipher::Sm4Cbc(sm4_cbc) => sm4_cbc
|
||||
.finger
|
||||
.as_ref()
|
||||
.map(|f| f.check_finger(net_packet))
|
||||
.unwrap_or(Ok(())),
|
||||
Cipher::None => Ok(()),
|
||||
}
|
||||
}
|
||||
pub fn key(&self) -> Option<&[u8]> {
|
||||
match self {
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
Cipher::AesGcm((_, key)) => Some(key),
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
Cipher::AesCbc(aes_cbc) => Some(aes_cbc.key()),
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
Cipher::AesEcb(aes_ecb) => Some(aes_ecb.key()),
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
Cipher::Sm4Cbc(sm4_cbc) => Some(sm4_cbc.key()),
|
||||
Cipher::None => None,
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
#[cfg(feature = "aes_cbc")]
|
||||
mod aes_cbc;
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
|
||||
mod aes_ecb;
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
#[cfg(not(feature = "ring-cipher"))]
|
||||
mod aes_gcm_cipher;
|
||||
mod cipher;
|
||||
mod finger;
|
||||
#[cfg(feature = "aes_ecb")]
|
||||
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||
mod openssl_aes_ecb;
|
||||
#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))]
|
||||
#[cfg(feature = "ring-cipher")]
|
||||
mod ring_aes_gcm_cipher;
|
||||
mod rsa_cipher;
|
||||
|
||||
#[cfg(any(feature = "openssl-vendored", feature = "openssl"))]
|
||||
mod openssl_aes_ecb;
|
||||
#[cfg(feature = "sm4_cbc")]
|
||||
mod sm4_cbc;
|
||||
pub use cipher::Cipher;
|
||||
pub use cipher::CipherModel;
|
||||
|
||||
@@ -1,23 +1,32 @@
|
||||
use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED};
|
||||
use crate::protocol::NetPacket;
|
||||
use rand::Rng;
|
||||
use rsa::pkcs8::der::Decode;
|
||||
use rsa::{PublicKey, RsaPublicKey};
|
||||
use sha2::Digest;
|
||||
use spki::{DecodePublicKey, EncodePublicKey};
|
||||
use std::io;
|
||||
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
use crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED};
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
use rand::Rng;
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
use rsa::pkcs8::der::Decode;
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
use rsa::{PublicKey, RsaPublicKey};
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
use sha2::Digest;
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
use spki::{DecodePublicKey, EncodePublicKey};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RsaCipher {
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
inner: Inner,
|
||||
}
|
||||
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
#[derive(Clone)]
|
||||
struct Inner {
|
||||
public_key: RsaPublicKey,
|
||||
}
|
||||
|
||||
impl RsaCipher {
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
pub fn new(der: &[u8]) -> io::Result<Self> {
|
||||
match RsaPublicKey::from_public_key_der(der) {
|
||||
Ok(public_key) => {
|
||||
@@ -30,6 +39,11 @@ impl RsaCipher {
|
||||
)),
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "server_encrypt"))]
|
||||
pub fn new(_der: &[u8]) -> io::Result<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
pub fn finger(&self) -> io::Result<String> {
|
||||
match self.inner.public_key.to_public_key_der() {
|
||||
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfo::from_der(der.as_bytes()) {
|
||||
@@ -51,9 +65,21 @@ impl RsaCipher {
|
||||
)),
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "server_encrypt"))]
|
||||
pub fn finger(&self) -> io::Result<String> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl RsaCipher {
|
||||
#[cfg(not(feature = "server_encrypt"))]
|
||||
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
_net_packet: &mut NetPacket<B>,
|
||||
) -> io::Result<NetPacket<Vec<u8>>> {
|
||||
unimplemented!()
|
||||
}
|
||||
#[cfg(feature = "server_encrypt")]
|
||||
/// net_packet 必须预留足够长度
|
||||
pub fn encrypt<B: AsRef<[u8]> + AsMut<[u8]>>(
|
||||
&self,
|
||||
|
||||
@@ -116,7 +116,7 @@ impl Sm4CbcCipher {
|
||||
let mut out = [0u8; 1024 * 4];
|
||||
let mut iv = [0u8; 16];
|
||||
rand::thread_rng().fill_bytes(&mut iv);
|
||||
if net_packet.buffer().len() > 1024 * 4 - 32 {
|
||||
if net_packet.data_len() > 1024 * 4 - 32 {
|
||||
log::error!(
|
||||
"数据异常,长度{}大于1024 * 4 - 32",
|
||||
net_packet.buffer().len()
|
||||
@@ -125,10 +125,9 @@ impl Sm4CbcCipher {
|
||||
}
|
||||
match self.cipher.encrypt(net_packet.buffer(), &iv, &mut out) {
|
||||
Ok(len) => {
|
||||
out[len..len + 16].copy_from_slice(&iv);
|
||||
net_packet.set_data_len(HEAD_LEN + len + 16)?;
|
||||
net_packet.set_payload(&out[..len + 16])?;
|
||||
net_packet.set_encrypt_flag(true);
|
||||
net_packet.payload_mut()[..len].copy_from_slice(&out[..len]);
|
||||
net_packet.payload_mut()[len..].copy_from_slice(&iv);
|
||||
if let Some(finger) = &self.finger {
|
||||
let mut nonce_raw = [0; 12];
|
||||
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
|
||||
@@ -144,6 +143,7 @@ impl Sm4CbcCipher {
|
||||
|
||||
net_packet.buffer_mut()[src_data_len..].copy_from_slice(&finger);
|
||||
}
|
||||
net_packet.set_encrypt_flag(true);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(io::Error::new(
|
||||
|
||||
@@ -155,7 +155,7 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
|
||||
}
|
||||
/// 网关通信的标识
|
||||
pub fn is_gateway(&self) -> bool {
|
||||
self.buffer.as_ref()[0] & 0x50 == 0x50
|
||||
self.buffer.as_ref()[0] & 0x40 == 0x40
|
||||
}
|
||||
pub fn version(&self) -> Version {
|
||||
Version::from(self.buffer.as_ref()[0] & 0x0F)
|
||||
@@ -198,6 +198,7 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
|
||||
}
|
||||
pub fn set_gateway_flag(&mut self, is_gateway: bool) {
|
||||
if is_gateway {
|
||||
// 后面的版本再改为0x40,改了之后不兼容1.2.5之前的版本
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
|
||||
} else {
|
||||
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
|
||||
|
||||
Reference in New Issue
Block a user