Lux Ringtail - Post-Quantum Threshold Signatures
Ringtail is the post-quantum signature primitive for Lux consensus. It enables t-of-n threshold signing without relying on classical assumptions R...
Overview
Ringtail is a pure Go implementation of the Ringtail post-quantum threshold signature scheme from eprint.iacr.org/2024/1113. It provides practical two-round lattice-based threshold signatures from standard LWE (Learning With Errors) assumptions, built on the github.com/luxfi/lattice/v7 ring polynomial library.
Ringtail is the post-quantum signature primitive for Lux consensus. It enables t-of-n threshold signing without relying on classical assumptions (RSA, ECDSA) that are vulnerable to quantum computers.
When to use
- Implementing or modifying post-quantum threshold signatures in the Lux stack
- Integrating PQ-safe consensus finality (Quasar certificates)
- Working with lattice-based cryptographic protocols
- Benchmarking or testing Ring-LWE signing performance
- Extending the threshold package for new signing protocols
Hard requirements
- ALWAYS use
github.com/luxfi/*packages -- NEVERgo-ethereumorluxfi - NEVER use EWOQ keys
- Requires
github.com/luxfi/lattice/v7for all ring polynomial operations - Go packages stay at v1.x.x (the module itself has no version suffix)
Quick reference
| Item | Value |
|---|---|
| Repo | github.com/luxfi/ringtail |
| Module | github.com/luxfi/ringtail |
| Go version | 1.26.1 |
| Binary | bin/ringtail |
| Paper | eprint.iacr.org/2024/1113 |
| License | Apache 2.0 |
| Key dep | github.com/luxfi/lattice/v7 v7.0.0 |
Core Concepts
Directory structure
luxfi/ringtail/
main.go -- Entry point: local sim or P2P party mode
sign/
config.go -- Scheme parameters (Q, N, M, bounds, ring dims)
sign.go -- Core: Party, Gen, SignRound1/2, Finalize, Verify
local.go -- Local single-machine simulation with stats
primitives/
hash.go -- Hash, MAC, PRF, GaussianHash, LowNormHash
shamir.go -- Shamir secret sharing over ring vectors
networking/
networking.go -- TCP P2P comm between signers (send/recv)
threshold/
threshold.go -- High-level API: GenerateKeys, Signer, Verify
threshold_test.go -- Full signing flow tests (key gen, sign, verify)
utils/
utils.go -- NTT/Montgomery, matrix/vector ops, rounding
utils-naive.go -- Naive ring multiplication (test-only)
test_helpers.go -- Shared test utilitiesScheme parameters (sign/config.go)
| Parameter | Value | Description |
|---|---|---|
| LogN | 8 | Ring dimension N = 256 |
| Q | 0x1000000004A01 | 48-bit NTT-friendly prime |
| M | 8 | Public key matrix rows |
| N | 7 | Secret key dimension |
| Dbar | 48 | Commitment column count |
| Kappa | 23 | Security parameter |
| KeySize | 32 | 256-bit keys |
| SigmaE | 6.108 | Error distribution width |
| SigmaStar | ~2^37.3 | Masking distribution width |
Protocol flow
- Gen (Trusted Dealer): Generate LWE public key (A, b), Shamir-split secret key into shares, distribute seeds and MAC keys to all parties.
- Sign Round 1 (Each party): Sample masking vectors, compute commitment matrix D_i and MAC tags, broadcast to all parties.
- Sign Round 2 (Each party): Verify MACs, check D-sum full rank, compute partial signature z_i using Lagrange coefficients, send to combiner.
- Finalize (Combiner): Aggregate z shares into final signature (c, z, Delta).
- Verify (Anyone): Recompute hash, check L2 norm bound.
Two API levels
Low-level (sign package): Direct Party struct with explicit ring operations. Used by main.go for P2P networking mode.
High-level (threshold package): Clean GenerateKeys/Signer/Verify API with proper error handling. Preferred for integration.
// Generate 2-of-3 threshold keys
shares, groupKey, err := threshold.GenerateKeys(2, 3, nil)
// Create signers
signers := make([]*threshold.Signer, 3)
for i, share := range shares {
signers[i] = threshold.NewSigner(share)
}
// Round 1
round1Data := make(map[int]*threshold.Round1Data)
for _, s := range signers {
round1Data[s.Round1(sessionID, prfKey, signerIDs).PartyID] = ...
}
// Round 2
round2Data := make(map[int]*threshold.Round2Data)
for _, s := range signers {
data, err := s.Round2(sessionID, message, prfKey, signerIDs, round1Data)
round2Data[data.PartyID] = data
}
// Finalize + Verify
sig, err := signers[0].Finalize(round2Data)
valid := threshold.Verify(groupKey, message, sig)Build and test
make build # bin/ringtail
make test # go test -v -timeout 30s ./...
make test-race # Tests with race detector
make bench # Benchmarks with -benchmem
make coverage # HTML coverage report
make ci # fmt, vet, lint, test-race, coverage, buildRunning
# Local simulation (no networking)
./bin/ringtail l 1 3 # l=local, 1=iterations, 3=parties
# Distributed P2P (one terminal per party)
./bin/ringtail 0 1 3 # Party 0 = trusted dealer
./bin/ringtail 1 1 3 # Party 1 = combiner
./bin/ringtail 2 1 3 # Party 2 = signerTroubleshooting
| Issue | Cause | Solution |
|---|---|---|
| MAC verification failed | Corrupted network data or wrong MAC keys | Check TCP connectivity; ensure all parties use same dealer key |
| NTT panic | Ring dimension mismatch | Ensure LogN matches across all parties |
| Full rank check failed | Degenerate commitment matrix | Retry with fresh randomness (rare) |
| Connection refused in P2P mode | Party not started in time | Start all parties before TCP timeout |
| Slow benchmarks | Large party count | Start with 3 parties; computation scales with K |
Related Skills
lux/lux-lattice.md-- Ring polynomial library (RLWE, NTT, sampling)lux/lux-crypto.md-- Classical crypto primitives (BLS, secp256k1)lux/lux-consensus.md-- Quasar consensus (consumes Ringtail for PQ certificates)lux/lux-threshold.md-- Threshold cryptography abstractionslux/lux-fhe.md-- Homomorphic encryption (shares lattice foundations)
Last Updated: 2026-03-13