bls-signature-aggregator
The implementation is in ~/bls_aggregator.py. It provides five core functions using py_ecc's optimized BLS12-381 curve primitives:
| Function | What it does |
|---|---|
key_gen(seed) |
Deterministic secret key from seed (HKDF-based, CFRG BLS standard) |
sk_to_pk(sk) |
Public key = sk · G1 (48 bytes, G1 compressed) |
sign(sk, msg) |
Signature = sk · H(msg) where H: {0,1}* → G2 (96 bytes) |
aggregate(sigs) |
Aggregated signature = Σ sig_i (addition in G2) |
aggregate_verify(pks, msgs, sig) |
Pairing check: e(sig, G1) == ∏ e(H(m_i), PK_i) |
verify(pk, msg, sig) |
Single signature verification |
batch_verify(tuples) |
Aggregates all sigs then runs aggregate_verify |
Key cryptographic details:
- KeyGen: Iterates HKDF-extract/expand until SK ≠ 0 mod r (curve order)
- Signing: Uses the hash_to_G2 function (SSWU map-to-curve with SHA-256, per IRTF hash-to-curve spec)
- Aggregation: Simple point addition in G2, starting from the point at infinity
- Verification: Uses the optimal Ate pairing. Single verify checks e(sig, G1) · e(H(m), -PK) == 1. Aggregate verify checks e(sig, G1) · ∏ e(H(m_i), -PK_i) == 1
- Rogue-key protection: Rejects duplicate messages in aggregate_verify
All 27 tests pass: ``` ============================================================ BLS Signature Aggregation -- Self Test ============================================================ [Key Generation] [PASS] sk1 in valid range [PASS] sk2 in valid range [PASS] deterministic keygen (same seed -> same key) [PASS] different seeds -> different keys [PASS] public key is 48 bytes (G1 compressed) [PASS] different secret keys -> different public keys [Single Sign & Verify] [PASS] signature is 96 bytes (G2 compressed) [PASS] verify own signature [PASS] verify own signature (key 2) [PASS] wrong key rejects signature [PASS] wrong message rejects signature [Aggregation] [PASS] aggregated signature is 96 bytes [PASS] aggregated != first signature [PASS] aggregated != second signature [PASS] aggregate of [sig] == sig [PASS] empty list raises ValueError [Aggregate Verify] [PASS] aggregate verify with unique messages [PASS] reject wrong aggregated signature [PASS] reject duplicate messages (rogue-key protection) [PASS] mismatched PK/message counts -> reject [Batch Verify] [PASS] batch verify all valid signatures [PASS] batch rejects when one signature is bad [PASS] empty batch returns True [Edge Cases] [PASS] keygen never returns 0 (iterates until SK!=0) [PASS] verify with garbage PK returns False [PASS] verify with garbage sig returns False [PASS] sign/verify large message ============================================================ Results: 27/27 passed, 0 failed ``` **Edge cases verified:** 1. Deterministic keygen (same seed → same key, different seeds → different keys) 2. Aggregate of a single signature equals the original 3. Empty signature list raises `ValueError` 4. Duplicate messages in `aggregate_verify` are rejected (rogue-key attack prevention) 5. Mismatched PK/message counts are rejected 6. Garbage public key/signature bytes return `False` (not exceptions) 7. Large messages (10KB) sign and verify correctly 8. Wrong public key or wrong message reject the signature 9. Batch verification rejects a batch containing even one bad signature ---
{"model": "claude", "problem_class": "bls-signature-aggregator", "result": "passed", "tests": 27}The implementation is in ~/bls_aggregator.py. It provides five core functions using py_ecc's optimized BLS12-381 curve primitives:
| Function | What it does |
|---|---|
key_gen(seed) |
Deterministic secret key from seed (HKDF-based, CFRG BLS standard) |
sk_to_pk(sk) |
Public key = sk · G1 (48 bytes, G1 compressed) |
sign(sk, msg) |
Signature = sk · H(msg) where H: {0,1}* → G2 (96 bytes) |
aggregate(sigs) |
Aggregated signature = Σ sig_i (addition in G2) |
aggregate_verify(pks, msgs, sig) |
Pairing check: e(sig, G1) == ∏ e(H(m_i), PK_i) |
verify(pk, msg, sig) |
Single signature verification |
batch_verify(tuples) |
Aggregates all sigs then runs aggregate_verify |
Key cryptographic details:
- KeyGen: Iterates HKDF-extract/expand until SK ≠ 0 mod r (curve order)
- Signing: Uses the hash_to_G2 function (SSWU map-to-curve with SHA-256, per IRTF hash-to-curve spec)
- Aggregation: Simple point addition in G2, starting from the point at infinity
- Verification: Uses the optimal Ate pairing. Single verify checks e(sig, G1) · e(H(m), -PK) == 1. Aggregate verify checks e(sig, G1) · ∏ e(H(m_i), -PK_i) == 1
- Rogue-key protection: Rejects duplicate messages in aggregate_verify
All 27 tests pass: ``` ============================================================ BLS Signature Aggregation -- Self Test ============================================================ [Key Generation] [PASS] sk1 in valid range [PASS] sk2 in valid range [PASS] deterministic keygen (same seed -> same key) [PASS] different seeds -> different keys [PASS] public key is 48 bytes (G1 compressed) [PASS] different secret keys -> different public keys [Single Sign & Verify] [PASS] signature is 96 bytes (G2 compressed) [PASS] verify own signature [PASS] verify own signature (key 2) [PASS] wrong key rejects signature [PASS] wrong message rejects signature [Aggregation] [PASS] aggregated signature is 96 bytes [PASS] aggregated != first signature [PASS] aggregated != second signature [PASS] aggregate of [sig] == sig [PASS] empty list raises ValueError [Aggregate Verify] [PASS] aggregate verify with unique messages [PASS] reject wrong aggregated signature [PASS] reject duplicate messages (rogue-key protection) [PASS] mismatched PK/message counts -> reject [Batch Verify] [PASS] batch verify all valid signatures [PASS] batch rejects when one signature is bad [PASS] empty batch returns True [Edge Cases] [PASS] keygen never returns 0 (iterates until SK!=0) [PASS] verify with garbage PK returns False [PASS] verify with garbage sig returns False [PASS] sign/verify large message ============================================================ Results: 27/27 passed, 0 failed ``` **Edge cases verified:** 1. Deterministic keygen (same seed → same key, different seeds → different keys) 2. Aggregate of a single signature equals the original 3. Empty signature list raises `ValueError` 4. Duplicate messages in `aggregate_verify` are rejected (rogue-key attack prevention) 5. Mismatched PK/message counts are rejected 6. Garbage public key/signature bytes return `False` (not exceptions) 7. Large messages (10KB) sign and verify correctly 8. Wrong public key or wrong message reject the signature 9. Batch verification rejects a batch containing even one bad signature ---
{"model": "claude", "problem_class": "bls-signature-aggregator", "result": "passed", "tests": 27}