clean project from comments

This commit is contained in:
2026-03-13 21:39:29 +07:00
parent 66036c1451
commit 0cc44d0037
34 changed files with 132 additions and 542 deletions
-8
View File
@@ -1,22 +1,14 @@
/// Handshake message types
pub const HANDSHAKE_TYPE_CLIENT_HELLO: u8 = 0x01;
pub const HANDSHAKE_TYPE_SERVER_HELLO: u8 = 0x02;
/// SNI (Server Name Indication) specific
pub const TYPE_HOST_NAME: u8 = 0x00;
/// PSK (Pre-Shared Key) modes
pub const PSK_DHE_KE_MODE: u8 = 0x01;
/// Certificate compression algorithms
pub const CERT_COMPRESSION_BROTLI: u16 = 0x0002;
/// Extension internal status types
pub const OCSP_STATUS_TYPE: u8 = 0x01;
//pub const EC_POINT_FORMAT_UNCOMPRESSED: u8 = 0x00;
/// GREASE (Generate Random Extensions And Sustain Extensibility)
/// Используется для предотвращения ошибок серверов при встрече с неизвестными ID.
pub const GREASE_IDENTIFIERS: [u16; 16] = [
0x0A0A, 0x1A1A, 0x2A2A, 0x3A3A, 0x4A4A, 0x5A5A, 0x6A6A, 0x7A7A, 0x8A8A, 0x9A9A, 0xAAAA, 0xBABA,
0xCACA, 0xDADA, 0xEAEA, 0xFAFA,
+8 -28
View File
@@ -1,7 +1,6 @@
use bytes::{BufMut, Bytes, BytesMut};
use rand::RngExt;
// Using your provided constants and types
use crate::tlseng::{
consts::{
CERT_COMPRESSION_BROTLI, GREASE_IDENTIFIERS, OCSP_STATUS_TYPE, PSK_DHE_KE_MODE,
@@ -33,16 +32,6 @@ impl ExtensionStack {
}
impl Extension {
/// Creates a new Extension from the given parameters.
///
/// # Arguments
///
/// * `etype`: The type of extension (e.g., EXT_SUPPORTED_VERSIONS).
/// * `data`: The actual data being transported (e.g., a serialized list of supported versions).
///
/// # Returns
///
/// A new Extension structure with the given parameters.
pub fn new(etype: u16, data: Bytes) -> Self {
Self {
etype,
@@ -50,16 +39,7 @@ impl Extension {
data,
}
}
/// Packs an extension into a single byte array.
///
/// # Arguments
///
/// * `etype`: The type of extension (e.g., EXT_SUPPORTED_VERSIONS).
/// * `data`: The actual data being transported (e.g., a serialized list of supported versions).
///
/// # Returns
///
/// A single byte array containing the type and length of the extension, followed by the actual extension data.
pub fn pack(etype: u16, data: &[u8]) -> Bytes {
let mut ext = BytesMut::with_capacity(4 + data.len());
ext.put_u16(etype);
@@ -139,9 +119,9 @@ impl ExtensionBuilder {
pub fn key_share(&mut self, pub_key: &[u8]) {
let mut data = BytesMut::with_capacity(38);
data.put_u16(34); // Total Key Share List Length
data.put_u16(34);
data.put_u16(TlsGroups::X25519);
data.put_u16(32); // Public Key length
data.put_u16(32);
data.put_slice(pub_key);
self.add_extension(TlsExtensions::KEY_SHARE, &data);
}
@@ -152,7 +132,7 @@ impl ExtensionBuilder {
let p_bytes = proto.as_bytes();
data.put_u8(p_bytes.len() as u8);
data.put_slice(p_bytes);
data.put_u16(0); // Empty settings per-protocol
data.put_u16(0);
}
self.add_extension(TlsExtensions::ALPS, &data);
}
@@ -189,15 +169,15 @@ impl ExtensionBuilder {
pub fn status_request(&mut self) {
let mut data = BytesMut::with_capacity(5);
data.put_u8(OCSP_STATUS_TYPE);
data.put_u16(0); // responder_id_list
data.put_u16(0); // request_extensions
data.put_u16(0);
data.put_u16(0);
self.add_extension(TlsExtensions::STATUS_REQUEST, &data);
}
pub fn ec_point_formats(&mut self) {
let mut data = BytesMut::with_capacity(2);
data.put_u8(1);
data.put_u8(0x00); // Uncompressed
data.put_u8(0x00);
self.add_extension(TlsExtensions::EC_POINT_FORMATS, &data);
}
@@ -263,7 +243,7 @@ impl ExtensionBuilder {
self.add_extension(TlsExtensions::PADDING, &[]);
}
}
// Обработка GREASE по маске
id if (id & 0x0f0f) == 0x0a0a => self.grease(),
_ => {}
}
+16 -48
View File
@@ -17,65 +17,46 @@ pub struct HelloHeader {
}
pub struct ClientHello {
/// The maximum version supported (legacy field in TLS 1.3)
pub version: ProtocolVersion,
/// 32 bytes of client-generated entropy
pub random: [u8; 32],
/// Legacy session ID (used in TLS 1.3 for middlebox compatibility)
pub session_id: Bytes,
/// List of cryptographic ciphers the client supports
pub cipher_suites: Vec<u16>,
/// Opaque block of extensions generated by ExtensionBuilder
pub extensions: Bytes,
}
impl ClientHello {
/// Serializes the ClientHello message into its wire format.
/// Includes the 4-byte Handshake header (Type + Length).
pub fn serialize(&self) -> Bytes {
let mut buf = BytesMut::with_capacity(512 + self.extensions.len());
// Handshake Type: 0x01 (ClientHello)
buf.put_u8(HANDSHAKE_TYPE_CLIENT_HELLO);
// Handshake Length Placeholder:
// Handshake messages use a 24-bit (3 byte) length field.
let length_pos = buf.len();
buf.put_bytes(0, 3);
// Protocol Version:
// For TLS 1.3, this is traditionally pinned to 0x0303 (TLS 1.2)
// to prevent middleboxes from dropping the packet.
buf.put_u16(0x0303);
buf.put_slice(&self.random);
// Legacy Session ID:
// Formatted as Length (1 byte) + ID bytes.
buf.put_u8(self.session_id.len() as u8);
buf.put_slice(&self.session_id);
// Cipher Suites:
// Formatted as Total Length (2 bytes) + Suite IDs (2 bytes each).
buf.put_u16((self.cipher_suites.len() * 2) as u16);
for &suite in &self.cipher_suites {
buf.put_u16(suite);
}
// Legacy Compression Methods:
// Always 1 byte of length (1) followed by the 'Null' method (0x00).
buf.put_u8(1);
buf.put_u8(0x00);
// Extensions Block:
// Formatted as Total Length (2 bytes) + Extension Data.
buf.put_u16(self.extensions.len() as u16);
buf.put_slice(&self.extensions);
// Patch the Handshake Length:
// We calculate the length of everything after the 3-byte placeholder.
let total_len = (buf.len() - length_pos - 3) as u32;
let len_bytes = total_len.to_be_bytes();
// Copy the last 3 bytes of the big-endian u32 into the placeholder.
buf[length_pos..length_pos + 3].copy_from_slice(&len_bytes[1..4]);
let ext_len = self.extensions.len();
@@ -108,10 +89,10 @@ impl ClientHello {
session_id.put_slice(&[0u8; 32]);
let client_hello = ClientHello {
version: ProtocolVersion::Tls12, // Legacy version for compatibility
version: ProtocolVersion::Tls12,
random: tls_random,
session_id: session_id.freeze(), // Standard 32-byte session ID
cipher_suites: vec![0x1301, 0x1302, 0x1303], // TLS 1.3 suites
session_id: session_id.freeze(),
cipher_suites: vec![0x1301, 0x1302, 0x1303],
extensions: extensions_bytes,
};
@@ -133,7 +114,6 @@ pub struct ServerHello {
pub extensions: BytesMut,
}
impl ServerHello {
/// Динамически создает ServerHello на основе данных из ClientHello
pub fn from_client_hello(
client_hello: &ClientHello,
server_public_key: &[u8],
@@ -149,17 +129,14 @@ impl ServerHello {
let mut extensions = BytesMut::new();
// --- Extension: Supported Versions (0x002b) ---
extensions.put_u16(0x002b);
extensions.put_u16(2);
extensions.put_u16(0x0304); // TLS 1.3
extensions.put_u16(0x0304);
// --- Extension: Key Share (0x0033) ---
// Структура: Type(2) + Length(2) + Group(2) + KeyLength(2) + Key(N)
extensions.put_u16(0x0033);
extensions.put_u16(36); // Общая длина данных расширения (2+2+32)
extensions.put_u16(0x001d); // Named Group: x25519
extensions.put_u16(32); // Key Length
extensions.put_u16(36);
extensions.put_u16(0x001d);
extensions.put_u16(32);
extensions.put_slice(server_public_key);
Self {
@@ -171,7 +148,6 @@ impl ServerHello {
}
}
/// Оборачивает в TLS Record, принимая ключ
pub fn make_server_hello(
client_hello: &ClientHello,
server_public_key: &[u8],
@@ -188,43 +164,35 @@ impl ServerHello {
record.serialize()
}
/// Сериализация самого сообщения Handshake (Type + Len gth + Body)
pub fn serialize(&self) -> Bytes {
let mut buf = BytesMut::with_capacity(256 + self.extensions.len());
// 1. Handshake Type: 0x02 (ServerHello)
buf.put_u8(HANDSHAKE_TYPE_SERVER_HELLO);
// 2. Placeholder для длины (u24)
let length_pos = buf.len();
buf.put_bytes(0, 3);
// 3. Тело ServerHello
buf.put_u16(0x0303); // Legacy Version
buf.put_u16(0x0303);
buf.put_slice(&self.random);
// Session ID: Length (1 byte) + Data
buf.put_u8(self.session_id.len() as u8);
buf.put_slice(&self.session_id);
// Selected Cipher Suite
buf.put_u16(self.cipher_suite);
// Compression: всегда 0x00
buf.put_u8(0x00);
// Extensions: Length (2 bytes) + Data
buf.put_u16(self.extensions.len() as u16);
buf.put_slice(&self.extensions);
// 4. Патчим длину Handshake сообщения (u24)
let total_len = (buf.len() - length_pos - 3) as u32;
let len_bytes = total_len.to_be_bytes();
buf[length_pos..length_pos + 3].copy_from_slice(&len_bytes[1..4]);
let total_handshake_len = (buf.len() - length_pos - 3) as u32;
let ext_len = self.extensions.len();
// ИНФОРМАТИВНЫЙ ЛОГ
tracing::debug!(
handshake_type = "ServerHello",
body_len = total_handshake_len,
@@ -233,6 +201,6 @@ impl ServerHello {
"Serialized Handshake message"
);
buf.freeze() // Превращаем BytesMut в Bytes
buf.freeze()
}
}
+5 -32
View File
@@ -1,33 +1,20 @@
use crate::tlseng::types::{ExtensionOrder, TlsGroups, TlsSignatures, TlsVersions};
/// Represents a complete TLS fingerprint profile for a specific browser.
///
/// This struct contains all the necessary information to generate a TLS
/// fingerprint for a specific browser, including the groups, signatures,
/// delegated signatures, versions, ALPN, and extension order.
pub struct BrowserProfile {
/// The name of the browser profile.
pub name: &'static str,
/// The groups supported by the browser.
pub groups: TlsGroups,
/// The signatures supported by the browser.
pub signatures: TlsSignatures,
/// The delegated signatures supported by the browser.
pub delegated_signatures: TlsSignatures,
/// The versions of TLS supported by the browser.
pub versions: TlsVersions,
/// The ALPN protocols supported by the browser.
pub alpn: &'static [&'static str],
/// The specific order of Extension IDs (e.g., [0x0000, 0x0017, ...])
pub extension_order: ExtensionOrder,
/// Whether the browser is based on Chromium.
pub is_chromium: bool,
}
@@ -45,7 +32,7 @@ impl BrowserProfile {
pub const EDGE: Self = Self {
name: "Edge",
groups: TlsGroups::CHROMIUM, // Edge использует тот же набор, что и Chrome
groups: TlsGroups::CHROMIUM,
signatures: TlsSignatures::BROWSER_STANDARD,
delegated_signatures: TlsSignatures::BROWSER_STANDARD,
versions: TlsVersions::MODERN,
@@ -56,45 +43,31 @@ impl BrowserProfile {
pub const DEFAULT: Self = Self::CHROME_131;
}
/// Represents a TLS configuration profile for the server side.
pub struct ServerProfile {
/// Имя профиля (например, "Modern-TLS-1.3-Only" или "Compatible-Nginx-Style")
pub name: &'static str,
/// Поддерживаемые версии TLS. Сервер выберет высшую общую с клиентом.
pub versions: TlsVersions,
/// Приоритетный список шифров (Cipher Suites).
/// В TLS 1.3 это обычно [0x1301, 0x1302, 0x1303].
pub cipher_suites: &'static [u16],
/// Группы для обмена ключами (Key Exchange Groups).
pub groups: TlsGroups,
/// Поддерживаемые алгоритмы подписи для аутентификации сервера.
pub signatures: TlsSignatures,
/// Протоколы ALPN, которые сервер готов подтвердить (h2, http/1.1).
pub alpn: &'static [&'static str],
/// Настройки сессий
pub session_tickets: bool,
/// Нужно ли форсировать порядок шифров сервера (Server Preference),
/// игнорируя порядок предпочтений клиента.
pub honor_cipher_order: bool,
}
impl ServerProfile {
pub const MODERN: Self = Self {
name: "Modern-Secure",
versions: TlsVersions::MODERN, // Допустим, у тебя есть такой хелпер
cipher_suites: &[
0x1301, // TLS_AES_128_GCM_SHA256
0x1302, // TLS_AES_256_GCM_SHA384
0x1303, // TLS_CHACHA20_POLY1305_SHA256
],
groups: TlsGroups::MODERN, // X25519, P-256
versions: TlsVersions::MODERN,
cipher_suites: &[0x1301, 0x1302, 0x1303],
groups: TlsGroups::MODERN,
signatures: TlsSignatures::BROWSER_STANDARD,
alpn: &["h2", "http/1.1"],
session_tickets: true,
+2 -18
View File
@@ -2,32 +2,18 @@ use bytes::{BufMut, Bytes, BytesMut};
use crate::tlseng::types::{ContentType, ProtocolVersion};
/// The TLS Record Layer structure.
/// This is the outer envelope that wraps all TLS messages sent over the wire.
#[derive(Debug)]
pub struct TlsRecord {
/// The type of data contained (Handshake, ApplicationData, etc.)
pub content_type: ContentType,
/// The record layer version (usually 0x0301 for legacy support)
pub version: ProtocolVersion,
pub len: u16,
/// The actual data being transported (e.g., a serialized ClientHello)
pub payload: Bytes,
}
impl TlsRecord {
/// Creates a new TLS Record Layer from the given parameters.
///
/// # Arguments
///
/// * `content_type`: The type of data contained (Handshake, ApplicationData, etc.).
/// * `version`: The record layer version (usually 0x0301 for legacy support).
/// * `payload`: The actual data being transported (e.g., a serialized ClientHello).
///
/// # Returns
///
/// A new TLS Record Layer structure with the given parameters.
pub fn new(content_type: ContentType, version: ProtocolVersion, payload: Bytes) -> Self {
Self {
content_type,
@@ -37,8 +23,6 @@ impl TlsRecord {
}
}
/// Serializes the Record Layer header and payload.
/// Wire Format: [Type (1)] [Version (2)] [Length (2)] [Payload (N)]
pub fn serialize(&self) -> Bytes {
let mut buf = BytesMut::with_capacity(5 + self.payload.len());
+9 -80
View File
@@ -1,25 +1,15 @@
/// TLS Content Types as defined in the TLS Record Protocol.
/// These identify what is contained within the TLS Record payload.
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContentType {
/// Handshake messages (e.g., ClientHello, ServerHello)
Handshake = 0x16,
/// Encrypted application data (the actual traffic)
ApplicationData = 0x17,
/// Notification messages (e.g., CloseNotify or error signals)
Alert = 0x15,
}
impl TryFrom<u8> for ContentType {
type Error = &'static str;
/// Attempts to convert a given `u8` value into a `ContentType`.
///
/// Returns `Ok(ContentType)` if the conversion is successful, and `Err(&str)` if not.
///
/// # Examples
///
///
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
@@ -31,14 +21,6 @@ impl TryFrom<u8> for ContentType {
}
}
///
/// Represents known TLS protocol versions.
///
/// Note that TLS 1.3 often uses legacy versions in headers for compatibility.
///
/// # Examples
///
///
#[repr(u16)]
#[derive(Copy, Clone, Debug)]
pub enum ProtocolVersion {
@@ -50,66 +32,28 @@ pub enum ProtocolVersion {
impl TryFrom<u16> for ProtocolVersion {
type Error = &'static str;
/// Attempts to convert a given `u16` value into a `ProtocolVersion`.
///
/// Returns `Ok(ProtocolVersion)` if the conversion is successful, and `Err(&str)` if not.
///
/// # Examples
///
///
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
// TLS 1.0 (RFC 2246)
0x0301 => Ok(ProtocolVersion::Tls10),
// TLS 1.2 (RFC 4346)
0x0303 => Ok(ProtocolVersion::Tls12),
// TLS 1.3 (draft-ietf-tls-tls13-28)
0x0304 => Ok(ProtocolVersion::Tls13),
_ => Err("This is not Protocol Version"),
}
}
}
/// Hello types as defined in the TLS Handshake Protocol.
///
/// These identify the type of the message in the TLS Handshake protocol.
///
/// # Examples
///
///
/// # Notes
///
/// The values of these enum variants are used as the first byte of the TLS
/// Handshake protocol message.
///
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum HelloType {
/// Client hello message type
Client = 0x01,
/// Server hello message type
Server = 0x02,
}
/// Attempts to convert a given `u8` value into a `HelloType`.
///
/// Returns `Ok(HelloType)` if the conversion is successful, and `Err(&str)` if not.
///
/// # Examples
///
///
/// # Notes
///
/// This function is used to convert raw bytes into a `HelloType`.
/// It is used in the `HelloHeader` parsing process.
impl TryFrom<u8> for HelloType {
type Error = &'static str;
/// Attempts to convert a given `u8` value into a `HelloType`.
///
/// Returns `Ok(HelloType)` if the conversion is successful, and `Err(&str)` if not.
///
/// # Examples
///
///
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x01 => Ok(HelloType::Client),
@@ -119,10 +63,6 @@ impl TryFrom<u8> for HelloType {
}
}
/// A collection of supported TLS groups.
///
/// This is a list of 16-bit group identifiers that the client supports.
/// The server will select one of these groups to use for the key exchange.
#[derive(Clone, Copy)]
pub struct TlsGroups(pub &'static [u16]);
@@ -131,17 +71,11 @@ impl TlsGroups {
pub const SECP256R1: u16 = 0x0017;
pub const SECP384R1: u16 = 0x0018;
/// Стандартный набор для Chrome/Edge (X25519 + P-256)
pub const CHROMIUM: Self = Self(&[Self::X25519, Self::SECP256R1, Self::SECP384R1]);
/// Набор "только современные кривые"
pub const MODERN: Self = Self(&[Self::X25519, Self::SECP256R1]);
}
/// A collection of supported TLS signature algorithms.
///
/// This is a list of 16-bit signature algorithm identifiers that the client supports.
/// The server will select one of these algorithms to use for the digital signature.
#[derive(Clone, Copy)]
pub struct TlsSignatures(pub &'static [u16]);
@@ -155,7 +89,6 @@ impl TlsSignatures {
pub const RSA_PSS_RSAE_SHA512: u16 = 0x0806;
pub const RSA_PKCS1_SHA512: u16 = 0x0601;
/// Типичный набор для современных браузеров
pub const BROWSER_STANDARD: Self = Self(&[
Self::ECDSA_SECP256R1_SHA256,
Self::RSA_PSS_RSAE_SHA256,
@@ -167,10 +100,6 @@ impl TlsSignatures {
]);
}
/// A collection of supported TLS protocol versions.
///
/// This is a list of 16-bit protocol version identifiers that the client supports.
/// The server will select one of these versions to use for the TLS connection.
#[derive(Clone, Copy)]
pub struct TlsVersions(pub &'static [u16]);
@@ -218,7 +147,7 @@ impl<'a> IntoIterator for &'a ExtensionOrder {
impl ExtensionOrder {
pub const CHROMIUM_131: Self = Self(&[
0xaaaa, // GREASE
0xaaaa,
TlsExtensions::SNI,
TlsExtensions::EMS,
TlsExtensions::SESSION_TICKET,
@@ -237,7 +166,7 @@ impl ExtensionOrder {
]);
pub const EDGE_130: Self = Self(&[
0x1a1a, // GREASE
0x1a1a,
TlsExtensions::SNI,
TlsExtensions::EMS,
TlsExtensions::SESSION_TICKET,
@@ -254,6 +183,6 @@ impl ExtensionOrder {
TlsExtensions::SCT,
TlsExtensions::DELEGATED_CREDENTIAL,
TlsExtensions::PADDING,
0x3a3a, // GREASE
0x3a3a,
]);
}