14 KiB
Threat Model
UltrafastSecp256k1 v3.22.0 -- Layer-by-Layer Risk Assessment
Architecture Overview
+-----------------------------------------------------------------+
| Application Layer |
| (Wallet, Signer, Verifier, Key Manager, Address Generator) |
+--------------+---------------+-------------------+--------------+
| Coins (27) | HD (BIP-32) | Taproot/MuSig2 | FROST/Adaptor|
+--------------+---------------+-------------------+--------------+
| ECDSA (RFC 6979) | Schnorr (BIP-340) | Pedersen |
+-----------------------------------------------------------------+
| FAST (variable-time) | CT (constant-time) |
| secp256k1::fast:: | secp256k1::ct:: |
+-----------------------------------------------------------------+
| Field / Scalar / Point core (4x64 limbs) |
+-----------------------------------------------------------------+
| CPU (x64 BMI2/ADX, ARM64, RISC-V, Xtensa, Cortex-M3) |
| GPU (CUDA PTX, ROCm/HIP, OpenCL 3.0, Metal) |
| WASM (Emscripten) |
+-----------------------------------------------------------------+
See docs/ARCHITECTURE.md for detailed technical architecture. See AUDIT_GUIDE.md for the auditor navigation guide.
Layer Definitions
1. FAST Layer (Default)
Purpose: Maximum throughput for public-key operations, verification, and research.
| Property | Value |
|---|---|
| Constant-time | No |
| Secret key handling | Not safe |
| Intended use | Verification, batch processing, benchmarking |
| Threat | Side-channel attacks if used with secrets |
| Mitigation | Use ct:: namespace for any secret-dependent operation |
Variable-time algorithms may leak information about operands through timing, cache access patterns, or branch prediction state. This is acceptable only when all operands are public (e.g., signature verification, public key derivation from known scalars).
2. CT Layer (ct:: namespace)
Purpose: Side-channel resistant operations for secret key material.
| Property | Value |
|---|---|
| Constant-time | Yes (no secret-dependent branches or memory access) |
| Secret key handling | Designed for this |
| Performance penalty | ~5-7x vs FAST |
| Threat | Compiler optimization may break CT guarantees |
| Mitigation | Sanitizer builds (ASan, TSan), manual inspection, -O2 only |
The CT layer provides complete addition formulas, constant-time field inversion (SafeGCD), and timing-safe scalar multiplication. The library automatically erases secret-derived intermediates in CT signing paths (ct::ecdsa_sign, ct::schnorr_sign) via secure_erase -- callers only need to erase their own copies of private keys.
Known limitation: Formal verification via ct-verif LLVM pass and Valgrind CT taint analysis is in CI, but Vale-level machine-checked proofs have not been applied.
3. GPU Backends (CUDA, ROCm, OpenCL, Metal)
Purpose: High-throughput batch operations on GPU hardware.
| Property | Value |
|---|---|
| Constant-time | No |
| Secret key handling | Not safe |
| Intended use | Batch verification, public key generation, search |
| Threat | GPU memory may be observable; no CT guarantees on device |
| Mitigation | Use GPU only for public-data workloads |
GPU kernels are variable-time by design. Device memory is not zeroed. Do not pass secret keys to GPU kernels.
4. Signature Schemes (ECDSA, Schnorr, MuSig2, FROST, Adaptor)
Purpose: Digital signatures and multi-party signing protocols.
| Property | Value |
|---|---|
| Nonce generation | Deterministic (RFC 6979 for ECDSA) |
| Input validation | Point-on-curve, scalar range checks |
| Threat | Nonce reuse -> private key recovery |
| Mitigation | RFC 6979 eliminates random nonce dependency |
MuSig2, FROST, and Adaptor Signatures are experimental. Their APIs may change and they have not been independently reviewed.
5. HD Derivation & Coin Dispatch
Purpose: BIP-32/44 key derivation and 27-coin address generation.
| Property | Value |
|---|---|
| Key derivation | BIP-32 (hardened + normal) |
| Address generation | Coin-specific encoding (Base58, Bech32, etc.) |
| Secret handling | Derived keys are secret; use CT layer for signing |
| Threat | Incorrect derivation path -> wrong keys |
| Mitigation | Test vectors from BIP-32/44 specifications |
The coin dispatch layer generates addresses only. It does not store keys, manage UTXOs, or broadcast transactions.
6. Batch Operations & Multi-Scalar
Purpose: Batch inverse (Montgomery trick), multi-scalar multiplication.
| Property | Value |
|---|---|
| Allocation | Zero heap allocation (scratchpad model) |
| Threat | Incorrect batch inverse -> silent wrong results |
| Mitigation | Sweep-tested up to 8192; boundary KAT vectors; fuzz harness |
7. Zero-Knowledge Proof Layer (secp256k1::zk)
Added in v3.22.0. Provides non-interactive ZK proofs over secp256k1:
| Primitive | Description | Security Property |
|---|---|---|
| Knowledge Proof | Prove knowledge of discrete log (P = x*G) | Completeness, soundness, zero-knowledge |
| DLEQ Proof | Prove equality of discrete logs (P = xG and Q = xH) | Completeness, soundness, zero-knowledge |
| Bulletproof Range Proof | Prove committed value ∈ [0, 2⁶⁴) | Completeness, soundness, perfect hiding |
| Property | Value |
|---|---|
| Proving | Uses CT layer (constant-time nonce derivation) |
| Verification | Uses FAST layer (variable-time, public data only) |
| Fiat-Shamir | Tagged SHA-256 (domain-separated per proof type) |
| Nonce hedging | Deterministic + auxiliary randomness (same design as RFC 6979 hedged) |
Threat vectors specific to ZK layer:
| Vector | Risk | Mitigation |
|---|---|---|
| Nonce reuse in knowledge proof | CRITICAL — reveals secret | Deterministic + hedged nonce derivation; CT proving path |
| Soundness break (forged proof) | HIGH | Audited via tampered-proof rejection tests (~300 rejection checks in audit_zk.cpp) |
| Fiat-Shamir weak domain separation | MEDIUM | Tagged SHA-256 with unique prefix per proof type |
| Bulletproof generator malleability | MEDIUM | Nothing-up-my-sleeve generators (hash-to-curve); cached after first derivation |
| ZK proof reveals secret via timing | MEDIUM | Proving path uses ct:: namespace throughout |
| Batch verification shortcut forgery | LOW | Batch verify independently validates each proof; no shortcut |
⚠️ Status (v3.22.0): API experimental. ZK primitives have internal audit coverage (audit_zk.cpp, ~1,500 checks) but have not undergone independent third-party review. Bulletproof soundness is not formally proven for this implementation.
8. Ethereum Signing Layer (secp256k1::eth)
Added in v3.22.0. Provides Ethereum-specific signing (EIP-191, EIP-155, ecrecover):
| Primitive | Description | Risk |
|---|---|---|
eip191_hash |
EIP-191 personal message hash (Keccak-256 with prefix) | Incorrect prefix -> wrong hash, silent signing failure |
eth_sign_hash / eth_personal_sign |
RFC 6979 ECDSA + EIP-155 v encoding | Wrong chain ID -> replay attacks on other chains |
ecrecover |
Ethereum precompile 0x01 -- recover address from signature | Incorrect recovery -> wrong address, silent auth failure |
| Threat | Risk | Mitigation |
|---|---|---|
| Wrong chain ID in EIP-155 v encoding | HIGH — cross-chain replay | eip155_v() / eip155_chain_id() round-trip tested; 32 Ethereum test cases |
| Non-standard Keccak-256 (not SHA3) | HIGH — hash mismatch | Library uses secp256k1 Keccak-256, not SHA3; cross-validated against known ETH addresses |
| ecrecover returns wrong signer | CRITICAL | ecrecover cross-validated against Ethereum test vectors |
personal_sign prefix mangling |
MEDIUM | Tested with known Ethereum MetaMask-compatible vectors |
Trust Boundaries
TRUSTED (this library controls):
+- Arithmetic correctness (field, scalar, point)
+- CT layer timing properties
+- Deterministic nonce generation
+- Input validation (on-curve, range)
NOT TRUSTED (caller responsibility):
+- Key storage and lifecycle
+- Buffer zeroing after use
+- Choosing FAST vs CT appropriately
+- Network security / transport
+- Entropy source (if any randomness needed)
What This Library Does NOT Protect Against
- Physical attacks (power analysis, EM emanation, fault injection)
- Compromised compilers or build environments
- OS-level memory disclosure (cold boot, swap file, core dumps)
- Application-level misuse (wrong profile selection, key reuse)
- Quantum adversaries (secp256k1 is not post-quantum)
Attack Surface Analysis
A1: Timing Side Channels
| Vector | Risk | Mitigation |
|---|---|---|
| Variable-time scalar mul leaking secret bits | HIGH (if fast:: used with secrets) |
Always use ct:: for secret-dependent ops |
| Variable-time field inversion | MEDIUM | CT inversion uses fixed-length chain |
| Cache-timing on table lookups | MEDIUM | CT uses linear scan + cmov, not indexed |
| Compiler-introduced branches | MEDIUM | asm volatile barriers, -O2 recommended |
| Microarchitecture-specific timing | LOW | dudect testing on x86-64, ARM64 |
Testing: tests/test_ct_sidechannel.cpp -- dudect Welch t-test, |t| < 4.5
A2: Nonce Attacks
| Vector | Risk | Mitigation |
|---|---|---|
| ECDSA random nonce reuse -> key recovery | CRITICAL | RFC 6979 deterministic nonces (no randomness needed) |
| Biased nonces -> lattice attack | HIGH | RFC 6979 provides uniform distribution |
| Schnorr nonce bias | HIGH | BIP-340 tagged hash nonce derivation |
| FROST nonce mishandling | MEDIUM | Experimental -- under review |
A3: Arithmetic Errors
| Vector | Risk | Mitigation |
|---|---|---|
| Incorrect field reduction | CRITICAL | 641,194 audit checks, fuzz testing |
| Point addition edge cases (P+P, P+O, P+(-P)) | CRITICAL | Complete addition formulas in CT, sweep tests |
| GLV decomposition error | HIGH | Reconstruction test: k1+k2*lambda == k for random k |
| SafeGCD inverse error | HIGH | Cross-checked against Fermat chain |
| Batch inverse corrupting elements | MEDIUM | Sweep-tested up to 8192 elements |
A4: Memory Safety
| Vector | Risk | Mitigation |
|---|---|---|
| Buffer overflow in field/scalar ops | CRITICAL | Fixed-size POD types, no dynamic allocation |
| Use-after-free | HIGH | ASan in CI, no heap pointers in hot path |
| Uninitialized memory reads | MEDIUM | Valgrind memcheck (weekly CI) |
| Stack-based secret leakage | MEDIUM | Library erases CT signing intermediates; caller zeros own copies |
A5: Supply Chain
| Vector | Risk | Mitigation |
|---|---|---|
| Compromised dependency | HIGH | Dependabot, Dependency Review, SLSA attestation |
| Malicious PR injection | HIGH | Branch protection, CODEOWNERS, required reviews |
| Build reproducibility | MEDIUM | Docker SHA-pinned, deterministic builds |
| Typosquatting (npm/vcpkg) | LOW | Official package names documented |
A6: GPU-Specific
| Vector | Risk | Mitigation |
|---|---|---|
| GPU shared memory observable | HIGH | GPU is for public data ONLY |
| Branch divergence leaking data | HIGH | No CT guarantees on GPU |
| Device memory not zeroed | MEDIUM | Do not pass secrets to GPU |
| PCIe bus snooping | LOW | Physical access required |
Recommendations for Integrators
- Always use
ct::for secret scalar operations (signing, key derivation) - Zero your own private key copies after use -- the library erases its intermediates automatically via
secure_erase(volatile trick +explicit_bzero+std::atomic_signal_fence) - Build with sanitizers regularly (
cpu-asan,cpu-tsanpresets) - Run selftest on startup (
Selftest(false, SelftestMode::smoke)) - Do not expose GPU memory to untrusted contexts
- Pin your dependency version -- API may change before v4.0
- Review CT_VERIFICATION.md for known constant-time limitations
- Use
-O2for production CT builds -- higher levels may break CT properties - Run dudect test on your target hardware before deployment
Automated Security Measures (v3.22.0)
| Measure | Frequency | What It Catches |
|---|---|---|
| CodeQL | Every push/PR | Static security bugs, injection, overflow |
| OpenSSF Scorecard | Weekly | Supply-chain weaknesses |
| Security Audit CI | Push/PR + weekly | Compiler warnings (-Werror), memory errors, UB |
| Clang-Tidy (30+ checks) | Every push/PR | Bugprone patterns, cert violations |
| SonarCloud | Every push/PR | Code quality, security hotspots |
| ASan + UBSan | CI | Address errors, undefined behavior |
| TSan | CI | Data races, thread safety |
| Valgrind | Weekly | Memory leaks, invalid access |
| Valgrind CT taint | CI | Secret-dependent branches (CLASSIFY/DECLASSIFY) |
| dudect timing analysis | CI | Side-channel timing leaks (Welch t-test) |
| ct-verif LLVM pass | CI | Compile-time CT verification |
| Fiat-Crypto linkage | CI | Formally verified field arithmetic cross-check |
| Wycheproof vectors | CI | ECDSA/ECDH invalid input rejection (89+36 cases) |
ZK Proof audit (audit_zk) |
CI | Knowledge/DLEQ/Bulletproof correctness + rejection (~1,500 checks) |
| MSan (Memory Sanitizer) | CI | Uninitialized read detection (instrumented libc++) |
| Mutation testing | Scheduled | Verifies tests detect injected faults |
| Performance regression gate | Every push/PR | Blocks merge if any op regresses >50% |
| Dependabot | Daily | Vulnerable dependency updates |
| Dependency Review | Every PR | New vulnerable dependencies |
| SLSA Attestation | Every release | Build provenance verification |
| libFuzzer | Continuous | Random input crashes |
Related Documents
| Document | Purpose |
|---|---|
| AUDIT_GUIDE.md | Auditor navigation and checklist |
| AUDIT_REPORT.md | Internal audit report (v3.9.0 baseline; test suite has been restructured since) |
| SECURITY.md | Vulnerability reporting, production readiness |
| docs/ARCHITECTURE.md | Technical architecture deep-dive |
| docs/CT_VERIFICATION.md | Constant-time methodology |
| docs/TEST_MATRIX.md | Test coverage matrix |
UltrafastSecp256k1 v3.17.0 -- Threat Model