Files
crypto/mldsa
Hanzo AI 333b13fc9c mldsa: propagate accel.ErrInvalidArgument as hard error (Red CRITICAL-2)
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.
2026-06-05 02:38:14 -07:00
..

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

License

Copyright (C) 2025, Lux Industries Inc. All rights reserved.