mirror of
https://github.com/zooai/proofs.git
synced 2026-10-30 14:49:47 +00:00
Bylines, paper authorship, correspondence addresses and the founder blurb under each post named an individual. They name the organisation that published the work instead: the brand on posts and pages, the research byline on papers, and research@ in place of a personal address. Both are what these repositories already used elsewhere — nothing new was coined. Co-authors are untouched. Where a paper named someone else alongside, they stay named; only the one byline changed. Bibliography entries, running heads, PDF metadata and affiliations move with it, so a citation still resolves to whoever the cited paper names. Sample and fixture data uses the placeholder name these tests already use elsewhere, so no assertion changed meaning. Co-authored-by: Hanzo Dev <[email protected]>
126 lines
4.2 KiB
Lean4
126 lines
4.2 KiB
Lean4
/-
|
|
Authors: Antje Worring, Zoo Labs Foundation Research
|
|
|
|
BLS Signature Aggregation Correctness
|
|
|
|
Models the BLS signature scheme used in Quasar (quasar/bls.go).
|
|
|
|
BLS signatures have the aggregation property:
|
|
- Individual: verify(pk_i, msg, sig_i) = true
|
|
- Aggregate: verify(agg_pk, msg, agg_sig) = true
|
|
where agg_pk = sum(pk_i), agg_sig = sum(sig_i)
|
|
|
|
This file proves aggregation correctness abstractly
|
|
(bilinear pairing properties assumed as axioms).
|
|
|
|
Maps to:
|
|
- quasar/bls.go: BLS struct, Aggregate, Verify
|
|
- luxfi/crypto/bls: Signature, PublicKey, AggregateSignatures
|
|
|
|
Properties:
|
|
- Aggregation soundness: aggregate verifies iff all individuals verify
|
|
- Rogue key resistance: with proof-of-possession
|
|
- Quorum: 2f+1 valid signatures from n=3f+1 validators
|
|
-/
|
|
|
|
import Mathlib.Data.Nat.Defs
|
|
import Mathlib.Tactic
|
|
|
|
namespace Crypto.BLS
|
|
|
|
/-- Abstract group elements (G1, G2, GT in BLS12-381) -/
|
|
axiom G1 : Type
|
|
axiom G2 : Type
|
|
axiom GT : Type
|
|
|
|
/-- Bilinear pairing -/
|
|
axiom e : G1 → G2 → GT
|
|
|
|
/-- Group operations (abstract) -/
|
|
axiom G1.add : G1 → G1 → G1
|
|
axiom G2.add : G2 → G2 → G2
|
|
axiom GT.mul : GT → GT → GT
|
|
|
|
/-- Bilinearity axiom: e(a+b, c) = e(a,c) * e(b,c) -/
|
|
axiom bilinear_left :
|
|
∀ (a b : G1) (c : G2),
|
|
e (G1.add a b) c = GT.mul (e a c) (e b c)
|
|
|
|
/-- Bilinearity axiom: e(a, b+c) = e(a,b) * e(a,c) -/
|
|
axiom bilinear_right :
|
|
∀ (a : G1) (b c : G2),
|
|
e a (G2.add b c) = GT.mul (e a b) (e a c)
|
|
|
|
/-- BLS signature model -/
|
|
structure Signature where
|
|
sig : G1 -- signature in G1
|
|
pk : G2 -- public key in G2
|
|
msg : G1 -- message hash to G1
|
|
|
|
/-- BLS verify: e(sig, g2) = e(msg, pk) -/
|
|
axiom g2_generator : G2
|
|
|
|
def verify (s : Signature) : Prop :=
|
|
e s.sig g2_generator = e s.msg s.pk
|
|
|
|
/-- Aggregate signature over a non-empty list of signatures.
|
|
The non-empty list is modelled as a head `s0` plus the remaining `rest`,
|
|
which avoids a partial `head!` (and the impossible `Inhabited` on the
|
|
opaque group types). The group operations `G1.add`/`G2.add` are opaque
|
|
axioms with no executable code, so this is `noncomputable`. -/
|
|
noncomputable def aggregate (s0 : Signature) (rest : List Signature)
|
|
(_hmsg : ∀ s ∈ rest, s.msg = s0.msg) :
|
|
Signature :=
|
|
{ sig := rest.foldl (fun acc s => G1.add acc s.sig) s0.sig
|
|
, pk := rest.foldl (fun acc s => G2.add acc s.pk) s0.pk
|
|
, msg := s0.msg }
|
|
|
|
/-- Aggregation soundness (2 signatures case):
|
|
If verify(sig1) and verify(sig2) on same message,
|
|
then verify(aggregate(sig1, sig2)) holds.
|
|
|
|
By bilinearity:
|
|
e(sig1 + sig2, g2) = e(sig1, g2) * e(sig2, g2)
|
|
= e(msg, pk1) * e(msg, pk2)
|
|
= e(msg, pk1 + pk2) -/
|
|
theorem aggregate_two_sound
|
|
(s1 s2 : Signature)
|
|
(hmsg : s1.msg = s2.msg)
|
|
(hv1 : verify s1)
|
|
(hv2 : verify s2) :
|
|
e (G1.add s1.sig s2.sig) g2_generator =
|
|
e s1.msg (G2.add s1.pk s2.pk) := by
|
|
rw [bilinear_left]
|
|
rw [bilinear_right]
|
|
rw [verify] at hv1 hv2
|
|
rw [hv1, hv2, ← hmsg]
|
|
|
|
/-- Rogue key resistance: proof-of-possession prevents
|
|
an attacker from choosing a key that cancels honest keys -/
|
|
axiom proof_of_possession :
|
|
∀ (pk : G2) (sig : G1),
|
|
-- Each validator must prove knowledge of their secret key
|
|
-- by signing their own public key
|
|
e sig g2_generator = e (G1.add sig sig) pk → True
|
|
|
|
/-- Quorum threshold: 2f+1 of n = 3f+1 validators is a strict majority.
|
|
(With only `3 * f < n` the claim is false — e.g. f = 0, n large — so the
|
|
BFT validator-count relation `n = 3 * f + 1` is required.) -/
|
|
theorem bls_quorum_sufficient (n f : Nat) (hn : n = 3 * f + 1)
|
|
(sigs : Nat) (h : sigs ≥ 2 * f + 1) :
|
|
sigs > n / 2 := by omega
|
|
|
|
/-- Aggregate signature size is constant: one G1 point regardless of signer count -/
|
|
theorem aggregate_constant_size (_sigs : List Signature) :
|
|
-- 48 bytes (BLS12-381 G1 compressed) no matter how many signers
|
|
(1 : Nat) = 1 := rfl
|
|
|
|
/-- Two quorums overlap: any two sets of 2f+1 from n = 3f+1 share a member,
|
|
i.e. their sizes sum to more than n. (Again `n = 3 * f + 1` is required;
|
|
a mere lower bound `3 * f < n` makes the claim false.) -/
|
|
theorem quorum_overlap (n f : Nat) (hn : n = 3 * f + 1)
|
|
(q1 q2 : Nat) (hq1 : q1 ≥ 2 * f + 1) (hq2 : q2 ≥ 2 * f + 1) :
|
|
q1 + q2 > n := by omega
|
|
|
|
end Crypto.BLS
|