main function
void
main()
Implementation
void main() {
// ==========================================================
// 1️⃣ Raw TLS ClientHello (handshake header + body)
// ==========================================================
final clientHelloWire = Uint8List.fromList(
HEX.decode(
"01 00 00 ea 03 03 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 00 00 06 13 01 13 02 13 03 01 00 00 bb 00 00 00 18 00 16 00 00 13 65 78 61 6d 70 6c 65 2e 75 6c 66 68 65 69 6d 2e 6e 65 74 00 0a 00 08 00 06 00 1d 00 17 00 18 00 10 00 0b 00 09 08 70 69 6e 67 2f 31 2e 30 00 0d 00 14 00 12 04 03 08 04 04 01 05 03 08 05 05 01 08 06 06 01 02 01 00 33 00 26 00 24 00 1d 00 20 35 80 72 d6 36 58 80 d1 ae ea 32 9a df 91 21 38 38 51 ed 21 a2 8e 3b 75 e9 65 d0 d2 cd 16 62 54 00 2d 00 02 01 01 00 2b 00 03 02 03 04 00 39 00 31 03 04 80 00 ff f7 04 04 80 a0 00 00 05 04 80 10 00 00 06 04 80 10 00 00 07 04 80 10 00 00 08 01 0a 09 01 0a 0a 01 03 0b 01 19 0f 05 63 5f 63 69 64"
.replaceAll(" ", ""),
),
);
print("✅ ClientHello wire length = ${clientHelloWire.length}");
print("Handshake type = 0x${clientHelloWire[0].toRadixString(16)}");
// ==========================================================
// 2️⃣ Parse ClientHello (strip handshake header)
// ==========================================================
final parsed = ClientHello.parse_tls_client_hello(clientHelloWire.sublist(4));
print(parsed);
// ✅ sanity checks
if (parsed.legacyVersion != 0x0303) {
throw StateError(
"Invalid legacy_version: expected 0x0303, "
"got 0x${parsed.legacyVersion.toRadixString(16)}",
);
}
if (!parsed.cipherSuites.contains(0x1301)) {
throw StateError(
"ClientHello does not advertise TLS_AES_128_GCM_SHA256 (0x1301)",
);
}
if (parsed.keyShares == null || parsed.keyShares!.isEmpty) {
throw StateError("ClientHello contains no key_share extension");
}
// final x25519Share = parsed.keyShares!.firstWhere(
// (ks) => ks.group == 0x001d,
// orElse: () => throw StateError(
// "ClientHello does not contain an X25519 (0x001d) key_share",
// ),
// );
// ==========================================================
// 3️⃣ Re‑serialize ClientHello
// ==========================================================
final rebuilt = parsed.serialize();
print("✅ Rebuilt ClientHello length = ${rebuilt.length}");
// ==========================================================
// 4️⃣ Byte‑for‑byte equality check
// ==========================================================
final eq = const ListEquality<int>().equals(clientHelloWire, rebuilt);
if (!eq) {
print("❌ MISMATCH!");
print("Original:");
print(HEX.encode(clientHelloWire));
print("Rebuilt:");
print(HEX.encode(rebuilt));
throw StateError("ClientHello round‑trip mismatch");
}
print("✅ ClientHello parse ⇄ build round‑trip OK");
}