Skip to main content

decrypt_initial/
decrypt_initial.rs

1/* examples/decrypt_initial.rs */
2
3#![allow(missing_docs)]
4
5// Demonstrates the full decrypt flow: parse header, decrypt payload, extract
6// CRYPTO frames, and reassemble the crypto stream.
7//
8// Uses the RFC 9001 Appendix A test vector for QUIC v1 Initial packets.
9// The DCID used in the test vector is 0x8394c8f03e515708.
10
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}
62
63fn hex(bytes: &[u8]) -> String {
64	bytes.iter().map(|b| format!("{b:02x}")).collect()
65}
66
67fn rfc9001_client_initial() -> Vec<u8> {
68	// RFC 9001 Appendix A.2 — Client Initial packet (1200 bytes).
69	// DCID = 0x8394c8f03e515708 (8 bytes).
70	hex_decode(concat!(
71		"c000000001088394c8f03e515708",
72		"0000449e",
73		"7b9aec34d1b1c98dd7689fb8ec11",
74		"d242b123dc9bd8bab936b47d92ec356c",
75		"0bab7df5976d27cd449f63300099f399",
76		"1c260ec4c60d17b31f8429157bb35a12",
77		"82a643a8d2262cad67500cadb8e7378c",
78		"8eb7539ec4d4905fed1bee1fc8aafba1",
79		"7c750e2c7ace01e6005f80fcb7df6212",
80		"30c83711b39343fa028cea7f7fb5ff89",
81		"eac2308249a02252155e2347b63d58c5",
82		"457afd84d05dfffdb20392844ae81215",
83		"4682e9cf012f9021a6f0be17ddd0c208",
84		"4dce25ff9b06cde535d0f920a2db1bf3",
85		"62c23e596dee38f5a6cf3948838a3aec",
86		"4e15daf8500a6ef69ec4e3feb6b1d98e",
87		"610ac8b7ec3faf6ad760b7bad1db4ba3",
88		"485e8a94dc250ae3fdb41ed15fb6a8e5",
89		"eba0fc3dd60bc8e30c5c4287e53805db",
90		"059ae0648db2f64264ed5e39be2e20d8",
91		"2df566da8dd5998ccabdae053060ae6c",
92		"7b4378e846d29f37ed7b4ea9ec5d82e7",
93		"961b7f25a9323851f681d582363aa5f8",
94		"9937f5a67258bf63ad6f1a0b1d96dbd4",
95		"faddfcefc5266ba6611722395c906556",
96		"be52afe3f565636ad1b17d508b73d874",
97		"3eeb524be22b3dcbc2c7468d54119c74",
98		"68449a13d8e3b95811a198f3491de3e7",
99		"fe942b330407abf82a4ed7c1b311663a",
100		"c69890f4157015853d91e923037c227a",
101		"33cdd5ec281ca3f79c44546b9d90ca00",
102		"f064c99e3dd97911d39fe9c5d0b23a22",
103		"9a234cb36186c4819e8b9c592772663229",
104		"1d6a418211cc2962e20fe47feb3edf33",
105		"0f2c603a9d48c0fcb5699dbfe5896425",
106		"c5bac4aee82e57a85aaf4e2513e4f057",
107		"96b07ba2ee47d80506f8d2c25e50fd14",
108		"de71e6c418559302f939b0e1abd576f2",
109		"79c4b2e0feb85c1f28ff18f58891ffef",
110		"132eef2fa09346aee33c28eb130ff28f",
111		"5b766953334113211996d20011a198e3",
112		"fc433f9f2541010ae17c1bf202580f60",
113		"47472fb36857fe843b19f5984009ddc3",
114		"24044e847a4f4a0ab34f719595de3725",
115		"2d6235365e9b84392b061085349d7320",
116		"3a4a13e96f5432ec0fd4a1ee65accdd5",
117		"e3904df54c1da510b0ff20dcc0c77fcb",
118		"2c0e0eb605cb0504db87632cf3d8b4da",
119		"e6e705769d1de354270123cb11450efc",
120		"60ac47683d7b8d0f811365565fd98c4c",
121		"8eb936bcab8d069fc33bd801b03adea2",
122		"e1fbc5aa463d08ca19896d2bf59a071b",
123		"851e6c239052172f296bfb5e72404790",
124		"a2181014f3b94a4e97d117b438130368",
125		"cc39dbb2d198065ae3986547926cd216",
126		"2f40a29f0c3c8745c0f50fba3852e566",
127		"d44575c29d39a03f0cda721984b6f440",
128		"591f355e12d439ff150aab7613499dbd",
129		"49adabc8676eef023b15b65bfc5ca069",
130		"48109f23f350db82123535eb8a7433bd",
131		"abcb909271a6ecbcb58b936a88cd4e8f",
132		"2e6ff5800175f113253d8fa9ca8885c2",
133		"f552e657dc603f252e1a8e308f76f0be",
134		"79e2fb8f5d5fbbe2e30ecadd220723c8",
135		"c0aea8078cdfcb3868263ff8f0940054",
136		"da48781893a7e49ad5aff4af300cd804",
137		"a6b6279ab3ff3afb64491c85194aab76",
138		"0d58a606654f9f4400e8b38591356fbf",
139		"6425aca26dc85244259ff2b19c41b9f9",
140		"6f3ca9ec1dde434da7d2d392b905ddf3",
141		"d1f9af93d1af5950bd493f5aa731b405",
142		"6df31bd267b6b90a079831aaf579be0a",
143		"39013137aac6d404f518cfd46840647e",
144		"78bfe706ca4cf5e9c5453e9f7cfd2b8b",
145		"4c8d169a44e55c88d4a9a7f947424110",
146		"92abbdf8b889e5c199d096e3f24788",
147	))
148}
149
150fn hex_decode(s: &str) -> Vec<u8> {
151	(0..s.len())
152		.step_by(2)
153		.map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("valid hex"))
154		.collect()
155}