mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
Closes Red CRITICAL-2 (red-c-new-1). The luxcpp/accel layer's M-1
tri-state propagation (5a02e55b) was effectively defeated by Go
consumers that swallowed every error into a silent CPU fallback. The
consensus-split-prevention claim was hollow: a malformed input the
GPU rejected with INVALID_ARGUMENT would silently CPU-pass via
cloudflare/circl, which accepts arbitrary-length messages per FIPS
204. Two nodes running the same input could produce different
verdicts depending on whether they ran GPU or CPU → consensus split.
Fix: ErrInvalidArgument from accel propagates as a hard error;
ErrNotSupported, ErrOutOfMemory, ErrKernelFailed, ErrNoBackends
remain silent-fallback (they're recoverable: GPU path unavailable,
not contract violation). Three call sites updated:
* crypto/mldsa/gpu.go::batchVerifyGPU — returns (false, err) with
ErrInvalidArgument so batch.go::BatchVerify panics (no error
return, same shape as existing length-mismatch + mixed-mode
panics in the same function).
* crypto/mldsa/gpu.go::batchSignGPU — same shape; batch.go::
BatchSign already returns error so it surfaces directly.
* crypto/pq/mldsa/gpu/gpu_cgo.go::{signBatch,verifyBatch} — same
classifier; signBatch returns the error to BatchSign caller,
verifyBatch returns (nil, err) to BatchVerify caller.
Skip-list in batchVerifyGPU: when ErrInvalidArgument bubbles from
MLDSAVerifyBatch and the mode is ML-DSA-65, do NOT fall back to the
legacy DilithiumVerifyBatch path — that path runs the SAME C ABI
under a different dispatch slot and would reject again. Only mask
the legacy retry when the FIRST error was something other than
ErrInvalidArgument (NotSupported is the canonical case: a substrate
that doesn't publish the new MLDSAVerifyBatch slot but does publish
the legacy Dilithium3 kernel).
New test: pq/mldsa/gpu/invalid_argument_propagation_test.go locks
the policy in as a unit test. It verifies:
1. accel.ErrInvalidArgument exists.
2. errors.Is(...) detects it through fmt.Errorf %w wraps.
3. Other accel sentinels do not alias it.
4. The classifier ("hard" vs "recover") matches the dispatch code
for nil, ErrInvalidArgument (raw + wrapped), ErrNotSupported,
ErrOutOfMemory, ErrKernelFailed, ErrNoBackends, and an unrelated
error.
This is the propagation policy test the prompt asked for. A
real-input fault-injection test would need a > 2 GB synthetic
message (Go can't construct one in CI memory budgets) or a session
mock harness (overengineering for a single check); the policy test
locks the error-routing logic at the exact `errors.Is` boundary
where the contract lives.
luxgo crypto module version stays at current; no breaking-API change.
ML-DSA (Module-Lattice Digital Signature Algorithm) for Lux
FIPS 204 compliant implementation of ML-DSA (formerly known as ML-DSA (FIPS 204, formerly CRYSTALS-Dilithium)) post-quantum signatures.
Overview
This package provides both pure Go and CGO implementations of ML-DSA, offering quantum-resistant digital signatures for the Lux blockchain ecosystem.
Security Levels
-
ML-DSA-44 (Dilithium2): NIST Level 2 security
- Public key: 1,312 bytes
- Private key: 2,560 bytes
- Signature: 2,420 bytes
-
ML-DSA-65 (Dilithium3): NIST Level 3 security (recommended)
- Public key: 1,952 bytes
- Private key: 4,032 bytes
- Signature: 3,309 bytes
-
ML-DSA-87 (Dilithium5): NIST Level 5 security
- Public key: 2,592 bytes
- Private key: 4,896 bytes
- Signature: 4,627 bytes
Features
- Dual Implementation: Pure Go (via Cloudflare CIRCL) and optimized C (via pq-crystals/dilithium)
- FIPS 204 Compliant: Follows the NIST ML-DSA standard
- Automatic Fallback: Uses CGO when available, falls back to pure Go
- Full Test Coverage: Comprehensive tests including cross-compatibility
Building
Pure Go (default)
go build ./...
With CGO support
# Build the C library first
cd c
make
# Then build with CGO enabled
CGO_ENABLED=1 go build ./...
Building all security levels
./build.sh
Usage
import "github.com/luxfi/lux/crypto/mldsa"
// Generate key pair (ML-DSA-65 recommended)
priv, err := mldsa.GenerateKey(rand.Reader, mldsa.MLDSA65)
if err != nil {
panic(err)
}
// Sign a message
message := []byte("Hello, post-quantum world!")
signature, err := priv.Sign(rand.Reader, message, nil)
if err != nil {
panic(err)
}
// Verify signature
valid := priv.PublicKey.Verify(message, signature)
fmt.Printf("Signature valid: %v\n", valid)
// Use CGO implementation if available
if mldsa.UseCGO() {
privCGO, _ := mldsa.GenerateKeyCGO(rand.Reader, mldsa.MLDSA65)
sigCGO, _ := mldsa.SignCGO(privCGO, rand.Reader, message, nil)
validCGO := mldsa.VerifyCGO(&privCGO.PublicKey, message, sigCGO)
fmt.Printf("CGO signature valid: %v\n", validCGO)
}
Integration with Lux
This implementation is designed to integrate with:
- C-Chain: EVM precompiled contracts for ML-DSA verification
- X-Chain: UTXO-based transactions with post-quantum signatures
- P-Chain: Validator staking with quantum-resistant keys
Performance
Benchmark results (M1 Pro):
BenchmarkMLDSAKeyGen/ML-DSA-44-Go 500 2.1 ms/op
BenchmarkMLDSAKeyGen/ML-DSA-44-CGO 1000 1.3 ms/op
BenchmarkMLDSAKeyGen/ML-DSA-65-Go 300 3.8 ms/op
BenchmarkMLDSAKeyGen/ML-DSA-65-CGO 500 2.4 ms/op
BenchmarkMLDSAKeyGen/ML-DSA-87-Go 200 5.2 ms/op
BenchmarkMLDSAKeyGen/ML-DSA-87-CGO 300 3.5 ms/op
BenchmarkMLDSASign/ML-DSA-44-Go 1000 1.1 ms/op
BenchmarkMLDSASign/ML-DSA-44-CGO 2000 0.6 ms/op
BenchmarkMLDSASign/ML-DSA-65-Go 500 2.3 ms/op
BenchmarkMLDSASign/ML-DSA-65-CGO 1000 1.4 ms/op
BenchmarkMLDSASign/ML-DSA-87-Go 300 3.8 ms/op
BenchmarkMLDSASign/ML-DSA-87-CGO 500 2.2 ms/op
BenchmarkMLDSAVerify/ML-DSA-44-Go 2000 0.5 ms/op
BenchmarkMLDSAVerify/ML-DSA-44-CGO 3000 0.3 ms/op
BenchmarkMLDSAVerify/ML-DSA-65-Go 1000 0.9 ms/op
BenchmarkMLDSAVerify/ML-DSA-65-CGO 2000 0.6 ms/op
BenchmarkMLDSAVerify/ML-DSA-87-Go 500 1.5 ms/op
BenchmarkMLDSAVerify/ML-DSA-87-CGO 1000 0.9 ms/op
CGO implementation provides ~40% performance improvement.
Testing
# Run all tests
go test ./...
# Run with CGO
CGO_ENABLED=1 go test ./...
# Run benchmarks
go test -bench=. ./...
# Test C library directly
cd c && make test
Security Considerations
- Quantum Resistance: Secure against attacks by quantum computers
- Side-Channel Protection: Implementation includes countermeasures
- Deterministic Signatures: No randomness required for signing (uses deterministic nonce)
- Key Storage: Larger keys require secure storage solutions
References
- NIST FIPS 204: Module-Lattice-Based Digital Signature Standard
- pq-crystals/dilithium: Reference implementation
- Cloudflare CIRCL: Pure Go implementation
License
Copyright (C) 2025, Lux Industries Inc. All rights reserved.