LPsLux Proposals
Precompiles
LP-3501

SLH-DSA Signature Precompile

Review

Native precompile for NIST FIPS 205 SLH-DSA (SPHINCS+) hash-based post-quantum signatures

Category
Core
Created
2025-11-13

Abstract

This LP specifies a precompiled contract for verifying SLH-DSA (Stateless Hash-based Digital Signature Algorithm) signatures as standardized in NIST FIPS 205. The precompile implements SLH-DSA-192s (security level 3, small variant) verification at address 0x0200000000000000000000000000000000000007, providing stateless hash-based quantum-resistant signatures with ~15ms verification performance.

Motivation

SLH-DSA (formerly SPHINCS+) provides unique security properties compared to ML-DSA:

  1. Hash-based security: Security relies only on hash function collision resistance, not structured lattice problems
  2. Conservative security: More conservative post-quantum assumption than lattice-based schemes
  3. Stateless: No state management required (unlike legacy hash-based schemes like XMSS)
  4. Long-term confidence: Hash functions have decades of cryptanalytic history
  5. Backup option: Provides alternative to ML-DSA if lattice problems are broken

Use Cases

  • Ultra-long-term archives: Documents meant to remain secure for 50+ years
  • Diversified security: Use alongside ML-DSA for defense-in-depth
  • Conservative applications: When lattice security is questioned
  • Audit trails: Permanent, hash-based signatures for compliance

Specification

Precompile Address

0x0200000000000000000000000000000000000007

Input Format

OffsetLengthFieldDescription
048publicKeySLH-DSA-192s public key
4832messageLengthMessage length as big-endian uint256
8016224signatureSLH-DSA-192s signature
16304variablemessageMessage to verify

Total minimum size: 16304 bytes (without message)

Output Format

32-byte word:

  • 0x...0001 - signature valid
  • 0x...0000 - signature invalid

Gas Cost

gas = BASE_COST + (messageLength * PER_BYTE_COST)

Where:
  BASE_COST = 500,000 gas (higher due to 15ms verification time)
  PER_BYTE_COST = 50 gas (higher due to multiple hash operations)

Solidity Interface

interface ISLHDSA {
    /**
     * @dev Verifies an SLH-DSA-192s signature
     * @param publicKey The 48-byte SLH-DSA-192s public key
     * @param message The message that was signed
     * @param signature The 16224-byte SLH-DSA-192s signature
     * @return valid True if signature is valid
     */
    function verify(
        bytes calldata publicKey,
        bytes calldata message,
        bytes calldata signature
    ) external view returns (bool valid);
}

Rationale

Why SLH-DSA-192s?

SLH-DSA variants:

  • 128s/128f: Level 1 (128-bit) - Small/Fast
  • 192s/192f: Level 3 (192-bit) - Recommended - Balanced
  • 256s/256f: Level 5 (256-bit) - Maximum security

We chose 192s (small, not fast) because:

  1. NIST level 3 matches our ML-DSA choice
  2. "Small" variant has smaller signatures (16KB vs 35KB for 192f)
  3. Verification time difference is minimal (15ms vs 12ms)
  4. Signature size is more important than signing speed for blockchain use

Gas Cost Justification

  • Verification time: ~15ms on Apple M1
  • Compared to ML-DSA: 139x slower (15ms vs 108μs)
  • Base cost: ML-DSA is 100K gas, so 500K is 5x (conservative multiplier)
  • Per-byte cost: 50 gas/byte due to multiple SHAKE-256 hashes

Why Both ML-DSA and SLH-DSA?

Having both provides:

  1. Algorithm diversity: If lattices are broken, hash-based still works
  2. Different trust assumptions: Lattices vs hash functions
  3. Use case optimization: ML-DSA for speed, SLH-DSA for conservatism
  4. Hybrid schemes: Can require both for maximum security

Backwards Compatibility

This LP introduces a new precompiled contract at a previously unused address. There are no backwards compatibility concerns:

  • New functionality: The precompile address 0x0200000000000000000000000000000000000007 has no prior use
  • No state changes: The precompile is stateless and read-only
  • Optional adoption: Contracts may choose to use SLH-DSA alongside existing signature schemes
  • Activation: Requires network upgrade (Quantum hard fork) for coordinated deployment

Migration Path

  1. Phase 1: Deploy precompile at activation height
  2. Phase 2: Contracts integrate SLH-DSA alongside ML-DSA (LP-311)
  3. Phase 3: Hybrid verification patterns adopted for critical applications

Security Considerations

Hash-Based Security

SLH-DSA security depends solely on:

  • SHAKE-256 collision resistance
  • No structured problems (unlike lattices)
  • Post-quantum proven security reductions

Signature Size Trade-off

Large signatures (16KB) may impact:

  • Transaction size limits
  • Storage costs
  • Bandwidth requirements

Mitigation: Use SLH-DSA selectively for high-value operations only.

Performance Impact

15ms verification is 139x slower than ML-DSA:

  • Use for critical operations where conservatism is needed
  • Batch verifications where possible
  • Consider async verification for UX

Test Cases

Test Vector 1: Valid SLH-DSA-192s Signature

publicKey: 0x<48 bytes of SLH-DSA public key>
message: "Quantum-resistant hash-based signature"
signature: 0x<16224 bytes of SLH-DSA signature>
Expected: 0x...0001 (valid)
Expected Gas: ~502,100 gas

Test Vector 2: Invalid Signature

publicKey: 0x<48 bytes>
message: "Test message"
signature: 0x<16224 bytes of WRONG signature>
Expected: 0x...0000 (invalid)

Test Vector 3: Large Message

publicKey: 0x<48 bytes>
message: 0x<10KB data>
signature: 0x<16224 bytes>
Expected Gas: ~1,012,000 gas (500K base + 512K for 10KB message)

Reference Implementation

Implementation Status: ✅ COMPLETE

See: precompiles/slhdsa/

Key Files:

  • contract.go - Core precompile implementation (114 lines)
  • module.go - Precompile registration (51 lines)
  • contract_test.go - Comprehensive test suite (130 lines)
  • ISLHDSA.sol - Solidity interface and library (133 lines)
  • README.md - Complete documentation (329 lines)

Cryptography:

  • Implementation: Uses native Go SPHINCS+ implementation
  • Standard: NIST FIPS 205 compliant
  • Variant: SLH-DSA-128s (32-byte public keys, 7,856-byte signatures)

Test Results: All tests passing with comprehensive coverage:

  • Valid signature verification
  • Invalid signature rejection
  • Tampered message detection
  • Input validation
  • Gas cost verification
  • Edge cases

Performance Benchmarks (Apple M1):

  • Verification time: ~286μs for small messages
  • Gas cost: 15,000 base + 10 gas/byte message
  • Memory usage: Minimal (~8KB per operation)

Economic Impact

Comparison to ML-DSA

MetricSLH-DSA-128sML-DSA-65Ratio
Public Key32 bytes1,952 bytes61x smaller
Signature7,856 bytes3,293 bytes2.4x larger
Verify Time~286μs~108μs2.6x slower
Base Gas15,000100,0006.7x cheaper

Use Case Guidance:

  • SLH-DSA: Long-term archives, ultra-conservative applications
  • ML-DSA: General-purpose, better performance, smaller signatures

Gas Cost Impact

SLH-DSA is CHEAPER than ML-DSA for small messages due to lower base cost:

  • 32-byte message: 15,320 gas (SLH-DSA) vs 100,320 gas (ML-DSA)
  • 1KB message: 25,240 gas (SLH-DSA) vs 110,240 gas (ML-DSA)

However, larger signatures increase storage costs.

Open Questions

  1. Should we support other SLH-DSA variants?

    • 192s/192f for higher security?
    • 256s/256f for maximum security?
    • Current implementation uses 128s for efficiency
  2. Signature aggregation?

    • Unlike BLS, SPHINCS+ signatures don't aggregate
    • Multiple signatures require multiple verifications
    • Could implement Merkle aggregation at application layer
  3. Caching strategies?

    • Should verification results be cached?
    • Trade-off: gas savings vs security concerns

Implementation Notes

Key Size Discrepancy

The spec originally referenced 48-byte keys (SLH-DSA-192s), but the implementation uses:

  • 32-byte public keys (SLH-DSA-128s)
  • 7,856-byte signatures (SLH-DSA-128s "small" variant)

This was chosen for:

  1. Smaller public keys (better for storage)
  2. Still provides 128-bit post-quantum security
  3. Smaller signatures than "fast" variant (7,856 vs 17,088 bytes)

Integration with MPC/Threshold

Unlike ML-DSA, SPHINCS+ is stateless hash-based:

  • No threshold variant exists
  • Each signer must have full secret key
  • For threshold use cases, use Ringtail (LP-320) instead

References

Copyright and related rights waived via CC0.