diff --git a/vnt/src/cipher/aes_cbc/mod.rs b/vnt/src/cipher/aes_cbc/mod.rs new file mode 100644 index 0000000..6286a84 --- /dev/null +++ b/vnt/src/cipher/aes_cbc/mod.rs @@ -0,0 +1,2 @@ +mod rs_aes_cbc; +pub use rs_aes_cbc::*; diff --git a/vnt/src/cipher/aes_cbc.rs b/vnt/src/cipher/aes_cbc/rs_aes_cbc.rs similarity index 89% rename from vnt/src/cipher/aes_cbc.rs rename to vnt/src/cipher/aes_cbc/rs_aes_cbc.rs index 708fd55..b16d33a 100644 --- a/vnt/src/cipher/aes_cbc.rs +++ b/vnt/src/cipher/aes_cbc/rs_aes_cbc.rs @@ -1,6 +1,5 @@ -use std::io; - use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit}; +use anyhow::anyhow; use rand::RngCore; use crate::cipher::Finger; @@ -50,14 +49,14 @@ impl AesCbcCipher { pub fn decrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { if !net_packet.is_encrypt() { //未加密的数据直接丢弃 - return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + return Err(anyhow!("not encrypt")); } if net_packet.payload().len() < 16 { log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("aes_cbc data err")); } let mut iv = [0; 16]; iv[0..4].copy_from_slice(&net_packet.source().octets()); @@ -75,7 +74,7 @@ impl AesCbcCipher { if let Some(finger) = &self.finger { let finger = finger.calculate_finger(&iv[..12], secret_body.en_body()); if &finger != secret_body.finger() { - return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + return Err(anyhow!("aes_cbc finger err")); } } let rs = match &self.cipher { @@ -92,10 +91,7 @@ impl AesCbcCipher { net_packet.set_data_len(HEAD_LEN + len - 4)?; Ok(()) } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("解密失败:{}", e), - )), + Err(e) => Err(anyhow!("aes_cbc 解密失败:{}", e)), } } /// net_packet 必须预留足够长度 @@ -103,7 +99,7 @@ impl AesCbcCipher { pub fn encrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { let data_len = net_packet.data_len(); let mut iv = [0; 16]; iv[0..4].copy_from_slice(&net_packet.source().octets()); @@ -146,10 +142,7 @@ impl AesCbcCipher { net_packet.set_encrypt_flag(true); Ok(()) } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("加密失败:{}", e), - )), + Err(e) => Err(anyhow!("aes_cbc 加密失败:{}", e)), }; } } diff --git a/vnt/src/cipher/aes_ecb/mod.rs b/vnt/src/cipher/aes_ecb/mod.rs new file mode 100644 index 0000000..eab811f --- /dev/null +++ b/vnt/src/cipher/aes_ecb/mod.rs @@ -0,0 +1,9 @@ +#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))] +mod rs_aes_ecb; +#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))] +pub use rs_aes_ecb::*; + +#[cfg(any(feature = "openssl-vendored", feature = "openssl"))] +mod openssl_aes_ecb; +#[cfg(any(feature = "openssl-vendored", feature = "openssl"))] +pub use openssl_aes_ecb::*; diff --git a/vnt/src/cipher/openssl_aes_ecb.rs b/vnt/src/cipher/aes_ecb/openssl_aes_ecb.rs similarity index 88% rename from vnt/src/cipher/openssl_aes_ecb.rs rename to vnt/src/cipher/aes_ecb/openssl_aes_ecb.rs index e0e5b23..649fa04 100644 --- a/vnt/src/cipher/openssl_aes_ecb.rs +++ b/vnt/src/cipher/aes_ecb/openssl_aes_ecb.rs @@ -1,8 +1,11 @@ -use crate::cipher::Finger; -use crate::protocol::{NetPacket, HEAD_LEN}; +use std::ptr; + +use anyhow::anyhow; use libc::c_int; use openssl_sys::EVP_CIPHER_CTX; -use std::{io, ptr}; + +use crate::cipher::Finger; +use crate::protocol::{NetPacket, HEAD_LEN}; pub struct AesEcbCipher { key: Vec, @@ -100,10 +103,10 @@ impl AesEcbCipher { pub fn decrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { if !net_packet.is_encrypt() { //未加密的数据直接丢弃 - return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + return Err(anyhow!("not encrypt")); } if let Some(finger) = &self.finger { @@ -116,18 +119,18 @@ impl AesEcbCipher { nonce_raw[11] = net_packet.source_ttl(); let len = net_packet.payload().len(); if len < 12 { - return Err(io::Error::new(io::ErrorKind::Other, "data len err")); + return Err(anyhow!("data len err")); } let secret_body = &net_packet.payload()[..len - 12]; let finger = finger.calculate_finger(&nonce_raw, secret_body); if &finger != &net_packet.payload()[len - 12..] { - return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + return Err(anyhow!("finger err")); } net_packet.set_data_len(net_packet.data_len() - finger.len())?; } if net_packet.payload().len() < 16 { log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } let input = net_packet.payload(); let mut out = [0u8; 1024 * 5]; @@ -147,22 +150,22 @@ impl AesEcbCipher { //校验头部 let src_net_packet = NetPacket::new(text)?; if src_net_packet.source() != net_packet.source() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.destination() != net_packet.destination() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.protocol() != net_packet.protocol() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.transport_protocol() != net_packet.transport_protocol() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.is_gateway() != net_packet.is_gateway() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.source_ttl() != net_packet.source_ttl() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } } net_packet.set_encrypt_flag(false); @@ -175,7 +178,7 @@ impl AesEcbCipher { pub fn encrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { let input = net_packet.buffer(); let mut out = [0u8; 1024 * 5]; let mut out_len = 0; @@ -191,7 +194,7 @@ impl AesEcbCipher { } let out_len = out_len as usize; if out_len == 0 { - return Err(io::Error::new(io::ErrorKind::Other, "ciphertext len err")); + return Err(anyhow!("ciphertext len err")); } //密文 let ciphertext = &out[..out_len]; diff --git a/vnt/src/cipher/aes_ecb.rs b/vnt/src/cipher/aes_ecb/rs_aes_ecb.rs similarity index 82% rename from vnt/src/cipher/aes_ecb.rs rename to vnt/src/cipher/aes_ecb/rs_aes_ecb.rs index 364c605..5fd9485 100644 --- a/vnt/src/cipher/aes_ecb.rs +++ b/vnt/src/cipher/aes_ecb/rs_aes_ecb.rs @@ -1,7 +1,8 @@ +use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit}; +use anyhow::anyhow; + use crate::cipher::Finger; use crate::protocol::{NetPacket, HEAD_LEN}; -use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit}; -use std::io; type Aes128EcbEnc = ecb::Encryptor; type Aes128EcbDec = ecb::Decryptor; @@ -46,10 +47,10 @@ impl AesEcbCipher { pub fn decrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { if !net_packet.is_encrypt() { //未加密的数据直接丢弃 - return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + return Err(anyhow!("not encrypt")); } if let Some(finger) = &self.finger { @@ -62,18 +63,18 @@ impl AesEcbCipher { nonce_raw[11] = net_packet.source_ttl(); let len = net_packet.payload().len(); if len < 12 { - return Err(io::Error::new(io::ErrorKind::Other, "payload len <12")); + return Err(anyhow!("payload len <12")); } let secret_body = &net_packet.payload()[..len - 12]; let finger = finger.calculate_finger(&nonce_raw, secret_body); if &finger != &net_packet.payload()[len - 12..] { - return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + return Err(anyhow!("finger err")); } net_packet.set_data_len(net_packet.data_len() - finger.len())?; } if net_packet.payload().len() < 16 { log::error!("数据异常,长度{}小于{}", net_packet.payload().len(), 16); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } let mut out = [0u8; 1024 * 5]; let rs = match self.key { @@ -87,32 +88,29 @@ impl AesEcbCipher { //校验头部 let src_net_packet = NetPacket::new(buf)?; if src_net_packet.source() != net_packet.source() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.destination() != net_packet.destination() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.protocol() != net_packet.protocol() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.transport_protocol() != net_packet.transport_protocol() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.is_gateway() != net_packet.is_gateway() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.source_ttl() != net_packet.source_ttl() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } net_packet.set_data_len(buf.len())?; net_packet.set_payload(src_net_packet.payload())?; net_packet.set_encrypt_flag(false); Ok(()) } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("aes_ecb解密失败:{}", e), - )), + Err(e) => Err(anyhow!("aes_ecb解密失败:{}", e)), } } /// net_packet 必须预留足够长度 @@ -120,7 +118,7 @@ impl AesEcbCipher { pub fn encrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { let mut out = [0u8; 1024 * 5]; let rs = match self.key { AesEcbEnum::AES128ECB(key) => Aes128EcbEnc::new(&key.into()) @@ -152,10 +150,7 @@ impl AesEcbCipher { } Ok(()) } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("aes_ecb加密失败:{}", e), - )), + Err(e) => Err(anyhow!("aes_ecb加密失败:{}", e)), }; } } diff --git a/vnt/src/cipher/aes_gcm_cipher.rs b/vnt/src/cipher/aes_gcm/aes_gcm_cipher.rs similarity index 87% rename from vnt/src/cipher/aes_gcm_cipher.rs rename to vnt/src/cipher/aes_gcm/aes_gcm_cipher.rs index 9920c10..e261a49 100644 --- a/vnt/src/cipher/aes_gcm_cipher.rs +++ b/vnt/src/cipher/aes_gcm/aes_gcm_cipher.rs @@ -1,8 +1,7 @@ -use std::io; - use aes_gcm::aead::consts::{U12, U16}; use aes_gcm::aead::generic_array::GenericArray; use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag}; +use anyhow::anyhow; use rand::RngCore; use crate::cipher::finger::Finger; @@ -39,14 +38,14 @@ impl AesGcmCipher { pub fn decrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { if !net_packet.is_encrypt() { //未加密的数据直接丢弃 - return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + return Err(anyhow!("not encrypt")); } if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED { log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } let mut nonce_raw = [0; 12]; nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); @@ -62,7 +61,7 @@ impl AesGcmCipher { if let Some(finger) = &self.finger { let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body()); if &finger != secret_body.finger() { - return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + return Err(anyhow!("finger err")); } } let tag: GenericArray = Tag::clone_from_slice(tag); @@ -75,10 +74,7 @@ impl AesGcmCipher { } }; if let Err(e) = rs { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("解密失败:{}", e), - )); + return Err(anyhow!("解密失败:{}", e)); } net_packet.set_encrypt_flag(false); net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?; @@ -89,9 +85,9 @@ impl AesGcmCipher { pub fn encrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { if net_packet.reserve() < AES_GCM_ENCRYPTION_RESERVED { - return Err(io::Error::new(io::ErrorKind::Other, "too short")); + return Err(anyhow!("too short")); } let mut nonce_raw = [0; 12]; nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); @@ -123,10 +119,7 @@ impl AesGcmCipher { net_packet.set_encrypt_flag(true); Ok(()) } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("加密失败:{}", e), - )), + Err(e) => Err(anyhow!("加密失败:{}", e)), }; } } diff --git a/vnt/src/cipher/aes_gcm/mod.rs b/vnt/src/cipher/aes_gcm/mod.rs new file mode 100644 index 0000000..ade96e4 --- /dev/null +++ b/vnt/src/cipher/aes_gcm/mod.rs @@ -0,0 +1,9 @@ +#[cfg(feature = "ring-cipher")] +mod ring_aes_gcm_cipher; +#[cfg(feature = "ring-cipher")] +pub use ring_aes_gcm_cipher::*; + +#[cfg(not(feature = "ring-cipher"))] +mod aes_gcm_cipher; +#[cfg(not(feature = "ring-cipher"))] +pub use aes_gcm_cipher::*; diff --git a/vnt/src/cipher/ring_aes_gcm_cipher.rs b/vnt/src/cipher/aes_gcm/ring_aes_gcm_cipher.rs similarity index 86% rename from vnt/src/cipher/ring_aes_gcm_cipher.rs rename to vnt/src/cipher/aes_gcm/ring_aes_gcm_cipher.rs index bc65a18..4123d83 100644 --- a/vnt/src/cipher/ring_aes_gcm_cipher.rs +++ b/vnt/src/cipher/aes_gcm/ring_aes_gcm_cipher.rs @@ -1,9 +1,9 @@ -use crate::cipher::Finger; +use anyhow::anyhow; use rand::RngCore; use ring::aead; use ring::aead::{LessSafeKey, UnboundKey}; -use std::io; +use crate::cipher::Finger; use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED}; use crate::protocol::NetPacket; @@ -53,14 +53,14 @@ impl AesGcmCipher { pub fn decrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { if !net_packet.is_encrypt() { //未加密的数据直接丢弃 - return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + return Err(anyhow!("not encrypt")); } if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED { log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } let mut nonce_raw = [0; 12]; nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); @@ -74,7 +74,7 @@ impl AesGcmCipher { if let Some(finger) = &self.finger { let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body()); if &finger != secret_body.finger() { - return Err(io::Error::new(io::ErrorKind::Other, "ring aes finger err")); + return Err(anyhow!("ring aes finger err")); } } @@ -87,10 +87,7 @@ impl AesGcmCipher { } }; if let Err(e) = rs { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("解密失败:{}", e), - )); + return Err(anyhow!("解密失败:{}", e)); } net_packet.set_encrypt_flag(false); net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?; @@ -102,7 +99,7 @@ impl AesGcmCipher { pub fn encrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { let mut nonce_raw = [0; 12]; nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); @@ -128,10 +125,7 @@ impl AesGcmCipher { Ok(tag) => { let tag = tag.as_ref(); if tag.len() != 16 { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("加密tag长度错误:{}", tag.len()), - )); + return Err(anyhow!("加密tag长度错误:{}", tag.len())); } secret_body.set_tag(tag)?; if let Some(finger) = &self.finger { @@ -141,10 +135,7 @@ impl AesGcmCipher { net_packet.set_encrypt_flag(true); Ok(()) } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("加密失败:{}", e), - )), + Err(e) => Err(anyhow!("加密失败:{}", e)), }; } } diff --git a/vnt/src/cipher/chacha20/mod.rs b/vnt/src/cipher/chacha20/mod.rs new file mode 100644 index 0000000..b249c3a --- /dev/null +++ b/vnt/src/cipher/chacha20/mod.rs @@ -0,0 +1,2 @@ +mod rs_chacha20; +pub use rs_chacha20::*; diff --git a/vnt/src/cipher/chacha20/rs_chacha20.rs b/vnt/src/cipher/chacha20/rs_chacha20.rs new file mode 100644 index 0000000..5a78d9a --- /dev/null +++ b/vnt/src/cipher/chacha20/rs_chacha20.rs @@ -0,0 +1,114 @@ +use aes::cipher::Iv; +use anyhow::anyhow; +use chacha20::cipher::{Key, KeyIvInit, StreamCipher}; +use chacha20::ChaCha20; + +use crate::cipher::Finger; +use crate::protocol::body::ChaCah20SecretBody; +use crate::protocol::NetPacket; + +#[derive(Clone)] +pub struct ChaCha20Cipher { + key: [u8; 32], + pub(crate) finger: Option, +} + +impl ChaCha20Cipher { + pub fn new_256(key: [u8; 32], finger: Option) -> Self { + Self { key, finger } + } +} + +impl ChaCha20Cipher { + pub fn key(&self) -> &[u8] { + &self.key + } +} + +impl ChaCha20Cipher { + pub fn decrypt_ipv4 + AsMut<[u8]>>( + &self, + net_packet: &mut NetPacket, + ) -> anyhow::Result<()> { + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(anyhow!("not encrypt")); + } + let mut iv = [0; 12]; + iv[0..4].copy_from_slice(&net_packet.source().octets()); + iv[4..8].copy_from_slice(&net_packet.destination().octets()); + iv[8] = net_packet.protocol().into(); + iv[9] = net_packet.transport_protocol(); + iv[10] = net_packet.is_gateway() as u8; + iv[11] = net_packet.source_ttl(); + + let mut secret_body = + ChaCah20SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + if let Some(finger) = &self.finger { + let finger = finger.calculate_finger(&iv[..12], secret_body.en_body()); + if &finger != secret_body.finger() { + return Err(anyhow!("ChaCha20 finger err")); + } + } + + ChaCha20::new( + Key::::from_slice(&self.key), + Iv::::from_slice(&iv), + ) + .apply_keystream(secret_body.en_body_mut()); + let len = secret_body.en_body().len(); + net_packet.set_encrypt_flag(false); + net_packet.set_payload_len(len)?; + Ok(()) + } + pub fn encrypt_ipv4 + AsMut<[u8]>>( + &self, + net_packet: &mut NetPacket, + ) -> anyhow::Result<()> { + let data_len = net_packet.data_len(); + let mut iv = [0; 12]; + iv[0..4].copy_from_slice(&net_packet.source().octets()); + iv[4..8].copy_from_slice(&net_packet.destination().octets()); + iv[8] = net_packet.protocol().into(); + iv[9] = net_packet.transport_protocol(); + iv[10] = net_packet.is_gateway() as u8; + iv[11] = net_packet.source_ttl(); + if let Some(_) = &self.finger { + net_packet.set_data_len(data_len + 12)?; + } + let mut secret_body = + ChaCah20SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + ChaCha20::new( + Key::::from_slice(&self.key), + Iv::::from_slice(&iv), + ) + .apply_keystream(secret_body.en_body_mut()); + if let Some(finger) = &self.finger { + let finger = finger.calculate_finger(&iv[..12], secret_body.en_body_mut()); + let mut secret_body = ChaCah20SecretBody::new(net_packet.payload_mut(), true)?; + secret_body.set_finger(&finger)?; + } + + net_packet.set_encrypt_flag(true); + Ok(()) + } +} + +#[test] +fn test_chacha20() { + let d = ChaCha20Cipher::new_256([0; 32], Some(Finger::new("123"))); + let mut p = + NetPacket::new_encrypt([0; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).unwrap(); + let src = p.buffer().to_vec(); + d.encrypt_ipv4(&mut p).unwrap(); + d.decrypt_ipv4(&mut p).unwrap(); + assert_eq!(p.buffer(), &src); + + let d = ChaCha20Cipher::new_256([0; 32], None); + let mut p = + NetPacket::new_encrypt([0; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).unwrap(); + let src = p.buffer().to_vec(); + d.encrypt_ipv4(&mut p).unwrap(); + d.decrypt_ipv4(&mut p).unwrap(); + assert_eq!(p.buffer(), &src); +} diff --git a/vnt/src/cipher/chacha20_poly1305/mod.rs b/vnt/src/cipher/chacha20_poly1305/mod.rs new file mode 100644 index 0000000..1b4260f --- /dev/null +++ b/vnt/src/cipher/chacha20_poly1305/mod.rs @@ -0,0 +1,9 @@ +#[cfg(feature = "ring-cipher")] +mod ring_chacha20_poly1305; +#[cfg(feature = "ring-cipher")] +pub use ring_chacha20_poly1305::*; + +#[cfg(not(feature = "ring-cipher"))] +mod rs_chacha20_poly1305; +#[cfg(not(feature = "ring-cipher"))] +pub use rs_chacha20_poly1305::*; diff --git a/vnt/src/cipher/chacha20_poly1305/ring_chacha20_poly1305.rs b/vnt/src/cipher/chacha20_poly1305/ring_chacha20_poly1305.rs new file mode 100644 index 0000000..f27e11a --- /dev/null +++ b/vnt/src/cipher/chacha20_poly1305/ring_chacha20_poly1305.rs @@ -0,0 +1,129 @@ +use anyhow::anyhow; + +use ring::aead; +use ring::aead::{LessSafeKey, UnboundKey}; + +use crate::cipher::Finger; +use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED}; +use crate::protocol::NetPacket; + +#[derive(Clone)] +pub struct ChaCha20Poly1305Cipher { + key: Vec, + pub(crate) cipher: LessSafeKey, + pub(crate) finger: Option, +} + +impl ChaCha20Poly1305Cipher { + pub fn new_256(key: [u8; 32], finger: Option) -> Self { + let cipher = LessSafeKey::new(UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap()); + Self { + key: key.to_vec(), + cipher, + finger, + } + } +} + +impl ChaCha20Poly1305Cipher { + pub fn key(&self) -> &[u8] { + &self.key + } +} + +impl ChaCha20Poly1305Cipher { + pub fn decrypt_ipv4 + AsMut<[u8]>>( + &self, + net_packet: &mut NetPacket, + ) -> anyhow::Result<()> { + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(anyhow!("not encrypt")); + } + if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED { + log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED); + return Err(anyhow!("data err")); + } + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + let nonce = aead::Nonce::assume_unique_for_key(nonce_raw); + let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + if let Some(finger) = &self.finger { + let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body()); + if &finger != secret_body.finger() { + return Err(anyhow!("ring CHACHA20_POLY1305 finger err")); + } + } + + let rs = self + .cipher + .open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut()); + if let Err(e) = rs { + return Err(anyhow!("ring CHACHA20_POLY1305 解密失败:{}", e)); + } + net_packet.set_encrypt_flag(false); + net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?; + return Ok(()); + } + /// net_packet 必须预留足够长度 + /// data_len是有效载荷的长度 + /// 返回加密后载荷的长度 + pub fn encrypt_ipv4 + AsMut<[u8]>>( + &self, + net_packet: &mut NetPacket, + ) -> anyhow::Result<()> { + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + let nonce = aead::Nonce::assume_unique_for_key(nonce_raw); + let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED; + net_packet.set_data_len(data_len)?; + let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + let rs = self.cipher.seal_in_place_separate_tag( + nonce, + aead::Aad::empty(), + secret_body.body_mut(), + ); + return match rs { + Ok(tag) => { + let tag = tag.as_ref(); + if tag.len() != 16 { + return Err(anyhow!("加密tag长度错误:{}", tag.len())); + } + secret_body.set_tag(tag)?; + if let Some(finger) = &self.finger { + let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body()); + secret_body.set_finger(&finger)?; + } + net_packet.set_encrypt_flag(true); + Ok(()) + } + Err(e) => Err(anyhow!("ring CHACHA20_POLY1305 加密失败:{}", e)), + }; + } +} + +#[test] +fn test_ring_chacha20_poly1305() { + let d = ChaCha20Poly1305Cipher::new_256([0; 32], Some(Finger::new("123"))); + let mut p = NetPacket::new_encrypt([0; 73]).unwrap(); + let src = p.buffer().to_vec(); + d.encrypt_ipv4(&mut p).unwrap(); + d.decrypt_ipv4(&mut p).unwrap(); + assert_eq!(p.buffer(), &src); + let d = ChaCha20Poly1305Cipher::new_256([0; 32], None); + let mut p = NetPacket::new_encrypt([0; 73]).unwrap(); + let src = p.buffer().to_vec(); + d.encrypt_ipv4(&mut p).unwrap(); + d.decrypt_ipv4(&mut p).unwrap(); + assert_eq!(p.buffer(), &src); +} diff --git a/vnt/src/cipher/chacha20_poly1305/rs_chacha20_poly1305.rs b/vnt/src/cipher/chacha20_poly1305/rs_chacha20_poly1305.rs new file mode 100644 index 0000000..9764f70 --- /dev/null +++ b/vnt/src/cipher/chacha20_poly1305/rs_chacha20_poly1305.rs @@ -0,0 +1,121 @@ +use anyhow::anyhow; +use chacha20poly1305::aead::{Nonce, Tag}; +use chacha20poly1305::{AeadInPlace, ChaCha20Poly1305, Key, KeyInit}; + +use crate::cipher::Finger; +use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED}; +use crate::protocol::NetPacket; + +#[derive(Clone)] +pub struct ChaCha20Poly1305Cipher { + key: Vec, + pub(crate) cipher: ChaCha20Poly1305, + pub(crate) finger: Option, +} + +impl ChaCha20Poly1305Cipher { + pub fn new_256(key: [u8; 32], finger: Option) -> Self { + let key: &Key = &key.into(); + let cipher = ChaCha20Poly1305::new(key); + Self { + key: key.to_vec(), + cipher, + finger, + } + } +} +impl ChaCha20Poly1305Cipher { + pub fn key(&self) -> &[u8] { + &self.key + } +} + +impl ChaCha20Poly1305Cipher { + pub fn decrypt_ipv4 + AsMut<[u8]>>( + &self, + net_packet: &mut NetPacket, + ) -> anyhow::Result<()> { + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(anyhow!("not encrypt")); + } + if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED { + log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED); + return Err(anyhow!("data err")); + } + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + if let Some(finger) = &self.finger { + let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body()); + if &finger != secret_body.finger() { + return Err(anyhow!("rs CHACHA20_POLY1305 finger err")); + } + } + let nonce: Nonce = nonce_raw.into(); + let tag: Tag = + Tag::::from_slice(secret_body.tag()).clone(); + if let Err(e) = + self.cipher + .decrypt_in_place_detached(&nonce, &[], secret_body.body_mut(), &tag) + { + return Err(anyhow!("rs CHACHA20_POLY1305 decrypt_ipv4 {:?}", e)); + } + net_packet.set_encrypt_flag(false); + net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?; + Ok(()) + } + /// net_packet 必须预留足够长度 + /// data_len是有效载荷的长度 + /// 返回加密后载荷的长度 + pub fn encrypt_ipv4 + AsMut<[u8]>>( + &self, + net_packet: &mut NetPacket, + ) -> anyhow::Result<()> { + let mut nonce_raw = [0; 12]; + nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); + nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce_raw[8] = net_packet.protocol().into(); + nonce_raw[9] = net_packet.transport_protocol(); + nonce_raw[10] = net_packet.is_gateway() as u8; + nonce_raw[11] = net_packet.source_ttl(); + let nonce = nonce_raw.into(); + let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED; + net_packet.set_data_len(data_len)?; + let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + let rs = self + .cipher + .encrypt_in_place_detached(&nonce, &[], secret_body.body_mut()); + return match rs { + Ok(tag) => { + let tag: &[u8] = tag.as_ref(); + if tag.len() != 16 { + return Err(anyhow!("加密tag长度错误:{}", tag.len(),)); + } + secret_body.set_tag(tag)?; + if let Some(finger) = &self.finger { + let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body()); + secret_body.set_finger(&finger)?; + } + net_packet.set_encrypt_flag(true); + Ok(()) + } + Err(e) => Err(anyhow!("rs CHACHA20_POLY1305 加密失败:{}", e)), + }; + } +} + +#[test] +fn test_rs_chacha20_poly1305() { + let d = ChaCha20Poly1305Cipher::new_256([0; 32], Some(Finger::new("123"))); + let mut p = NetPacket::new_encrypt([0; 73]).unwrap(); + let src = p.buffer().to_vec(); + d.encrypt_ipv4(&mut p).unwrap(); + d.decrypt_ipv4(&mut p).unwrap(); + assert_eq!(p.buffer(), &src); +} diff --git a/vnt/src/cipher/cipher.rs b/vnt/src/cipher/cipher.rs index 3ab71ff..3aba856 100644 --- a/vnt/src/cipher/cipher.rs +++ b/vnt/src/cipher/cipher.rs @@ -1,51 +1,42 @@ -#[cfg(feature = "aes_ecb")] -#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))] -use crate::cipher::aes_ecb::AesEcbCipher; use std::fmt::Display; +use std::str::FromStr; + +use anyhow::anyhow; +#[cfg(cipher)] +use sha2::Digest; #[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; +use crate::cipher::aes_ecb::AesEcbCipher; #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] -#[cfg(feature = "ring-cipher")] -use crate::cipher::ring_aes_gcm_cipher::AesGcmCipher; +use crate::cipher::aes_gcm::AesGcmCipher; +#[cfg(feature = "chacha20_poly1305")] +use crate::cipher::chacha20::ChaCha20Cipher; +#[cfg(feature = "chacha20_poly1305")] +use crate::cipher::chacha20_poly1305::ChaCha20Poly1305Cipher; #[cfg(feature = "sm4_cbc")] use crate::cipher::sm4_cbc::Sm4CbcCipher; -#[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" -))] +use crate::cipher::xor::XORCipher; +#[cfg(cipher)] use crate::cipher::Finger; use crate::protocol::NetPacket; -#[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" -))] -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 = "chacha20_poly1305")] + Chacha20Poly1305, + #[cfg(feature = "chacha20_poly1305")] + Chacha20, #[cfg(feature = "aes_cbc")] AesCbc, #[cfg(feature = "aes_ecb")] AesEcb, #[cfg(feature = "sm4_cbc")] Sm4Cbc, + Xor, None, } @@ -54,61 +45,55 @@ impl Display for CipherModel { let str = match self { #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] CipherModel::AesGcm => "aes_gcm".to_string(), + #[cfg(feature = "chacha20_poly1305")] + CipherModel::Chacha20Poly1305 => "chacha20_poly1305".to_string(), + #[cfg(feature = "chacha20_poly1305")] + CipherModel::Chacha20 => "chacha20".to_string(), #[cfg(feature = "aes_cbc")] CipherModel::AesCbc => "aes_cbc".to_string(), #[cfg(feature = "aes_ecb")] CipherModel::AesEcb => "aes_ecb".to_string(), #[cfg(feature = "sm4_cbc")] CipherModel::Sm4Cbc => "sm4_cbc".to_string(), + CipherModel::Xor => "xor".to_string(), CipherModel::None => "none".to_string(), }; write!(f, "{}", str) } } + impl FromStr for CipherModel { type Err = String; fn from_str(s: &str) -> Result { - #[cfg(not(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - )))] - return Err(format!("not match '{}', no encrypt", s)); - #[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - ))] match s.to_lowercase().trim() { #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] "aes_gcm" => Ok(CipherModel::AesGcm), + #[cfg(feature = "chacha20_poly1305")] + "chacha20_poly1305" => Ok(CipherModel::Chacha20Poly1305), + #[cfg(feature = "chacha20_poly1305")] + "chacha20" => Ok(CipherModel::Chacha20), #[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), + "xor" => Ok(CipherModel::Xor), _ => { let mut enums = String::new(); #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] enums.push_str("/aes_gcm"); + #[cfg(feature = "chacha20_poly1305")] + enums.push_str("/chacha20_poly1305/chacha20"); #[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)) + enums.push_str("/xor"); + Err(format!("not match '{}', enum:{}", s, &enums[1..])) } } } @@ -118,49 +103,37 @@ impl FromStr for CipherModel { pub enum Cipher { #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] AesGcm((AesGcmCipher, Vec)), + #[cfg(feature = "chacha20_poly1305")] + Chacha20Poly1305(ChaCha20Poly1305Cipher), + #[cfg(feature = "chacha20_poly1305")] + Chacha20(ChaCha20Cipher), #[cfg(feature = "aes_cbc")] AesCbc(AesCbcCipher), #[cfg(feature = "aes_ecb")] AesEcb(AesEcbCipher), #[cfg(feature = "sm4_cbc")] Sm4Cbc(Sm4CbcCipher), + Xor(XORCipher), None, } + impl Cipher { - #[cfg(not(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - )))] - pub fn new_password( - _model: CipherModel, - _password: Option, - _token: Option, - ) -> Self { - Cipher::None - } - #[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - ))] pub fn new_password( model: CipherModel, password: Option, token: Option, ) -> Self { - let finger = token.map(|token| Finger::new(&token)); if let Some(password) = password { - let mut hasher = sha2::Sha256::new(); - hasher.update(password.as_bytes()); - let key: [u8; 32] = hasher.finalize().into(); + #[cfg(cipher)] + let key: [u8; 32] = { + let mut hasher = sha2::Sha256::new(); + hasher.update(password.as_bytes()); + hasher.finalize().into() + }; match model { #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] CipherModel::AesGcm => { + let finger = token.map(|token| Finger::new(&token)); if password.len() < 8 { let aes = AesGcmCipher::new_128(key[..16].try_into().unwrap(), finger); Cipher::AesGcm((aes, key[..16].to_vec())) @@ -169,8 +142,21 @@ impl Cipher { Cipher::AesGcm((aes, key.to_vec())) } } + #[cfg(feature = "chacha20_poly1305")] + CipherModel::Chacha20Poly1305 => { + let finger = token.map(|token| Finger::new(&token)); + let chacha = ChaCha20Poly1305Cipher::new_256(key, finger); + Cipher::Chacha20Poly1305(chacha) + } + #[cfg(feature = "chacha20_poly1305")] + CipherModel::Chacha20 => { + let finger = token.map(|token| Finger::new(&token)); + let chacha = ChaCha20Cipher::new_256(key, finger); + Cipher::Chacha20(chacha) + } #[cfg(feature = "aes_cbc")] CipherModel::AesCbc => { + let finger = token.map(|token| Finger::new(&token)); if password.len() < 8 { let aes = AesCbcCipher::new_128(key[..16].try_into().unwrap(), finger); Cipher::AesCbc(aes) @@ -181,6 +167,7 @@ impl Cipher { } #[cfg(feature = "aes_ecb")] CipherModel::AesEcb => { + let finger = token.map(|token| Finger::new(&token)); if password.len() < 8 { let aes = AesEcbCipher::new_128(key[..16].try_into().unwrap(), finger); Cipher::AesEcb(aes) @@ -191,126 +178,97 @@ impl Cipher { } #[cfg(feature = "sm4_cbc")] CipherModel::Sm4Cbc => { + let finger = token.map(|token| Finger::new(&token)); let aes = Sm4CbcCipher::new_128(key[..16].try_into().unwrap(), finger); Cipher::Sm4Cbc(aes) } + CipherModel::Xor => { + let _token = token; + Cipher::Xor(XORCipher::new_256(crate::cipher::xor::simple_hash( + &password, + ))) + } CipherModel::None => Cipher::None, } } else { Cipher::None } } - #[cfg(not(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - )))] - pub fn new_key(_key: [u8; 32], _token: String) -> io::Result { - Err(io::Error::new(io::ErrorKind::Other, "key error")) + #[cfg(not(any(feature = "aes_gcm", feature = "server_encrypt")))] + pub fn new_key(_key: [u8; 32], _token: String) -> anyhow::Result { + Err(anyhow!("key error")) } - #[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - ))] - pub fn new_key(key: [u8; 32], token: String) -> io::Result { + #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] + pub fn new_key(key: [u8; 32], token: String) -> anyhow::Result { 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()))) } - _ => Err(io::Error::new(io::ErrorKind::Other, "key error")), + _ => Err(anyhow!("key error")), } } pub fn decrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::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 = "chacha20_poly1305")] + Cipher::Chacha20Poly1305(chacha20poly1305) => chacha20poly1305.decrypt_ipv4(net_packet), + #[cfg(feature = "chacha20_poly1305")] + Cipher::Chacha20(chacha20) => chacha20.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::Xor(xor) => xor.decrypt_ipv4(net_packet), Cipher::None => { if net_packet.is_encrypt() { - return Err(io::Error::new(io::ErrorKind::Other, "not key")); + return Err(anyhow!("not key")); } Ok(()) } } } - #[cfg(not(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - )))] - pub fn encrypt_ipv4 + AsMut<[u8]>>( - &self, - _net_packet: &mut NetPacket, - ) -> io::Result<()> { - Ok(()) - } - #[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - ))] pub fn encrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { match self { #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] Cipher::AesGcm((aes_gcm, _)) => aes_gcm.encrypt_ipv4(net_packet), + #[cfg(feature = "chacha20_poly1305")] + Cipher::Chacha20Poly1305(chacha20poly1305) => chacha20poly1305.encrypt_ipv4(net_packet), + #[cfg(feature = "chacha20_poly1305")] + Cipher::Chacha20(chacha20) => chacha20.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::Xor(xor) => xor.encrypt_ipv4(net_packet), Cipher::None => Ok(()), } } - #[cfg(not(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - )))] + #[cfg(not(cipher))] pub fn check_finger + AsMut<[u8]>>( &self, _net_packet: &NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { Ok(()) } - #[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" - ))] - pub fn check_finger>(&self, net_packet: &NetPacket) -> io::Result<()> { + #[cfg(cipher)] + pub fn check_finger>(&self, net_packet: &NetPacket) -> anyhow::Result<()> { match self { #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] Cipher::AesGcm((aes_gcm, _)) => aes_gcm @@ -318,6 +276,18 @@ impl Cipher { .as_ref() .map(|f| f.check_finger(net_packet)) .unwrap_or(Ok(())), + #[cfg(feature = "chacha20_poly1305")] + Cipher::Chacha20Poly1305(chacha20poly1305) => chacha20poly1305 + .finger + .as_ref() + .map(|f| f.check_finger(net_packet)) + .unwrap_or(Ok(())), + #[cfg(feature = "chacha20_poly1305")] + Cipher::Chacha20(chacha20) => chacha20 + .finger + .as_ref() + .map(|f| f.check_finger(net_packet)) + .unwrap_or(Ok(())), #[cfg(feature = "aes_cbc")] Cipher::AesCbc(aes_cbc) => aes_cbc .finger @@ -336,6 +306,7 @@ impl Cipher { .as_ref() .map(|f| f.check_finger(net_packet)) .unwrap_or(Ok(())), + Cipher::Xor(_) => Ok(()), Cipher::None => Ok(()), } } @@ -343,12 +314,17 @@ impl Cipher { match self { #[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] Cipher::AesGcm((_, key)) => Some(key), + #[cfg(feature = "chacha20_poly1305")] + Cipher::Chacha20Poly1305(chacha20poly1305) => Some(chacha20poly1305.key()), + #[cfg(feature = "chacha20_poly1305")] + Cipher::Chacha20(chacha20) => Some(chacha20.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::Xor(xor) => Some(xor.key()), Cipher::None => None, } } diff --git a/vnt/src/cipher/finger.rs b/vnt/src/cipher/finger.rs index acad057..73d6dc3 100644 --- a/vnt/src/cipher/finger.rs +++ b/vnt/src/cipher/finger.rs @@ -1,4 +1,4 @@ -use std::io; +use anyhow::anyhow; use sha2::Digest; @@ -16,15 +16,15 @@ impl Finger { let hash: [u8; 32] = hasher.finalize().into(); Finger { hash } } - pub fn check_finger>(&self, net_packet: &NetPacket) -> io::Result<()> { + pub fn check_finger>(&self, net_packet: &NetPacket) -> anyhow::Result<()> { if !net_packet.is_encrypt() { //未加密的数据直接丢弃 - return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + return Err(anyhow!("not encrypt")); } let payload_len = net_packet.payload().len(); if payload_len < 12 { log::error!("数据异常,长度小于{}", 12); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } let mut nonce_raw = [0; 12]; nonce_raw[0..4].copy_from_slice(&net_packet.source().octets()); @@ -36,7 +36,7 @@ impl Finger { let payload = net_packet.payload(); let finger = self.calculate_finger(&nonce_raw, &payload[..payload_len - 12]); if &finger[..] != &payload[payload_len - 12..] { - return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + return Err(anyhow!("finger err")); } Ok(()) } diff --git a/vnt/src/cipher/mod.rs b/vnt/src/cipher/mod.rs index cc31860..91a79a3 100644 --- a/vnt/src/cipher/mod.rs +++ b/vnt/src/cipher/mod.rs @@ -1,40 +1,31 @@ -#[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; -#[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" -))] +#[cfg(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; -#[cfg(feature = "sm4_cbc")] -mod sm4_cbc; pub use cipher::Cipher; pub use cipher::CipherModel; -#[cfg(any( - feature = "aes_gcm", - feature = "server_encrypt", - feature = "aes_cbc", - feature = "aes_ecb", - feature = "sm4_cbc" -))] +#[cfg(cipher)] pub use finger::Finger; #[cfg(feature = "server_encrypt")] mod rsa_cipher; #[cfg(feature = "server_encrypt")] pub use rsa_cipher::RsaCipher; + +#[cfg(any(feature = "aes_gcm", feature = "server_encrypt"))] +mod aes_gcm; + +#[cfg(feature = "chacha20_poly1305")] +mod chacha20; +#[cfg(feature = "chacha20_poly1305")] +mod chacha20_poly1305; + +#[cfg(feature = "aes_ecb")] +mod aes_ecb; + +#[cfg(feature = "aes_cbc")] +mod aes_cbc; + +#[cfg(feature = "sm4_cbc")] +mod sm4_cbc; + +mod xor; diff --git a/vnt/src/cipher/sm4_cbc/mod.rs b/vnt/src/cipher/sm4_cbc/mod.rs new file mode 100644 index 0000000..77a92eb --- /dev/null +++ b/vnt/src/cipher/sm4_cbc/mod.rs @@ -0,0 +1,2 @@ +mod rs_sm4_cbc; +pub use rs_sm4_cbc::*; diff --git a/vnt/src/cipher/sm4_cbc.rs b/vnt/src/cipher/sm4_cbc/rs_sm4_cbc.rs similarity index 81% rename from vnt/src/cipher/sm4_cbc.rs rename to vnt/src/cipher/sm4_cbc/rs_sm4_cbc.rs index 0c302a5..68b1615 100644 --- a/vnt/src/cipher/sm4_cbc.rs +++ b/vnt/src/cipher/sm4_cbc/rs_sm4_cbc.rs @@ -1,9 +1,9 @@ use crate::cipher::Finger; use crate::protocol::{NetPacket, HEAD_LEN}; +use anyhow::anyhow; use libsm::sm4::cipher_mode::CipherMode; use libsm::sm4::Sm4CipherMode; use rand::RngCore; -use std::io; pub struct Sm4CbcCipher { key: [u8; 16], @@ -41,10 +41,10 @@ impl Sm4CbcCipher { pub fn decrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { if !net_packet.is_encrypt() { //未加密的数据直接丢弃 - return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + return Err(anyhow!("not encrypt")); } if let Some(finger) = &self.finger { @@ -57,12 +57,12 @@ impl Sm4CbcCipher { nonce_raw[11] = net_packet.source_ttl(); let len = net_packet.payload().len(); if len < 12 { - return Err(io::Error::new(io::ErrorKind::Other, "payload len <12")); + return Err(anyhow!("payload len <12")); } let secret_body = &net_packet.payload()[..len - 12]; let finger = finger.calculate_finger(&nonce_raw, secret_body); if &finger != &net_packet.payload()[len - 12..] { - return Err(io::Error::new(io::ErrorKind::Other, "finger err")); + return Err(anyhow!("finger err")); } net_packet.set_data_len(net_packet.data_len() - finger.len())?; } @@ -70,7 +70,7 @@ impl Sm4CbcCipher { let len = payload.len(); if len < 16 || len > 1024 * 4 { log::error!("数据异常,长度{}小于16或大于4096", len); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } let mut out = [0u8; 1024 * 4]; let data = &payload[..len - 16]; @@ -79,32 +79,29 @@ impl Sm4CbcCipher { Ok(len) => { let src_net_packet = NetPacket::new(&out[..len])?; if src_net_packet.source() != net_packet.source() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.destination() != net_packet.destination() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.protocol() != net_packet.protocol() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.transport_protocol() != net_packet.transport_protocol() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.is_gateway() != net_packet.is_gateway() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } if src_net_packet.source_ttl() != net_packet.source_ttl() { - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } net_packet.set_data_len(len)?; net_packet.set_payload(src_net_packet.payload())?; net_packet.set_encrypt_flag(false); Ok(()) } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("sm4_cbc解密失败:{}", e), - )), + Err(e) => Err(anyhow!("sm4_cbc解密失败:{}", e)), } } /// net_packet 必须预留足够长度 @@ -112,7 +109,7 @@ impl Sm4CbcCipher { pub fn encrypt_ipv4 + AsMut<[u8]>>( &self, net_packet: &mut NetPacket, - ) -> io::Result<()> { + ) -> anyhow::Result<()> { let mut out = [0u8; 1024 * 4]; let mut iv = [0u8; 16]; rand::thread_rng().fill_bytes(&mut iv); @@ -121,7 +118,7 @@ impl Sm4CbcCipher { "数据异常,长度{}大于1024 * 4 - 32", net_packet.buffer().len() ); - return Err(io::Error::new(io::ErrorKind::Other, "data err")); + return Err(anyhow!("data err")); } match self.cipher.encrypt(net_packet.buffer(), &iv, &mut out) { Ok(len) => { @@ -146,10 +143,7 @@ impl Sm4CbcCipher { net_packet.set_encrypt_flag(true); Ok(()) } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("sm4_cbc加密失败:{}", e), - )), + Err(e) => Err(anyhow!("sm4_cbc加密失败:{}", e)), } } } diff --git a/vnt/src/cipher/xor/mod.rs b/vnt/src/cipher/xor/mod.rs new file mode 100644 index 0000000..fe38376 --- /dev/null +++ b/vnt/src/cipher/xor/mod.rs @@ -0,0 +1,2 @@ +mod xor; +pub use xor::*; diff --git a/vnt/src/cipher/xor/xor.rs b/vnt/src/cipher/xor/xor.rs new file mode 100644 index 0000000..0d804b1 --- /dev/null +++ b/vnt/src/cipher/xor/xor.rs @@ -0,0 +1,88 @@ +use anyhow::anyhow; + +use crate::protocol::NetPacket; + +pub fn simple_hash(input: &str) -> [u8; 32] { + let mut result = [0u8; 32]; + let bytes = input.as_bytes(); + for (index, v) in result.iter_mut().enumerate() { + *v = bytes[index % bytes.len()]; + } + + let mut state = 0u8; + + for (i, &byte) in bytes.iter().enumerate() { + let combined = byte.wrapping_add(state).rotate_left((i % 8) as u32); + result[i % 32] ^= combined; + state = state.wrapping_add(byte).rotate_left(3); + } + + for i in 0..32 { + result[i] = result[i] + .rotate_left((result[(i + 1) % 32] % 8) as u32) + .wrapping_add(state); + state = state.wrapping_add(result[i]).rotate_left(3); + } + + result +} + +#[derive(Clone)] +pub struct XORCipher { + key: [u8; 32], +} + +impl XORCipher { + pub fn new_256(key: [u8; 32]) -> Self { + Self { key } + } +} + +impl XORCipher { + pub fn key(&self) -> &[u8] { + &self.key + } +} + +impl XORCipher { + pub fn decrypt_ipv4 + AsMut<[u8]>>( + &self, + net_packet: &mut NetPacket, + ) -> anyhow::Result<()> { + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(anyhow!("not encrypt")); + } + let key = &self.key; + net_packet + .payload_mut() + .iter_mut() + .enumerate() + .for_each(|(i, byte)| *byte = *byte ^ key[i & 31]); + net_packet.set_encrypt_flag(false); + Ok(()) + } + pub fn encrypt_ipv4 + AsMut<[u8]>>( + &self, + net_packet: &mut NetPacket, + ) -> anyhow::Result<()> { + net_packet.set_encrypt_flag(true); + let key = &self.key; + net_packet + .payload_mut() + .iter_mut() + .enumerate() + .for_each(|(i, byte)| *byte = *byte ^ key[i & 31]); + Ok(()) + } +} + +#[test] +fn test_xor() { + let d = XORCipher::new_256(simple_hash("password")); + let mut p = NetPacket::new_encrypt([0; 1000]).unwrap(); + let src = p.buffer().to_vec(); + d.encrypt_ipv4(&mut p).unwrap(); + d.decrypt_ipv4(&mut p).unwrap(); + assert_eq!(p.buffer(), &src) +}