加密算法可选

This commit is contained in:
lubeilin
2023-09-27 19:51:23 +08:00
parent 40cbd2e26b
commit bd61cad7b6
9 changed files with 241 additions and 48 deletions
+12 -8
View File
@@ -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
View File
@@ -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,
}
+8 -3
View File
@@ -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;
+33 -7
View File
@@ -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,
+4 -4
View File
@@ -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(
+2 -1
View File
@@ -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