LLMSkillHub
mirroredCopied from PlamenTSV/plamen under MIT. PlamenTSV has not claimed this page, and is not affiliated with LLM SkillHub.

plamentsv / bls-aggregation-audit

L1 trigger - audits BLS signature aggregation: subgroup check, rogue-key attack defense, aggregation order, signing-domain separation.

0
SKILL.md
9.2 KB

Injectable Skill: BLS Aggregation Audit

L1 trigger: L1_PATTERN=true AND (bls/ OR blst OR milagro OR pairing OR aggregate_signature OR proof_of_possession detected in recon subsystem map)
Inject Into: depth-consensus-invariant or depth-external
Language: Go, Rust, occasionally C
Finding prefix: [BLS-N]
Status: v0.1 draft, Round 4 exemplars pending

Orchestrator Decomposition Guide

  • Sections 1, 2: depth-consensus-invariant (protocol-level BLS use)
  • Section 3: depth-external (library interface, FFI)
  • Section 4: depth-edge-case (boundary inputs)

When This Skill Activates

Recon identifies BLS12-381 signature use, typically in: Ethereum beacon chain, Filecoin, Celo, Chia, Aptos, or any aggregated-signature consensus. BLS is subtle: textbook descriptions assume defenses (subgroup check, rogue-key defense) that implementations often forget.

1. Library Fingerprinting

Identify the BLS library:

LibraryLanguageCanonical use
blstC with Go/Rust bindingsLighthouse, Prysm, Teku
milagro-cryptoCOlder clients
arkworksRustAptos, some academic
celo-bls-zexeRustCelo
py_eccPythonReference implementations
hand-rolled pairingVariousRed flag — usually wrong

A hand-rolled pairing implementation is a near-certain bug source. Flag it for intensive review.

2. Subgroup Check

BLS signatures live in a subgroup of an elliptic curve group. An attacker can provide a curve point that is valid on the curve but outside the subgroup, leading to signature verification forgeries.

Check:

  • Is every received signature / public key checked for subgroup membership before use?
  • In blst, the function is blst_p1_in_g1 / blst_p2_in_g2
  • In arkworks, there are is_in_correct_subgroup_assuming_on_curve helpers
  • Protocol-level: when a signature is received from a peer, is subgroup-checked BEFORE aggregation with trusted signatures?
  • Aggregation without subgroup check: combining a valid sig with a subgroup-invalid sig can corrupt the aggregate

Tag: [BLS-SUBGROUP:{loc}:{checked}]

Known exemplar class: the blst library had a historical subgroup-check advisory; check upgrade logs.

3. Rogue-Key Attack (Proof of Possession)

Rogue-key attack: attacker registers a public key that is the difference of a target's key and the attacker's, then signs a message that verifies as signed by both.

Defenses:

  • Proof of Possession (PoP): requires each public key to come with a self-signature of the key. Ethereum beacon chain uses this.
  • Hash-to-point including signer: if the message hash includes the signer's public key, rogue-key is defeated

Check:

  • For every public key registration / deposit path, is PoP verified?
  • Is PoP using a distinct domain separator from normal signatures? (Required — otherwise PoP can be forged from a normal sig.)

Tag: [BLS-ROGUE-KEY:{defense}:{status}]

4. Signing Domain Separation

BLS signatures must include a domain tag in the hash-to-point step. This prevents a signature from one protocol being replayed in another.

Check:

  • List all message types signed (attestation, proposal, slashing, sync committee, PoP, ...)
  • Each must have a distinct domain tag
  • Domain tags must be hardcoded constants, not computed from user input
  • Domain tags must be consistent across client implementations

Tag: [BLS-DOMAIN:{message-type}:{tag}]

5. Aggregation Correctness

5a. Aggregation algebra

  • Sum of signatures = signature of sum (for BLS). Implementation must use curve addition correctly.
  • Aggregation of zero signatures is the identity element. Is this handled? Some libraries crash.
  • Aggregation of signatures on different messages requires a different verification formula (individual verification, not batch).

5b. Order independence

Signature aggregation must be commutative. If the verification result depends on insertion order, that's a bug (and a non-determinism source).

5c. Duplicate handling

If the same signature is aggregated twice, the result doubles. Is this intended? In beacon chain, double-counting an attestation is a slashing condition.

Check: Does the aggregation code deduplicate? Does it track which validators have already contributed?

Tag: [BLS-AGG:{issue}]

6. Hash-to-Curve

The hash-to-curve step (RFC 9380) has multiple valid implementations with subtle differences. Inconsistency across clients is a consensus bug.

Check:

  • Which hash-to-curve variant is used? SSWU? Icart?
  • Is the DST (domain separation tag) exactly as specified in the protocol?
  • Is cofactor clearing applied?

7. FFI Safety

Most BLS libraries are C (blst). Calling C from Go or Rust via FFI is a common bug source:

Check:

  • Every unsafe block around blst calls: is the pointer valid? Length correct?
  • Are buffers properly sized for blst's output?
  • Are errors from blst propagated, or silently ignored?
  • Is the calling convention correct? (blst's go bindings vs raw cgo)

Tag: [BLS-FFI:{issue}]

8. Boundary conditions

StateTestExpectedObserved
Zero signatureidentity-like bytesspec-defined rejection
Zero public keyidentity-like bytesrejected
Subgroup-invalid sigon-curve but wrong subgrouprejected
Empty aggregationaggregate of zero sigsidentity or error
Duplicate in aggregatesame sig twicespec-defined
Max validator aggregationaggregate of all validatorsno integer overflow in count
Domain tag swapattestation sig used as proposal sigrejected

9. Output schema

  • Layer: crypto
  • Bug class: subgroup / rogue-key / domain-sep / aggregation / hash-to-curve / ffi-safety
  • Preferred evidence tags: [CONFORMANCE-PASS] (test vectors) > [DIFF-PASS] (against reference) > [LSP-TRACE]
  • Severity baseline: Critical for subgroup/rogue-key; High for domain-sep; Medium for aggregation boundary

10. Known bug exemplars (v0.2 — Round 4 verified)

  1. Eth2 subgroup-check requirement (milagro_bls / blst) — pairing operation is undefined on points outside the prime-order subgroup of G1/G2. Omitting subgroup check breaks strong unforgeability. Eth2 specs explicitly mandate the check for signatures during verification and public keys during deserialization — because early implementations routinely forgot. eth2book BLS chapter; milagro_bls. Skill catch point: Section 2 — the #1 real-world BLS bug class.
  2. BLS rogue-key attack (class-wide) — if attacker publishes pk_attack = pk_hash_of_honest_sigs − pk_honest, they can unilaterally produce valid "aggregate" signatures without cooperation. Mitigated by Proof-of-Possession at registration OR by message-augmentation (MsgAug scheme from BLS IETF draft). Rogue Key Attack writeup; IETF BLS draft. Skill catch point: Section 3 — the #2 real-world BLS bug class.
  3. Aumasson Eth2 beacon client security review (35+ issues) — comprehensive security review of early beacon chain implementations. Found multiple subgroup check omissions, domain separation misconfigurations, and aggregation-order assumptions. Security Review of Ethereum Beacon Clients. Skill catch point: methodology is lifted from this review — the skill is essentially a distillation of the review's checklist.
  4. Avalanche RFC6979 nonce-determinism disputed report (coingeek, 2022) — ava-labs/avalanchego used a Decred library for RFC6979 deterministic signing; researcher James Edwards reported private-key-forgery concerns (disputed by Ava Labs). Whether or not the specific claim holds, the class is real. coingeek report. Skill catch point: Section 7 (FFI safety) + dependency-audit — audit the full signing-library dependency chain, check CVE history, verify deterministic-nonce generation doesn't leak secret bits.

Methodology nuance from Round 4 (subgroup + rogue-key are the #1 and #2 real classes)

Reorder Sections 2 and 3 to reflect priority: subgroup check omission and rogue-key are the two most common real-world BLS failures. Every BLS verifier audit should START with these two checks, not end with them.

11. Fallback if primitives unavailable

  • Find BLS library import: import "github.com/supranational/blst" or similar
  • Read every call site
  • Check every signature-verification function for subgroup check presence
  • Grep for DOMAIN_SEPARATION, DOMAIN_, DST

Cross-references

  • Related: consensus-safety-invariants (fork-choice uses aggregated attestations), light-client-proof-verification (validator set signing)
  • Consumed by: depth-consensus-invariant, depth-external
  • Severity: docs/l1-mode/severity-matrix.md