/-- For every finite field `F` of odd characteristic, we have `2^(#F/2) = χ₈#F` in `F`. -/
theorem FiniteField.two_pow_card {F : Type*} [Fintype F] [Field F] (hF : ringChar F ≠ 2) :
    (2 : F) ^ (Fintype.card F / 2) = χ₈ (Fintype.card F) := by
  have hp2 : ∀ n : ℕ, (2 ^ n : F) ≠ 0 := fun n => pow_ne_zero n (Ring.two_ne_zero hF)
  obtain ⟨n, hp, hc⟩ := FiniteField.card F (ringChar F)

  -- we work in `FF`, the eighth cyclotomic field extension of `F`
  -- Porting note: was
  -- let FF := (Polynomial.cyclotomic 8 F).SplittingField
  -- but we want to unify with `CyclotomicField` below.
  let FF := CyclotomicField 8 F
  haveI : Polynomial.IsSplittingField F FF (Polynomial.cyclotomic 8 F) :=
    Polynomial.IsSplittingField.splittingField _
  haveI : FiniteDimensional F FF :=
    Polynomial.IsSplittingField.finiteDimensional FF (Polynomial.cyclotomic 8 F)
  haveI : Fintype FF := FiniteDimensional.fintypeOfFintype F FF
  have hchar := Algebra.ringChar_eq F FF
  have FFp := hchar.subst hp
  haveI := Fact.mk FFp
  have hFF := ne_of_eq_of_ne hchar.symm hF
  -- `ringChar FF ≠ 2`
  have hu : IsUnit (ringChar FF : ZMod 8) := by
    rw [isUnit_iff_not_dvd_char, ringChar_zmod_n]
    rw [Ne, ← Nat.prime_dvd_prime_iff_eq FFp Nat.prime_two] at hFF
    change ¬_ ∣ 2 ^ 3
    exact mt FFp.dvd_of_dvd_pow hFF

  -- there is a primitive additive character `ℤ/8ℤ → FF`, sending `a + 8ℤ ↦ τ^a`
  -- with a primitive eighth root of unity `τ`
  -- Porting note: The type is actually `PrimitiveAddChar (ZMod (8 : ℕ+)) F`, but this seems faster.
  let ψ₈ : PrimitiveAddChar (ZMod 8) F :=
    primitiveZModChar 8 F (by convert hp2 3 using 1; norm_cast)
  -- Porting note: unifying this is very slow, so only do it once.
  let ψ₈char : AddChar (ZMod 8) FF := ψ₈.char
  let τ : FF := ψ₈char 1
  have τ_spec : τ ^ 4 = -1 := by
    refine (sq_eq_one_iff.1 ?_).resolve_left ?_
    · rw [← pow_mul, ← map_nsmul_pow ψ₈char]
      -- doesn't match syntactically for `rw`
      refine (AddChar.IsPrimitive.zmod_char_eq_one_iff 8 ψ₈.prim _).2 ?_
      decide
    · rw [← map_nsmul_pow ψ₈char]
      -- doesn't match syntactically for `rw`
      refine (AddChar.IsPrimitive.zmod_char_eq_one_iff 8 ψ₈.prim _).not.2 ?_
      decide

  -- we consider `χ₈` as a multiplicative character `ℤ/8ℤ → FF`
  let χ := χ₈.ringHomComp (Int.castRingHom FF)
  have hχ : χ (-1) = 1 := Int.cast_one
  have hq : IsQuadratic χ := isQuadratic_χ₈.comp _

  -- we now show that the Gauss sum of `χ` and `ψ₈` has the relevant property
  have hg : gaussSum χ ψ₈char ^ 2 = χ (-1) * Fintype.card (ZMod 8) := by
    have _ := congr_arg (· ^ 2) (Fin.sum_univ_eight fun x => (χ₈ x : FF) * τ ^ x.1)
    have h₁ : (fun i : Fin 8 => ↑(χ₈ i) * τ ^ i.val) = (fun a : ZMod 8 => χ a * ↑(ψ₈char a)) := by
      -- Porting note: original proof
      -- ext; congr; apply pow_one
      ext (x : Fin 8); rw [← map_nsmul_pow ψ₈char]; congr 2;
      rw [Nat.smul_one_eq_coe, Fin.cast_val_eq_self x]
    have h₂ : (0 + 1 * τ ^ 1 + 0 + -1 * τ ^ 3 + 0 + -1 * τ ^ 5 + 0 + 1 * τ ^ 7) ^ 2 =
        8 + (τ ^ 4 + 1) * (τ ^ 10 - 2 * τ ^ 8 - 2 * τ ^ 6 + 6 * τ ^ 4 + τ ^ 2 - 8) := by ring
    have h₃ : 8 + (τ ^ 4 + 1) * (τ ^ 10 - 2 * τ ^ 8 - 2 * τ ^ 6 + 6 * τ ^ 4 + τ ^ 2 - 8) = ↑8 := by
      rw [τ_spec]; norm_num
    have h₄ : (0 + 1 * τ ^ 1 + 0 + -1 * τ ^ 3 + 0 + -1 * τ ^ 5 + 0 + 1 * τ ^ 7) ^ 2 = ↑8 := by
      rw [← h₃, ← h₂]
    

Proof state:
F : Type u_1
inst✝¹ : Fintype F
inst✝ : Field F
hF : ringChar F ≠ 2
hp2 : ∀ (n : ℕ), 2 ^ n ≠ 0
n : ℕ+
hp : Nat.Prime (ringChar F)
hc : Fintype.card F = ringChar F ^ ↑n
FF : Type u_1 := CyclotomicField 8 F
this✝² : Polynomial.IsSplittingField F FF (Polynomial.cyclotomic 8 F)
this✝¹ : FiniteDimensional F FF
this✝ : Fintype FF
hchar : ringChar F = ringChar FF
FFp : Nat.Prime (ringChar FF)
this : Fact (Nat.Prime (ringChar FF))
hFF : ringChar FF ≠ 2
hu : IsUnit ↑(ringChar FF)
ψ₈ : PrimitiveAddChar (ZMod 8) F := primitiveZModChar 8 F (_ : ↑↑8 ≠ 0)
ψ₈char : AddChar (ZMod 8) FF := PrimitiveAddChar.char ψ₈
τ : FF := ψ₈char 1
τ_spec : τ ^ 4 = -1
χ : MulChar (ZMod 8) FF := ringHomComp χ₈ (Int.castRingHom FF)
hχ : χ (-1) = 1
hq : IsQuadratic χ
x✝ :
  (fun x => x ^ 2) (∑ i : Fin 8, ↑(χ₈ i) * τ ^ ↑i) =
    (fun x => x ^ 2)
      (↑(χ₈ 0) * τ ^ ↑0 + ↑(χ₈ 1) * τ ^ ↑1 + ↑(χ₈ 2) * τ ^ ↑2 + ↑(χ₈ 3) * τ ^ ↑3 + ↑(χ₈ 4) * τ ^ ↑4 + ↑(χ₈ 5) * τ ^ ↑5 +
          ↑(χ₈ 6) * τ ^ ↑6 +
        ↑(χ₈ 7) * τ ^ ↑7)
h₁ : (fun i => ↑(χ₈ i) * τ ^ ↑i) = fun a => χ a * ψ₈char a
h₂ :
  (0 + 1 * τ ^ 1 + 0 + -1 * τ ^ 3 + 0 + -1 * τ ^ 5 + 0 + 1 * τ ^ 7) ^ 2 =
    8 + (τ ^ 4 + 1) * (τ ^ 10 - 2 * τ ^ 8 - 2 * τ ^ 6 + 6 * τ ^ 4 + τ ^ 2 - 8)
h₃ : 8 + (τ ^ 4 + 1) * (τ ^ 10 - 2 * τ ^ 8 - 2 * τ ^ 6 + 6 * τ ^ 4 + τ ^ 2 - 8) = 8
h₄ : (0 + 1 * τ ^ 1 + 0 + -1 * τ ^ 3 + 0 + -1 * τ ^ 5 + 0 + 1 * τ ^ 7) ^ 2 = 8
⊢ gaussSum χ ψ₈char ^ 2 = χ (-1) * ↑(Fintype.card (ZMod 8))

Next tactic:
have h₅ :
        (↑(χ₈ 0) * τ ^ 0 + ↑(χ₈ 1) * τ ^ 1 + ↑(χ₈ 2) * τ ^ 2 + ↑(χ₈ 3) * τ ^ 3 + ↑(χ₈ 4) * τ ^ 4 +
        ↑(χ₈ 5) * τ ^ 5 + ↑(χ₈ 6) * τ ^ 6 + ↑(χ₈ 7) * τ ^ 7) ^ 2 = 8 := by
      -- Porting note: original proof
      --  simp [← h₄, χ₈_apply, Matrix.cons_val_zero, algebraMap.coe_zero, zero_mul,
      -- Matrix.cons_val_one, Matrix.head_cons, algebraMap.coe_one, Matrix.cons_vec_bit0_eq_alt0,
      -- Matrix.cons_vecAppend, Matrix.cons_vecAlt0, Matrix.cons_vec_bit1_eq_alt1,
      -- Matrix.cons_vecAlt1, Int.cast_neg]
      simp_rw [χ₈_apply]
      rw [← h₄]
      dsimp only
      congr
      · rw [Matrix.cons_val_zero]; simp
      · simp only [Matrix.vecCons, ne_eq, Nat.cast_ofNat, id_eq, eq_mpr_eq_cast, mul_eq_zero,
          zero_lt_two, pow_eq_zero_iff]
        left
        rw [← Int.cast_zero (R := FF)]
        exact congr_arg Int.cast rfl
      · simp only [Matrix.vecCons]
        rw [show (-1 : FF) = ↑(- 1 : ℤ) by simp only [Int.cast_neg, Int.cast_one]]
        exact congr_arg Int.cast rfl
      · simp only [Matrix.vecCons, ne_eq, Nat.cast_ofNat, id_eq, eq_mpr_eq_cast, mul_eq_zero,
          zero_lt_two, pow_eq_zero_iff]
        left
        rw [← Int.cast_zero (R := FF)]
        exact congr_arg Int.cast rfl
      · simp only [Matrix.vecCons]
        rw [show (-1 : FF) = ↑(- 1 : ℤ) by simp only [Int.cast_neg, Int.cast_one]]
        exact congr_arg Int.cast rfl
      · simp only [Matrix.vecCons, ne_eq, Nat.cast_ofNat, id_eq, eq_mpr_eq_cast, mul_eq_zero,
          zero_lt_two, pow_eq_zero_iff]
        left
        rw [← Int.cast_zero (R := FF)]
        exact congr_arg Int.cast rfl