pub fn decrypt_initial(header: &InitialHeader<'_>) -> Result<Vec<u8>, Error>Expand description
Decrypt a QUIC Initial packet payload.
Performs header protection removal (AES-ECB), key derivation (HKDF-SHA256), and AEAD decryption (AES-128-GCM). Supports both QUIC v1 (RFC 9001) and v2 (RFC 9369).
The returned bytes contain the decrypted frames (PADDING, CRYPTO, ACK, etc.).
ยงErrors
Returns Error::UnsupportedVersion if the version is not v1 or v2.
Returns Error::DecryptionFailed if any cryptographic operation fails.
Returns Error::BufferTooShort if the payload is too short for header
protection removal.
Examples found in repository?
examples/decrypt_initial.rs (line 29)
11fn main() {
12 // RFC 9001 Appendix A.2 client Initial packet (complete, 1200 bytes).
13 let packet = rfc9001_client_initial();
14
15 let header = match quic_parser::parse_initial(&packet) {
16 Ok(h) => h,
17 Err(e) => {
18 eprintln!("header parse error: {e}");
19 return;
20 }
21 };
22
23 println!("Parsed header:");
24 println!(" version: {:#010x}", header.version);
25 println!(" dcid: {}", hex(header.dcid));
26 println!(" scid: {}", hex(header.scid));
27 println!(" payload: {} bytes", header.payload.len());
28
29 let decrypted = match quic_parser::decrypt_initial(&header) {
30 Ok(d) => d,
31 Err(e) => {
32 eprintln!("decryption error: {e}");
33 return;
34 }
35 };
36
37 println!("Decrypted {} bytes of frame data", decrypted.len());
38
39 let frames = match quic_parser::parse_crypto_frames(&decrypted) {
40 Ok(f) => f,
41 Err(e) => {
42 eprintln!("frame parse error: {e}");
43 return;
44 }
45 };
46
47 println!("Found {} CRYPTO frame(s)", frames.len());
48 for (i, f) in frames.iter().enumerate() {
49 println!(" frame {i}: offset={}, len={}", f.offset, f.data.len());
50 }
51
52 let stream = quic_parser::reassemble_crypto_stream(&frames);
53 println!("Reassembled crypto stream: {} bytes", stream.len());
54
55 if stream.len() >= 6 {
56 let msg_type = stream[0];
57 let length = u32::from_be_bytes([0, stream[1], stream[2], stream[3]]);
58 let tls_version = u16::from_be_bytes([stream[4], stream[5]]);
59 println!("TLS handshake: type={msg_type:#04x} length={length} version={tls_version:#06x}");
60 }
61}