// Capture hex fixtures representing realistic TLS handshakes
///|
pub fn fixture_client_hello_tls12() -> Bytes {
Bytes::from_array([
// Record Header: Handshake, TLS 1.0 (legacy record version), Length: 119
0x16, 0x03, 0x01, 0x00, 0x77,
// Handshake Header: ClientHello, Length: 115
0x01, 0x00, 0x00, 0x73,
// Version: TLS 1.2 (0x0303)
0x03, 0x03,
// Random: 32 bytes
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
// Session ID Length: 0
0x00,
// Cipher Suites Length: 8 bytes
0x00, 0x08,
// Ciphers: TLS_AES_128_GCM_SHA256 (0x1301), TLS_AES_256_GCM_SHA384 (0x1302), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f), TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
0x13, 0x01, 0x13, 0x02, 0xc0, 0x2f, 0x00, 0x35,
// Compression Methods Length: 1, null compression
0x01, 0x00,
// Extensions Length: 66 bytes
0x00, 0x42,
// Extension: Server Name Indication (type: 0, length: 14)
0x00, 0x00, 0x00, 0x0e,
// ServerNameList length: 12
0x00, 0x0c,
// Entry: HostName (type: 0), NameLength: 9, Name: "baidu.com"
0x00, 0x00, 0x09, 0x62, 0x61, 0x69, 0x64, 0x75, 0x2e, 0x63, 0x6f, 0x6d,
// Extension: ALPN (type: 16, length: 14)
0x00, 0x10, 0x00, 0x0e,
// ALPN list length: 12
0x00, 0x0c,
// Protocols: "h2" (length: 2), "http/1.1" (length: 8)
0x02, 0x68, 0x32, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
// Extension: Supported Groups (type: 10, length: 8)
0x00, 0x0a, 0x00, 0x08,
// List length: 6, Groups: X25519 (29), P-256 (23), P-384 (24)
0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
// Extension: EC Point Formats (type: 11, length: 2)
0x00, 0x0b, 0x00, 0x02,
// List length: 1, Format: uncompressed (0)
0x01, 0x00,
// Extension: Signature Algorithms (type: 13, length: 8)
0x00, 0x0d, 0x00, 0x08,
// List length: 6, Algorithms: rsa_pss_rsae_sha256 (0x0403), rsa_pkcs1_sha256 (0x0401), ecdsa_secp256r1_sha256 (0x0403)
0x00, 0x06, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01,
])
}
///|
pub fn fixture_server_hello_tls13() -> Bytes {
Bytes::from_array([
// Record Header: Handshake, TLS 1.2, Length: 59
0x16, 0x03, 0x03, 0x00, 0x3b,
// Handshake Header: ServerHello, Length: 55
0x02, 0x00, 0x00, 0x37,
// Version: TLS 1.2 (negotiation version for legacy compatibility)
0x03, 0x03,
// Random: 32 bytes
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c,
0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
// Session ID Length: 0
0x00,
// Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
0x13, 0x01,
// Compression Method: null (0)
0x00,
// Extensions Length: 15
0x00, 0x0f,
// Extension: Supported Versions (type: 43, length: 2) -> Negotiated TLS 1.3 (0x0304)
0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
// Extension: ALPN (type: 16, length: 5) -> "h2"
0x00, 0x10, 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32,
])
}
///|
pub fn fixture_tls_alert_fatal() -> Bytes {
Bytes::from_array([
// Record Header: Alert, TLS 1.2, Length: 2
0x15, 0x03, 0x03, 0x00, 0x02,
// Level: Fatal (2), Description: Decrypt Error (51 / 0x33)
0x02, 0x33,
])
}
///|
pub fn fixture_tls_certificate() -> Bytes {
Bytes::from_array([
// Record Header: Handshake, TLS 1.2, Length: 32
0x16, 0x03, 0x03, 0x00, 0x20,
// Handshake Header: Certificate (11), Length: 28
0x0b, 0x00, 0x00, 0x1c,
// Certificates List Length: 25
0x00, 0x00, 0x19,
// Cert 1 Length: 10, data
0x00, 0x00, 0x0a, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44,
// Cert 2 Length: 9, data
0x00, 0x00, 0x09, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
])
}
///|
pub fn fixture_client_key_exchange() -> Bytes {
Bytes::from_array([
// Record Header: Handshake, TLS 1.2, Length: 14
0x16, 0x03, 0x03, 0x00, 0x0e,
// Handshake Header: ClientKeyExchange (16), Length: 10
0x10, 0x00, 0x00, 0x0a,
// Key Exchange Payload: 10 bytes
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44,
])
}
///|
pub fn fixture_server_key_exchange() -> Bytes {
Bytes::from_array([
// Record Header: Handshake, TLS 1.2, Length: 16
0x16, 0x03, 0x03, 0x00, 0x10,
// Handshake Header: ServerKeyExchange (12), Length: 12
0x0c, 0x00, 0x00, 0x0c,
// Key Exchange Payload: 12 bytes
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
])
}
///|
pub fn fixture_new_session_ticket() -> Bytes {
Bytes::from_array([
// Record Header: Handshake, TLS 1.2, Length: 23
0x16, 0x03, 0x03, 0x00, 0x17,
// Handshake Header: NewSessionTicket (4), Length: 19
0x04, 0x00, 0x00, 0x13,
// Ticket Lifetime: 3600 (0x00000e10)
0x00, 0x00, 0x0e, 0x10,
// Ticket Age Add: 123456 (0x0001e240)
0x00, 0x01, 0xe2, 0x40,
// Ticket Length: 9
0x00, 0x09,
// Ticket data: 9 bytes
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
])
}
///|
pub fn fixture_encrypted_extensions() -> Bytes {
Bytes::from_array([
// Record Header: Handshake, TLS 1.2, Length: 16
0x16, 0x03, 0x03, 0x00, 0x10,
// Handshake Header: EncryptedExtensions (8), Length: 12
0x08, 0x00, 0x00, 0x0c,
// Extensions Total Length: 10
0x00, 0x0a,
// Extension: ServerName (type 0, len 0) -> Grease representation or empty
0x00, 0x00, 0x00, 0x00,
// Extension: ALPN (type 16, len 2) -> empty list
0x00, 0x10, 0x00, 0x02, 0x00, 0x00,
])
}