mirror of
https://github.com/saymrwulf/ltl-accumulator-verified.git
synced 2026-09-03 19:53:48 +00:00
186 lines
7.8 KiB
Text
186 lines
7.8 KiB
Text
|
|
/- L4 (first instance) of the accumulator pyramid: **root binding for the
|
|||
|
|
inclusion fold** — the Path instance of the paper's Lemma 2 — and
|
|||
|
|
**Theorem 2 (inclusion soundness)** as a constructive statement:
|
|||
|
|
an accepting receipt for a wrong leaf EXHIBITS a SHA-256 collision.
|
|||
|
|
|
|||
|
|
No collision-resistance assumption appears anywhere: `HasCollision`
|
|||
|
|
is the conclusion, never a hypothesis. -/
|
|||
|
|
import Proofs.Completeness
|
|||
|
|
|
|||
|
|
namespace LTLAcc
|
|||
|
|
|
|||
|
|
/-- Two distinct preimages with equal hash — the jackpot. Constructively
|
|||
|
|
exhibited by the soundness theorems; believing it cannot be found is
|
|||
|
|
the reader's interpretation of SHA-256, exactly as in the paper. -/
|
|||
|
|
def HasCollision : Prop :=
|
|||
|
|
∃ x y : List UInt8, x ≠ y ∧ sha256 x = sha256 y
|
|||
|
|
|
|||
|
|
/-- Either two hash values have equal preimage pairs, or their equality
|
|||
|
|
is itself a collision (the paper's case dichotomy at one node). -/
|
|||
|
|
theorem hnode_inj_or_collision {x y X Y : Hash}
|
|||
|
|
(h : hnode x y = hnode X Y) :
|
|||
|
|
(x = X ∧ y = Y) ∨ HasCollision := by
|
|||
|
|
by_cases hpre :
|
|||
|
|
(0x01 : UInt8) :: (x.val ++ y.val) = 0x01 :: (X.val ++ Y.val)
|
|||
|
|
· exact Or.inl (hnode_preimage_inj hpre)
|
|||
|
|
· exact Or.inr ⟨_, _, hpre, h⟩
|
|||
|
|
|
|||
|
|
/-- Likewise at a leaf: equal leaf hashes with distinct data collide. -/
|
|||
|
|
theorem hleaf_inj_or_collision {d e : Bytes}
|
|||
|
|
(h : hleaf d = hleaf e) : d = e ∨ HasCollision := by
|
|||
|
|
by_cases hde : d = e
|
|||
|
|
· exact Or.inl hde
|
|||
|
|
· refine Or.inr ⟨0x00 :: d, 0x00 :: e, ?_, h⟩
|
|||
|
|
intro hc; injection hc with _ ht; exact hde ht
|
|||
|
|
|
|||
|
|
/-- A non-empty list is its `dropLast` plus its last element
|
|||
|
|
(self-contained; no stdlib-name dependence). -/
|
|||
|
|
theorem eq_dropLast_append_of_getLast? (l : List Hash) (s : Hash)
|
|||
|
|
(h : l.getLast? = some s) : l = l.dropLast ++ [s] := by
|
|||
|
|
induction l with
|
|||
|
|
| nil => simp at h
|
|||
|
|
| cons a t ih =>
|
|||
|
|
cases t with
|
|||
|
|
| nil =>
|
|||
|
|
simp at h
|
|||
|
|
subst h
|
|||
|
|
rfl
|
|||
|
|
| cons b u =>
|
|||
|
|
have hh : (b :: u).getLast? = some s := by
|
|||
|
|
simpa using h
|
|||
|
|
have := ih hh
|
|||
|
|
calc a :: b :: u = a :: (b :: u) := rfl
|
|||
|
|
_ = a :: ((b :: u).dropLast ++ [s]) := by rw [← this]
|
|||
|
|
_ = (a :: b :: u).dropLast ++ [s] := by simp
|
|||
|
|
|
|||
|
|
/-- **Root binding** (the Path instance of the paper's Lemma 2): if any
|
|||
|
|
reconstruction from `(v, P)` hits the honest root, then either
|
|||
|
|
`(v, P)` IS the honest receipt — leaf hash and every consumed
|
|||
|
|
sibling — or a collision is exhibited. -/
|
|||
|
|
theorem root_binding (m : Nat) (D : List Bytes) :
|
|||
|
|
∀ (v : Hash) (P : List Hash), m < D.length →
|
|||
|
|
Root v m D.length P = some (MTH D) →
|
|||
|
|
(v = hleaf (D.getD m []) ∧ P = Path m D) ∨ HasCollision := by
|
|||
|
|
induction m, D using Path.induct with
|
|||
|
|
| case1 m D hle =>
|
|||
|
|
intro v P hm h
|
|||
|
|
have h1 : D.length = 1 := by omega
|
|||
|
|
obtain ⟨d, rfl⟩ := exists_singleton_of_length_one D h1
|
|||
|
|
have hm0 : m = 0 := by simpa using hm
|
|||
|
|
subst hm0
|
|||
|
|
have hlen : ([d] : List Bytes).length = 1 := rfl
|
|||
|
|
rw [hlen] at h
|
|||
|
|
cases P with
|
|||
|
|
| nil =>
|
|||
|
|
rw [Root_one, MTH_single] at h
|
|||
|
|
simp only [Option.some.injEq] at h
|
|||
|
|
left
|
|||
|
|
refine ⟨?_, by rw [Path]; simp⟩
|
|||
|
|
have hg : ([d] : List Bytes).getD 0 [] = d := rfl
|
|||
|
|
rw [hg]; exact h
|
|||
|
|
| cons p q =>
|
|||
|
|
rw [Root_one_cons] at h
|
|||
|
|
simp at h
|
|||
|
|
| case2 m D hgt k hmk ih =>
|
|||
|
|
intro v P hm h
|
|||
|
|
have h2 : 2 ≤ D.length := by omega
|
|||
|
|
have hkeq : k = kbelow D.length := rfl
|
|||
|
|
have hkl : k < D.length := by rw [hkeq]; exact kbelow_lt D.length h2
|
|||
|
|
have hmk' : m < kbelow D.length := by rw [← hkeq]; exact hmk
|
|||
|
|
have htklen : (D.take k).length = k := by
|
|||
|
|
simp [List.length_take]; omega
|
|||
|
|
cases hP : P.getLast? with
|
|||
|
|
| none =>
|
|||
|
|
have hPnil : P = [] := by
|
|||
|
|
cases P with
|
|||
|
|
| nil => rfl
|
|||
|
|
| cons a t => simp at hP
|
|||
|
|
subst hPnil
|
|||
|
|
rw [Root] at h
|
|||
|
|
have hn1 : ¬ D.length = 1 := by omega
|
|||
|
|
have hn0 : ¬ D.length = 0 := by omega
|
|||
|
|
simp [hn1, hn0] at h
|
|||
|
|
| some s =>
|
|||
|
|
obtain hsplit := eq_dropLast_append_of_getLast? P s hP
|
|||
|
|
rw [hsplit] at h
|
|||
|
|
rw [Root_left _ _ _ _ _ h2 hmk', ← hkeq] at h
|
|||
|
|
cases hR : Root v m k P.dropLast with
|
|||
|
|
| none => rw [hR] at h; simp at h
|
|||
|
|
| some x =>
|
|||
|
|
rw [hR] at h
|
|||
|
|
simp only [Option.map_some, Option.some.injEq] at h
|
|||
|
|
rw [MTH_split D h2, ← hkeq] at h
|
|||
|
|
rcases hnode_inj_or_collision h with ⟨hx, hs⟩ | hc
|
|||
|
|
· have ihm : m < (D.take k).length := by omega
|
|||
|
|
have hR' : Root v m (D.take k).length P.dropLast
|
|||
|
|
= some (MTH (D.take k)) := by rw [htklen, hR, hx]
|
|||
|
|
rcases ih v P.dropLast ihm hR' with ⟨hv, hPd⟩ | hc
|
|||
|
|
· left
|
|||
|
|
refine ⟨?_, ?_⟩
|
|||
|
|
· rw [hv]; exact congrArg hleaf (getD_take D k m hmk)
|
|||
|
|
· have hRHS : Path m D = Path m (D.take k) ++ [MTH (D.drop k)] := by
|
|||
|
|
rw [Path]; simp only [if_neg hgt, ← hkeq, if_pos hmk]
|
|||
|
|
rw [hRHS, hsplit, hPd, hs]
|
|||
|
|
· exact Or.inr hc
|
|||
|
|
· exact Or.inr hc
|
|||
|
|
| case3 m D hgt k hmk ih =>
|
|||
|
|
intro v P hm h
|
|||
|
|
have h2 : 2 ≤ D.length := by omega
|
|||
|
|
have hkeq : k = kbelow D.length := rfl
|
|||
|
|
have hkl : k < D.length := by rw [hkeq]; exact kbelow_lt D.length h2
|
|||
|
|
have hkp : 0 < k := by rw [hkeq]; exact kbelow_pos D.length
|
|||
|
|
have hmk' : ¬ m < kbelow D.length := by rw [← hkeq]; exact hmk
|
|||
|
|
have hdplen : (D.drop k).length = D.length - k := by
|
|||
|
|
simp [List.length_drop]
|
|||
|
|
cases hP : P.getLast? with
|
|||
|
|
| none =>
|
|||
|
|
have hPnil : P = [] := by
|
|||
|
|
cases P with
|
|||
|
|
| nil => rfl
|
|||
|
|
| cons a t => simp at hP
|
|||
|
|
subst hPnil
|
|||
|
|
rw [Root] at h
|
|||
|
|
have hn1 : ¬ D.length = 1 := by omega
|
|||
|
|
have hn0 : ¬ D.length = 0 := by omega
|
|||
|
|
simp [hn1, hn0] at h
|
|||
|
|
| some s =>
|
|||
|
|
obtain hsplit := eq_dropLast_append_of_getLast? P s hP
|
|||
|
|
rw [hsplit] at h
|
|||
|
|
rw [Root_right _ _ _ _ _ h2 hmk', ← hkeq] at h
|
|||
|
|
cases hR : Root v (m - k) (D.length - k) P.dropLast with
|
|||
|
|
| none => rw [hR] at h; simp at h
|
|||
|
|
| some x =>
|
|||
|
|
rw [hR] at h
|
|||
|
|
simp only [Option.map_some, Option.some.injEq] at h
|
|||
|
|
rw [MTH_split D h2, ← hkeq] at h
|
|||
|
|
rcases hnode_inj_or_collision h with ⟨hs, hx⟩ | hc
|
|||
|
|
· have ihm : m - k < (D.drop k).length := by omega
|
|||
|
|
have hR' : Root v (m - k) (D.drop k).length P.dropLast
|
|||
|
|
= some (MTH (D.drop k)) := by rw [hdplen, hR, hx]
|
|||
|
|
rcases ih v P.dropLast ihm hR' with ⟨hv, hPd⟩ | hc
|
|||
|
|
· left
|
|||
|
|
have hidx : k + (m - k) = m := by omega
|
|||
|
|
refine ⟨?_, ?_⟩
|
|||
|
|
· rw [hv]
|
|||
|
|
have hh : (D.drop k).getD (m - k) [] = D.getD m [] := by
|
|||
|
|
rw [getD_drop, hidx]
|
|||
|
|
exact congrArg hleaf hh
|
|||
|
|
· have hRHS : Path m D = Path (m - k) (D.drop k) ++ [MTH (D.take k)] := by
|
|||
|
|
rw [Path]; simp only [if_neg hgt, ← hkeq, if_neg hmk]
|
|||
|
|
rw [hRHS, hsplit, hPd, hs]
|
|||
|
|
· exact Or.inr hc
|
|||
|
|
· exact Or.inr hc
|
|||
|
|
|
|||
|
|
/-- **Theorem 2 (Inclusion soundness: position binding)**, paper §6,
|
|||
|
|
constructive form: an accepting receipt whose leaf differs from the
|
|||
|
|
honest leaf at position `m` exhibits a SHA-256 collision. -/
|
|||
|
|
theorem incl_sound (m : Nat) (D : List Bytes) (hm : m < D.length)
|
|||
|
|
(d : Bytes) (P : List Hash)
|
|||
|
|
(h : Root (hleaf d) m D.length P = some (MTH D)) :
|
|||
|
|
d = D.getD m [] ∨ HasCollision := by
|
|||
|
|
rcases root_binding m D (hleaf d) P hm h with ⟨hv, _⟩ | hc
|
|||
|
|
· exact hleaf_inj_or_collision hv
|
|||
|
|
· exact Or.inr hc
|
|||
|
|
|
|||
|
|
end LTLAcc
|