From 60ba3c64b2808a33f6dca3df7fcc5f881212e0e7 Mon Sep 17 00:00:00 2001 From: lbl8603 <49143209+lbl8603@users.noreply.github.com> Date: Tue, 4 Jun 2024 23:12:51 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8A=A0=E5=AF=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnt/src/cipher/aes_cbc/rs_aes_cbc.rs | 29 +- vnt/src/cipher/aes_ecb/openssl_aes_ecb.rs | 18 +- vnt/src/cipher/aes_ecb/rs_aes_ecb.rs | 16 +- vnt/src/cipher/aes_gcm/aes_gcm_cipher.rs | 35 +- vnt/src/cipher/aes_gcm/ring_aes_gcm_cipher.rs | 35 +- vnt/src/cipher/chacha20/rs_chacha20.rs | 57 ++- .../ring_chacha20_poly1305.rs | 60 ++-- .../chacha20_poly1305/rs_chacha20_poly1305.rs | 71 ++-- vnt/src/cipher/finger.rs | 25 ++ vnt/src/cipher/sm4_cbc/rs_sm4_cbc.rs | 16 +- vnt/src/protocol/body.rs | 334 +++++++++++++----- 11 files changed, 439 insertions(+), 257 deletions(-) diff --git a/vnt/src/cipher/aes_cbc/rs_aes_cbc.rs b/vnt/src/cipher/aes_cbc/rs_aes_cbc.rs index b16d33a..c765121 100644 --- a/vnt/src/cipher/aes_cbc/rs_aes_cbc.rs +++ b/vnt/src/cipher/aes_cbc/rs_aes_cbc.rs @@ -59,12 +59,7 @@ impl AesCbcCipher { return Err(anyhow!("aes_cbc data err")); } let mut iv = [0; 16]; - 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(); + iv[0..12].copy_from_slice(&net_packet.head_tag()); if let Some(finger) = &self.finger { iv[12..16].copy_from_slice(&finger.hash[0..4]); } @@ -102,12 +97,7 @@ impl AesCbcCipher { ) -> anyhow::Result<()> { let data_len = net_packet.data_len(); let mut iv = [0; 16]; - 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(); + iv[0..12].copy_from_slice(&net_packet.head_tag()); if let Some(finger) = &self.finger { iv[12..16].copy_from_slice(&finger.hash[0..4]); net_packet.set_data_len(data_len + 16)?; @@ -146,3 +136,18 @@ impl AesCbcCipher { }; } } +#[test] +fn test_aes_cbc() { + let d = AesCbcCipher::new_128([0; 16], Some(Finger::new("123"))); + let mut p = NetPacket::new_encrypt([0; 100]).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 = AesCbcCipher::new_128([0; 16], None); + let mut p = NetPacket::new_encrypt([0; 100]).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/aes_ecb/openssl_aes_ecb.rs b/vnt/src/cipher/aes_ecb/openssl_aes_ecb.rs index 649fa04..338865e 100644 --- a/vnt/src/cipher/aes_ecb/openssl_aes_ecb.rs +++ b/vnt/src/cipher/aes_ecb/openssl_aes_ecb.rs @@ -110,13 +110,7 @@ impl AesEcbCipher { } if let Some(finger) = &self.finger { - 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_raw = net_packet.head_tag(); let len = net_packet.payload().len(); if len < 12 { return Err(anyhow!("data len err")); @@ -202,13 +196,7 @@ impl AesEcbCipher { net_packet.payload_mut().copy_from_slice(ciphertext); net_packet.set_encrypt_flag(true); if let Some(finger) = &self.finger { - 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_raw = net_packet.head_tag(); let finger = finger.calculate_finger(&nonce_raw, ciphertext); let src_data_len = net_packet.data_len(); //设置实际长度 @@ -224,6 +212,8 @@ impl AesEcbCipher { fn test_openssl_aes_ecb() { let d = AesEcbCipher::new_128([0; 16], Some(Finger::new("123"))); let mut p = NetPacket::new_encrypt([0; 100]).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/aes_ecb/rs_aes_ecb.rs b/vnt/src/cipher/aes_ecb/rs_aes_ecb.rs index 5fd9485..ab68703 100644 --- a/vnt/src/cipher/aes_ecb/rs_aes_ecb.rs +++ b/vnt/src/cipher/aes_ecb/rs_aes_ecb.rs @@ -54,13 +54,7 @@ impl AesEcbCipher { } if let Some(finger) = &self.finger { - 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_raw = net_packet.head_tag(); let len = net_packet.payload().len(); if len < 12 { return Err(anyhow!("payload len <12")); @@ -134,13 +128,7 @@ impl AesEcbCipher { net_packet.set_encrypt_flag(true); if let Some(finger) = &self.finger { - 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_raw = net_packet.head_tag(); let finger = finger.calculate_finger(&nonce_raw, buf); let src_data_len = net_packet.data_len(); //设置实际长度 diff --git a/vnt/src/cipher/aes_gcm/aes_gcm_cipher.rs b/vnt/src/cipher/aes_gcm/aes_gcm_cipher.rs index e261a49..3b2ac78 100644 --- a/vnt/src/cipher/aes_gcm/aes_gcm_cipher.rs +++ b/vnt/src/cipher/aes_gcm/aes_gcm_cipher.rs @@ -47,13 +47,7 @@ impl AesGcmCipher { 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_raw = net_packet.head_tag(); let nonce: &GenericArray = Nonce::from_slice(&nonce_raw); let mut secret_body = SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; @@ -89,13 +83,7 @@ impl AesGcmCipher { if net_packet.reserve() < AES_GCM_ENCRYPTION_RESERVED { return Err(anyhow!("too short")); } - 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_raw = net_packet.head_tag(); let nonce: &GenericArray = Nonce::from_slice(&nonce_raw); let data_len = net_packet.data_len() + AES_GCM_ENCRYPTION_RESERVED; net_packet.set_data_len(data_len)?; @@ -123,3 +111,22 @@ impl AesGcmCipher { }; } } + +#[test] +fn test_aes_gcm() { + let d = AesGcmCipher::new_256([0; 32], Some(Finger::new("123"))); + let mut p = + NetPacket::new_encrypt([1; 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 = AesGcmCipher::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/aes_gcm/ring_aes_gcm_cipher.rs b/vnt/src/cipher/aes_gcm/ring_aes_gcm_cipher.rs index 4123d83..fbea94a 100644 --- a/vnt/src/cipher/aes_gcm/ring_aes_gcm_cipher.rs +++ b/vnt/src/cipher/aes_gcm/ring_aes_gcm_cipher.rs @@ -62,13 +62,7 @@ impl AesGcmCipher { 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_raw = net_packet.head_tag(); 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 { @@ -100,13 +94,7 @@ impl AesGcmCipher { &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_raw = net_packet.head_tag(); 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)?; @@ -139,3 +127,22 @@ impl AesGcmCipher { }; } } + +#[test] +fn test_aes_gcm() { + let d = AesGcmCipher::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 = AesGcmCipher::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/rs_chacha20.rs b/vnt/src/cipher/chacha20/rs_chacha20.rs index 5a78d9a..3da6d7c 100644 --- a/vnt/src/cipher/chacha20/rs_chacha20.rs +++ b/vnt/src/cipher/chacha20/rs_chacha20.rs @@ -3,8 +3,11 @@ use anyhow::anyhow; use chacha20::cipher::{Key, KeyIvInit, StreamCipher}; use chacha20::ChaCha20; +use crate::cipher::finger::{gen_nonce, gen_random_nonce}; use crate::cipher::Finger; -use crate::protocol::body::ChaCah20SecretBody; +use crate::protocol::body::{ + IVSecretBody, SecretTail, SecretTailMut, FINGER_RESERVED, RANDOM_RESERVED, +}; use crate::protocol::NetPacket; #[derive(Clone)] @@ -34,29 +37,22 @@ impl ChaCha20Cipher { //未加密的数据直接丢弃 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 head_tag = net_packet.head_tag(); - let mut secret_body = - ChaCah20SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + let mut secret_body = IVSecretBody::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()); + let finger = finger.calculate_finger(&head_tag, secret_body.data()); if &finger != secret_body.finger() { return Err(anyhow!("ChaCha20 finger err")); } } - + gen_nonce(&mut head_tag, secret_body.random_buf()); ChaCha20::new( Key::::from_slice(&self.key), - Iv::::from_slice(&iv), + Iv::::from_slice(&head_tag), ) - .apply_keystream(secret_body.en_body_mut()); - let len = secret_body.en_body().len(); + .apply_keystream(secret_body.data_mut()); + let len = secret_body.data().len(); net_packet.set_encrypt_flag(false); net_packet.set_payload_len(len)?; Ok(()) @@ -66,29 +62,26 @@ impl ChaCha20Cipher { 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(); + let head_tag = net_packet.head_tag(); if let Some(_) = &self.finger { - net_packet.set_data_len(data_len + 12)?; + net_packet.set_data_len(data_len + RANDOM_RESERVED + FINGER_RESERVED)?; + } else { + net_packet.set_data_len(data_len + RANDOM_RESERVED)?; } - let mut secret_body = - ChaCah20SecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + let mut secret_body = IVSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + let mut nonce = head_tag; + secret_body.set_random(&gen_random_nonce(&mut nonce)); + ChaCha20::new( Key::::from_slice(&self.key), - Iv::::from_slice(&iv), + Iv::::from_slice(&nonce), ) - .apply_keystream(secret_body.en_body_mut()); + .apply_keystream(secret_body.data_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)?; + let finger = finger.calculate_finger(&head_tag, secret_body.data()); + let mut secret_body = IVSecretBody::new(net_packet.payload_mut(), true)?; secret_body.set_finger(&finger)?; } - net_packet.set_encrypt_flag(true); Ok(()) } @@ -98,7 +91,7 @@ impl ChaCha20Cipher { 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(); + NetPacket::new_encrypt([1; 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(); @@ -106,7 +99,7 @@ fn test_chacha20() { let d = ChaCha20Cipher::new_256([0; 32], None); let mut p = - NetPacket::new_encrypt([0; 13 + crate::protocol::body::ENCRYPTION_RESERVED]).unwrap(); + NetPacket::new_encrypt([2; 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(); diff --git a/vnt/src/cipher/chacha20_poly1305/ring_chacha20_poly1305.rs b/vnt/src/cipher/chacha20_poly1305/ring_chacha20_poly1305.rs index f27e11a..1759a3c 100644 --- a/vnt/src/cipher/chacha20_poly1305/ring_chacha20_poly1305.rs +++ b/vnt/src/cipher/chacha20_poly1305/ring_chacha20_poly1305.rs @@ -3,8 +3,11 @@ use anyhow::anyhow; use ring::aead; use ring::aead::{LessSafeKey, UnboundKey}; +use crate::cipher::finger::{gen_nonce, gen_random_nonce}; use crate::cipher::Finger; -use crate::protocol::body::{SecretBody, AES_GCM_ENCRYPTION_RESERVED}; +use crate::protocol::body::{ + AEADSecretBody, SecretTail, SecretTailMut, FINGER_RESERVED, RANDOM_RESERVED, TAG_RESERVED, +}; use crate::protocol::NetPacket; #[derive(Clone)] @@ -40,34 +43,29 @@ impl ChaCha20Poly1305Cipher { //未加密的数据直接丢弃 return Err(anyhow!("not encrypt")); } - if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED { - log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED); + if net_packet.payload().len() < TAG_RESERVED { + log::error!("数据异常,长度小于{}", TAG_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())?; + let mut head_tag = net_packet.head_tag(); + let mut secret_body = AEADSecretBody::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()); + let finger = finger.calculate_finger(&head_tag, secret_body.data_tag_mut()); if &finger != secret_body.finger() { return Err(anyhow!("ring CHACHA20_POLY1305 finger err")); } } - + gen_nonce(&mut head_tag, secret_body.random_buf()); + let nonce = aead::Nonce::assume_unique_for_key(head_tag); let rs = self .cipher - .open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut()); + .open_in_place(nonce, aead::Aad::empty(), secret_body.data_tag_mut()); if let Err(e) = rs { return Err(anyhow!("ring CHACHA20_POLY1305 解密失败:{}", e)); } + let len = secret_body.data().len(); net_packet.set_encrypt_flag(false); - net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?; + net_packet.set_payload_len(len)?; return Ok(()); } /// net_packet 必须预留足够长度 @@ -77,23 +75,23 @@ impl ChaCha20Poly1305Cipher { &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 head_tag = net_packet.head_tag(); + let data_len = net_packet.data_len(); + if self.finger.is_some() { + net_packet.set_data_len(data_len + TAG_RESERVED + RANDOM_RESERVED + FINGER_RESERVED)?; + } else { + net_packet.set_data_len(data_len + TAG_RESERVED + RANDOM_RESERVED)?; + } + let mut secret_body = AEADSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + let mut nonce = head_tag; + secret_body.set_random(&gen_random_nonce(&mut nonce)); + let nonce = aead::Nonce::assume_unique_for_key(nonce); let rs = self.cipher.seal_in_place_separate_tag( nonce, aead::Aad::empty(), - secret_body.body_mut(), + secret_body.data_mut(), ); - return match rs { + match rs { Ok(tag) => { let tag = tag.as_ref(); if tag.len() != 16 { @@ -101,14 +99,14 @@ impl ChaCha20Poly1305Cipher { } secret_body.set_tag(tag)?; if let Some(finger) = &self.finger { - let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body()); + let finger = finger.calculate_finger(&head_tag, secret_body.data_tag_mut()); secret_body.set_finger(&finger)?; } net_packet.set_encrypt_flag(true); Ok(()) } Err(e) => Err(anyhow!("ring CHACHA20_POLY1305 加密失败:{}", e)), - }; + } } } diff --git a/vnt/src/cipher/chacha20_poly1305/rs_chacha20_poly1305.rs b/vnt/src/cipher/chacha20_poly1305/rs_chacha20_poly1305.rs index 9764f70..39388db 100644 --- a/vnt/src/cipher/chacha20_poly1305/rs_chacha20_poly1305.rs +++ b/vnt/src/cipher/chacha20_poly1305/rs_chacha20_poly1305.rs @@ -1,11 +1,13 @@ +use crate::cipher::finger::{gen_nonce, gen_random_nonce}; +use crate::cipher::Finger; +use crate::protocol::body::{ + AEADSecretBody, SecretTail, SecretTailMut, FINGER_RESERVED, RANDOM_RESERVED, TAG_RESERVED, +}; +use crate::protocol::NetPacket; 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, @@ -24,6 +26,7 @@ impl ChaCha20Poly1305Cipher { } } } + impl ChaCha20Poly1305Cipher { pub fn key(&self) -> &[u8] { &self.key @@ -39,35 +42,31 @@ impl ChaCha20Poly1305Cipher { //未加密的数据直接丢弃 return Err(anyhow!("not encrypt")); } - if net_packet.payload().len() < AES_GCM_ENCRYPTION_RESERVED { - log::error!("数据异常,长度小于{}", AES_GCM_ENCRYPTION_RESERVED); + if net_packet.payload().len() < TAG_RESERVED { + log::error!("数据异常,长度小于{}", TAG_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())?; + let mut head_tag = net_packet.head_tag(); + let mut secret_body = AEADSecretBody::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()); + let finger = finger.calculate_finger(&head_tag, secret_body.data_tag_mut()); if &finger != secret_body.finger() { return Err(anyhow!("rs CHACHA20_POLY1305 finger err")); } } - let nonce: Nonce = nonce_raw.into(); + gen_nonce(&mut head_tag, secret_body.random_buf()); + let nonce: Nonce = head_tag.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) + .decrypt_in_place_detached(&nonce, &[], secret_body.data_mut(), &tag) { return Err(anyhow!("rs CHACHA20_POLY1305 decrypt_ipv4 {:?}", e)); } + let len = secret_body.data().len(); net_packet.set_encrypt_flag(false); - net_packet.set_data_len(net_packet.data_len() - AES_GCM_ENCRYPTION_RESERVED)?; + net_packet.set_payload_len(len)?; Ok(()) } /// net_packet 必须预留足够长度 @@ -77,21 +76,21 @@ impl ChaCha20Poly1305Cipher { &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 head_tag = net_packet.head_tag(); + let data_len = net_packet.data_len(); + if self.finger.is_some() { + net_packet.set_data_len(data_len + TAG_RESERVED + RANDOM_RESERVED + FINGER_RESERVED)?; + } else { + net_packet.set_data_len(data_len + TAG_RESERVED + RANDOM_RESERVED)?; + } + let mut secret_body = AEADSecretBody::new(net_packet.payload_mut(), self.finger.is_some())?; + let mut nonce = head_tag; + secret_body.set_random(&gen_random_nonce(&mut nonce)); + let nonce = nonce.into(); let rs = self .cipher - .encrypt_in_place_detached(&nonce, &[], secret_body.body_mut()); - return match rs { + .encrypt_in_place_detached(&nonce, &[], secret_body.data_mut()); + match rs { Ok(tag) => { let tag: &[u8] = tag.as_ref(); if tag.len() != 16 { @@ -99,14 +98,14 @@ impl ChaCha20Poly1305Cipher { } secret_body.set_tag(tag)?; if let Some(finger) = &self.finger { - let finger = finger.calculate_finger(&nonce_raw, secret_body.en_body()); + let finger = finger.calculate_finger(&head_tag, secret_body.data_tag_mut()); secret_body.set_finger(&finger)?; } net_packet.set_encrypt_flag(true); Ok(()) } Err(e) => Err(anyhow!("rs CHACHA20_POLY1305 加密失败:{}", e)), - }; + } } } @@ -118,4 +117,10 @@ fn test_rs_chacha20_poly1305() { 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/finger.rs b/vnt/src/cipher/finger.rs index 73d6dc3..f070a7a 100644 --- a/vnt/src/cipher/finger.rs +++ b/vnt/src/cipher/finger.rs @@ -1,4 +1,5 @@ use anyhow::anyhow; +use rand::RngCore; use sha2::Digest; @@ -49,3 +50,27 @@ impl Finger { return key[20..].try_into().unwrap(); } } +impl> NetPacket { + pub fn head_tag(&self) -> [u8; 12] { + let mut tag = [0; 12]; + tag[0..4].copy_from_slice(&self.buffer()[4..8]); + tag[4..8].copy_from_slice(&self.buffer()[8..12]); + tag[8] = self.protocol().into(); + tag[9] = self.transport_protocol(); + tag[10] = self.is_gateway() as u8; + tag[11] = self.source_ttl(); + tag + } +} +pub fn gen_nonce(tag: &mut [u8], random: &[u8]) { + tag[8] = random[0] ^ tag[8]; + tag[9] = random[1] ^ tag[9]; + tag[10] = random[2] ^ tag[10]; + tag[11] = random[3] ^ tag[11]; +} +pub fn gen_random_nonce(tag: &mut [u8; 12]) -> [u8; 4] { + let mut random = [0; 4]; + rand::thread_rng().fill_bytes(&mut random); + gen_nonce(tag, &random); + random +} diff --git a/vnt/src/cipher/sm4_cbc/rs_sm4_cbc.rs b/vnt/src/cipher/sm4_cbc/rs_sm4_cbc.rs index 68b1615..885749c 100644 --- a/vnt/src/cipher/sm4_cbc/rs_sm4_cbc.rs +++ b/vnt/src/cipher/sm4_cbc/rs_sm4_cbc.rs @@ -48,13 +48,7 @@ impl Sm4CbcCipher { } if let Some(finger) = &self.finger { - 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_raw = net_packet.head_tag(); let len = net_packet.payload().len(); if len < 12 { return Err(anyhow!("payload len <12")); @@ -126,13 +120,7 @@ impl Sm4CbcCipher { 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()); - 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_raw = net_packet.head_tag(); let finger = finger.calculate_finger(&nonce_raw, net_packet.payload()); let src_data_len = net_packet.data_len(); //设置实际长度 diff --git a/vnt/src/protocol/body.rs b/vnt/src/protocol/body.rs index bfa5fd2..07d39c0 100644 --- a/vnt/src/protocol/body.rs +++ b/vnt/src/protocol/body.rs @@ -4,6 +4,261 @@ pub const ENCRYPTION_RESERVED: usize = 16 + 32 + 12; pub const AES_GCM_ENCRYPTION_RESERVED: usize = 32; pub const RSA_ENCRYPTION_RESERVED: usize = 32; +pub const RANDOM_RESERVED: usize = 4; +pub const FINGER_RESERVED: usize = 12; +pub const TAG_RESERVED: usize = 16; + +/* ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| random(32) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| finger(32) | +| finger(32) | +| finger(32) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +pub trait SecretTail { + fn buffer(&self) -> &[u8]; + fn exist_finger(&self) -> bool; + fn random_buf(&self) -> &[u8] { + let buf = self.buffer(); + let mut end = buf.len(); + if self.exist_finger() { + end -= FINGER_RESERVED; + } + &buf[end - RANDOM_RESERVED..end] + } + fn finger(&self) -> &[u8] { + if self.exist_finger() { + let buf = self.buffer(); + let end = buf.len(); + &buf[end - FINGER_RESERVED..end] + } else { + &[] + } + } +} + +pub trait SecretTailMut: SecretTail { + fn buffer_mut(&mut self) -> &mut [u8]; + fn set_random(&mut self, random: &[u8]) { + let f = self.exist_finger(); + let buf = self.buffer_mut(); + let mut end = buf.len(); + if f { + end -= FINGER_RESERVED; + } + buf[end - RANDOM_RESERVED..end].copy_from_slice(random); + } + fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> { + if self.exist_finger() { + if finger.len() != FINGER_RESERVED { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "finger.len != 12", + )); + } + let buf = self.buffer_mut(); + let end = buf.len(); + buf[end - FINGER_RESERVED..end].copy_from_slice(finger); + Ok(()) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "not exist finger", + )) + } + } +} + +/* aead加密数据体 + 0 15 31 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 数据体 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | tag(32) | + | tag(32) | + | tag(32) | + | tag(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | random(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | finger(32) | + | finger(32) | + | finger(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + 注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger, + 确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹) +*/ +pub struct AEADSecretBody { + buffer: B, + exist_finger: bool, +} + +impl> AEADSecretBody { + pub fn new(buffer: B, exist_finger: bool) -> io::Result> { + let len = buffer.as_ref().len(); + let min_len = if exist_finger { + TAG_RESERVED + RANDOM_RESERVED + FINGER_RESERVED + } else { + TAG_RESERVED + RANDOM_RESERVED + }; + // 不能大于udp最大载荷长度 + if len < min_len || len > 65535 - 20 - 8 - 12 { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!("AEADSecretBody length overflow {}", len), + )); + } + Ok(AEADSecretBody { + buffer, + exist_finger, + }) + } + pub fn data(&self) -> &[u8] { + let mut end = self.buffer.as_ref().len() - TAG_RESERVED - RANDOM_RESERVED; + if self.exist_finger { + end -= FINGER_RESERVED; + } + &self.buffer.as_ref()[..end] + } + pub fn tag(&self) -> &[u8] { + let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED; + if self.exist_finger { + end -= FINGER_RESERVED; + } + &self.buffer.as_ref()[end - TAG_RESERVED..end] + } +} + +impl> SecretTail for AEADSecretBody { + #[inline] + fn buffer(&self) -> &[u8] { + self.buffer.as_ref() + } + #[inline] + fn exist_finger(&self) -> bool { + self.exist_finger + } +} + +impl + AsMut<[u8]>> SecretTailMut for AEADSecretBody { + #[inline] + fn buffer_mut(&mut self) -> &mut [u8] { + self.buffer.as_mut() + } +} + +impl + AsMut<[u8]>> AEADSecretBody { + /// 数据部分 + pub fn data_mut(&mut self) -> &mut [u8] { + let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED - TAG_RESERVED; + if self.exist_finger { + end -= FINGER_RESERVED; + } + &mut self.buffer.as_mut()[..end] + } + /// 数据和tag部分 + pub fn data_tag_mut(&mut self) -> &mut [u8] { + let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED; + if self.exist_finger { + end -= FINGER_RESERVED; + } + &mut self.buffer.as_mut()[..end] + } + pub fn set_tag(&mut self, tag: &[u8]) -> io::Result<()> { + if tag.len() != 16 { + return Err(io::Error::new(io::ErrorKind::InvalidData, "tag.len != 16")); + } + let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED; + if self.exist_finger { + end -= FINGER_RESERVED; + } + self.buffer.as_mut()[end - TAG_RESERVED..end].copy_from_slice(tag); + Ok(()) + } +} + +/* 带随机数的加密数据体 + 0 15 31 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 数据体 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | random(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | finger(32) | + | finger(32) | + | finger(32) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + 注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger, + 确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹) +*/ +pub struct IVSecretBody { + buffer: B, + exist_finger: bool, +} + +impl> IVSecretBody { + pub fn new(buffer: B, exist_finger: bool) -> io::Result> { + let len = buffer.as_ref().len(); + let min_len = if exist_finger { + FINGER_RESERVED + RANDOM_RESERVED + } else { + RANDOM_RESERVED + }; + // 不能大于udp最大载荷长度 + if len < min_len || len > 65535 - 20 - 8 - 12 { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!("IVSecretBody length overflow {}", len), + )); + } + Ok(IVSecretBody { + buffer, + exist_finger, + }) + } + pub fn data(&self) -> &[u8] { + let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED; + if self.exist_finger { + end -= FINGER_RESERVED; + } + &self.buffer.as_ref()[..end] + } +} + +impl + AsMut<[u8]>> IVSecretBody { + pub fn data_mut(&mut self) -> &mut [u8] { + let mut end = self.buffer.as_ref().len() - RANDOM_RESERVED; + if self.exist_finger { + end -= FINGER_RESERVED; + } + &mut self.buffer.as_mut()[..end] + } +} + +impl> SecretTail for IVSecretBody { + #[inline] + fn buffer(&self) -> &[u8] { + self.buffer.as_ref() + } + #[inline] + fn exist_finger(&self) -> bool { + self.exist_finger + } +} + +impl + AsMut<[u8]>> SecretTailMut for IVSecretBody { + #[inline] + fn buffer_mut(&mut self) -> &mut [u8] { + self.buffer.as_mut() + } +} + /* aes_gcm加密数据体 0 15 31 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -253,85 +508,6 @@ impl + AsMut<[u8]>> AesCbcSecretBody { &mut self.buffer.as_mut()[..end] } } -/* ChaCah20加密数据体 - 0 15 31 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 数据体 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | finger(32) | - | finger(32) | - | finger(32) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - 注:finger用于快速校验数据是否被修改,上层可使用token、协议头参与计算finger, - 确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹) -*/ -pub struct ChaCah20SecretBody { - buffer: B, - exist_finger: bool, -} - -impl> ChaCah20SecretBody { - pub fn new(buffer: B, exist_finger: bool) -> io::Result> { - let len = buffer.as_ref().len(); - let min_len = if exist_finger { 12 } else { 0 }; - // 不能大于udp最大载荷长度 - if len < min_len || len > 65535 - 20 - 8 - 12 { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - "ChaCah20SecretBody length overflow", - )); - } - Ok(ChaCah20SecretBody { - buffer, - exist_finger, - }) - } - pub fn en_body(&self) -> &[u8] { - let mut end = self.buffer.as_ref().len(); - if self.exist_finger { - end -= 12; - } - &self.buffer.as_ref()[..end] - } - pub fn finger(&self) -> &[u8] { - if self.exist_finger { - let end = self.buffer.as_ref().len(); - &self.buffer.as_ref()[end - 12..end] - } else { - &[] - } - } -} - -impl + AsMut<[u8]>> ChaCah20SecretBody { - pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> { - if self.exist_finger { - if finger.len() != 12 { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - "finger.len != 12", - )); - } - let end = self.buffer.as_ref().len(); - self.buffer.as_mut()[end - 12..end].copy_from_slice(finger); - Ok(()) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - "cbc not exist finger", - )) - } - } - pub fn en_body_mut(&mut self) -> &mut [u8] { - let mut end = self.buffer.as_ref().len(); - if self.exist_finger { - end -= 12; - } - &mut self.buffer.as_mut()[..end] - } -} /* rsa加密数据体 0 15 31