mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
9a71af427fb313e20ed56560920466ce86858bbe
Three additive, fail-closed hardenings on the BLS boundary, with the security- critical regressions on the purego (CIRCL, //go:build !cgo) path — the canonical CGO_ENABLED=0 node image: HIGH-1 (panic-DoS). CIRCL's bls12381 G1/G2 SetBytes accepts the MALFORMED encoding 'infinity bit set, compression bit clear' (top byte b[0]&0xC0 == 0x40): it computes the UNCOMPRESSED length and slices b[1:96]/b[1:192] on a canonical 48/96-byte COMPRESSED buffer -> slice-bounds-out-of-range PANIC. On a purego node a single 0x40||zeros blob in a proof-of-possession / peer-handshake / warp / quasar BLS field is an unauthenticated, consensus-halting DoS. Reject b[0]&0xC0 == 0x40 at the compressed length BEFORE SetBytes, in-band (not recover()), restoring parity with blst's erroring Uncompress. Guards: PublicKeyFromCompressedBytes, SignatureFromBytes. Regression: sig_infinity_unset_compression_test.go. RESIDUAL-C (identity at one boundary). Move identity rejection to the SINGLE deserialization boundary: PublicKeyFromCompressedBytes / FromValidUncompressedBytes call Validate()/KeyValidate() (= !IsIdentity() && on-curve && in-subgroup), so an identity (or off-curve) key never escapes a constructor. Verify/VerifyProofOfPossession drop their redundant per-call identity test — which was WRONG anyway (it compared against 0x00||zeros; the canonical compressed-G1 infinity is 0xc0||zeros, so it never matched). FromValidUncompressedBytes now actually validates (was a silent _ = UnmarshalBinary). Identity-aggregate (defence in depth). AggregatePublicKeys now rejects an aggregate that is the IDENTITY (point at infinity). Each input is a valid non-identity subgroup key, and the subgroup is closed under addition — but the sum can still be O when inputs sum to zero (the rogue-key shape pk + (-pk) = O). An identity aggregate public key makes Verify trivially accept the identity signature (a forgery enabler). PoP at registration already blocks an attacker contributing an unpossessed key, but the verifier must not depend on that everywhere: purego result.Validate() and cgo out.KeyValidate() fail the aggregate closed. Regression (agg_identity_reject_test.go): pk + -pk must error; proven to FAIL without the guard (returns a usable identity key); a legitimate two-key aggregate still succeeds. Full bls suite green on both backends (CGO_ENABLED=0 and =1).
Lux Crypto
Cryptographic primitives for the Lux Network -- post-quantum signatures, key encapsulation, BLS aggregation, threshold signing, ring signatures, and EVM-compatible secp256k1.
go get github.com/luxfi/crypto
Architecture
luxfi/crypto is the cryptographic foundation for all Lux software. It provides both classical and post-quantum primitives, with automatic CGO acceleration where available (blst for BLS, circl for lattice schemes). The pure-Go fallback path requires no C compiler.
Post-Quantum (NIST FIPS 203/204/205)
| Package | Algorithm | Standard | Security | Key Sizes |
|---|---|---|---|---|
mldsa/ |
ML-DSA | FIPS 204 | 128/192/256-bit (Levels 2/3/5) | 44: 1312/2560 B, 65: 1952/4032 B, 87: 2592/4896 B |
mlkem/ |
ML-KEM | FIPS 203 | 128/192/256-bit | 512: 800/1632 B, 768: 1184/2400 B, 1024: 1568/3168 B |
slhdsa/ |
SLH-DSA (FIPS 205, formerly SPHINCS+) | FIPS 205 | 128/192/256-bit (12 variants) | SHA2/SHAKE, fast/small tradeoff |
pq/ |
Unified PQ interface | -- | Wraps mldsa, mlkem, slhdsa | Mode selection at runtime |
ML-DSA and ML-KEM wrap Cloudflare's circl with ergonomic key serialization. SLH-DSA provides hash-based signatures as a conservative fallback (no lattice assumptions).
Classical
| Package | Algorithm | Use |
|---|---|---|
bls/ |
BLS12-381 (G1 keys, G2 signatures) | Consensus signatures, aggregation, proof-of-possession |
secp256k1/ |
secp256k1 ECDSA | EVM transaction signing, Ethereum compatibility |
secp256r1/ |
P-256 ECDSA | TLS, WebAuthn, FIDO2 |
ecies/ |
ECIES (secp256k1) | Asymmetric encryption for Ethereum-compatible keys |
Threshold and Multi-Party
| Package | Protocol | Use |
|---|---|---|
threshold/ |
Threshold signature framework | Interface + registry for pluggable threshold schemes |
threshold/bls/ |
BLS threshold signatures | t-of-n BLS signing for consensus |
cggmp21/ |
CGGMP21 (ECDSA threshold) | MPC key generation and signing, Paillier commitments |
Advanced Constructions
| Package | Construction | Use |
|---|---|---|
ring/ |
Ring signatures (LSAG + lattice-based) | Unlinkable signer anonymity |
lamport/ |
Lamport one-time signatures | Hash-based PQ signatures (stateful) |
hpke/ |
Hybrid Public Key Encryption | ML-KEM + X25519 hybrid, KEM factory |
kem/ |
KEM abstraction | ML-KEM, X25519, hybrid combiner |
aead/ |
AEAD ciphers | AES-256-GCM, ChaCha20-Poly1305 |
kdf/ |
Key derivation | HKDF, SLIP-10 HD derivation |
verkle/ |
Verkle tree commitments | State proof compression |
kzg4844/ |
KZG commitments (EIP-4844) | Blob transaction proofs |
ipa/ |
Inner product arguments | Verkle proof backend |
Infrastructure
| Package | Purpose |
|---|---|
common/ |
Address, Hash types (20-byte, 32-byte) |
hash/, hashing/ |
Keccak256, SHA256, RIPEMD160, Blake2b |
rlp/ |
RLP encoding (Ethereum wire format) |
cb58/ |
CB58 encoding (Lux address format) |
cert/ |
TLS certificate management for node identity |
signer/ |
Transaction signing abstraction |
sign/ |
Signature scheme registry |
secret/ |
Secret-safe memory operations (zeroing, constant-time) |
address/ |
Multi-chain address derivation |
gpu/ |
GPU-accelerated modular arithmetic bindings |
bindings/ |
C/Rust FFI exports |
BLS Signatures
import "github.com/luxfi/crypto/bls"
sk, _ := bls.NewSecretKey()
pk := bls.PublicFromSecretKey(sk)
sig := bls.Sign(sk, []byte("block hash"))
valid := bls.Verify(pk, sig, []byte("block hash"))
// Aggregation
aggSig, _ := bls.AggregateSignatures(sig1, sig2, sig3)
aggPK, _ := bls.AggregatePublicKeys(pk1, pk2, pk3)
valid = bls.Verify(aggPK, aggSig, msg)
Post-Quantum Signatures (ML-DSA)
import "github.com/luxfi/crypto/mldsa"
sk, pk, _ := mldsa.GenerateKey(mldsa.MLDSA87) // NIST Level 5
sig, _ := sk.Sign(rand.Reader, data, nil)
valid := pk.VerifySignature(data, sig)
Post-Quantum Key Encapsulation (ML-KEM)
import "github.com/luxfi/crypto/mlkem"
sk, pk, _ := mlkem.GenerateKey(mlkem.MLKEM1024) // NIST Level 5
ciphertext, sharedSecret, _ := pk.Encapsulate()
recovered, _ := sk.Decapsulate(ciphertext)
// sharedSecret == recovered (32 bytes, use as AES key)
Hybrid HPKE
import "github.com/luxfi/crypto/hpke"
// ML-KEM-1024 + X25519 hybrid
suite := hpke.NewHybridSuite()
enc, ct, _ := suite.Seal(recipientPK, plaintext, aad)
pt, _ := suite.Open(recipientSK, enc, ct, aad)
Testing
go test ./... # 382 test functions
go test -bench=. ./... # benchmarks
Compiled test binaries are provided for quick verification:
bls.test-- BLS signature testsmldsa.test-- ML-DSA testsmlkem.test-- ML-KEM testsslhdsa.test-- SLH-DSA testscrypto.test-- Core crypto tests
Papers
- Lux PQ Crypto Suite -- parameter selection and security analysis for ML-DSA, ML-KEM, SLH-DSA
- Lux Hybrid PQ Architecture -- hybrid classical/PQ transition strategy
- Lux Crypto Agility -- algorithm negotiation and migration framework
- Lux Pulsar PQ -- post-quantum ring signatures
- Lux Universal Threshold Signatures -- multi-curve threshold framework
References
- NIST FIPS 203: ML-KEM (Module-Lattice-Based Key-Encapsulation Mechanism)
- NIST FIPS 204: ML-DSA (Module-Lattice-Based Digital Signature Algorithm)
- NIST FIPS 205: SLH-DSA (Stateless Hash-Based Digital Signature Algorithm)
- Cloudflare circl -- underlying lattice implementations
- BLS12-381 -- pairing-friendly curve specification
License
Lux Ecosystem License v1.2. See LICENSE.
Description
Core cryptographic primitives for Lux: high-performance hash functions (SHA-2/3), symmetric ciphers, ECDSA & BLS signatures, HKDF key derivation, and lattice-based post-quantum schemes.
167 MiB
Languages
C
48.2%
Go
41.3%
Rust
4%
Assembly
1.3%
Sage
0.9%
Other
4.2%