main function

void main()

Implementation

void main() {
  // ==========================================================
  // 1️⃣ Parse ClientHello (already validated earlier)
  // ==========================================================
  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(" ", ""),
    ),
  );

  final clientHello = ClientHello.parse_tls_client_hello(
    clientHelloWire.sublist(4),
  );

  final keyShare = clientHello.keyShares!.firstWhere(
    (ks) => ks.group == 0x001d,
    orElse: () => throw StateError("Missing X25519 key share"),
  );

  // ==========================================================
  // 2️⃣ Create fixed server crypto (ONE TIME)
  // ==========================================================
  final serverKeyPair = KeyPair.generate();

  final serverRandom = Uint8List(32);
  for (int i = 0; i < 32; i++) {
    serverRandom[i] = i;
  }

  // ==========================================================
  // 3️⃣ Build initial ServerHello ONCE
  // ==========================================================
  Uint8List current = buildServerHello(
    serverRandom: serverRandom,
    publicKey: serverKeyPair.publicKeyBytes,
    sessionId: Uint8List(0),
    cipherSuite: 0x1301,
    group: keyShare.group,
  );

  print("✅ Initial ServerHello length = ${current.length}");

  const iterations = 10;

  for (int i = 0; i < iterations; i++) {
    // --------------------------------------------------
    // 4️⃣ Parse ServerHello (skip handshake header)
    // --------------------------------------------------
    if (current.length < 4 || current[0] != 0x02) {
      throw StateError("Iteration $i: not a ServerHello handshake");
    }

    final buf = QuicBuffer(data: current.sublist(4));
    final parsed = ServerHello.parse(buf);

    // --------------------------------------------------
    // 5️⃣ Validate parsed ServerHello
    // --------------------------------------------------
    if (parsed.legacyVersion != 0x0303) {
      throw StateError("Iteration $i: invalid legacy_version");
    }

    if (parsed.cipherSuite != 0x1301) {
      throw StateError("Iteration $i: cipher_suite mismatch");
    }

    if (parsed.keyShareEntry == null || parsed.keyShareEntry!.group != 0x001d) {
      throw StateError("Iteration $i: key_share mismatch");
    }

    // --------------------------------------------------
    // 6️⃣ Rebuild ServerHello from parsed fields
    // --------------------------------------------------
    final rebuilt = buildServerHello(
      serverRandom: parsed.random,
      publicKey: parsed.keyShareEntry!.pub,
      sessionId: parsed.sessionId,
      cipherSuite: parsed.cipherSuite,
      group: parsed.keyShareEntry!.group,
    );

    // --------------------------------------------------
    // 7️⃣ Byte‑for‑byte compare
    // --------------------------------------------------
    if (rebuilt.length != current.length) {
      throw StateError(
        "Iteration $i: length mismatch "
        "${rebuilt.length} != ${current.length}",
      );
    }

    for (int j = 0; j < rebuilt.length; j++) {
      if (rebuilt[j] != current[j]) {
        throw StateError(
          "Iteration $i: byte mismatch at offset $j "
          "(0x${current[j].toRadixString(16)} != "
          "0x${rebuilt[j].toRadixString(16)})",
        );
      }
    }

    print("✅ Iteration $i OK");

    current = rebuilt;
  }

  print("✅ ServerHello stable after $iterations parse ⇄ build cycles");
}