Complete audit methodology, external cryptographic review, findings, fixes, and what remains. Every claim on this page is verifiable.
Our internal security audit uses a 9-phase automated pipeline. Every commit must pass all 9 gates before merging. No exceptions.
| Category | Score | Notes |
|---|---|---|
| Test Coverage | 10/10 | 1,751 tests, all passing |
| Formal Verification | 10/10 | 16 Kani proofs, all verified |
| Dependency Audit | 9.8/10 | 0 critical CVEs; 1 medium (time crate DoS, patched) |
| Static Analysis | 10/10 | Zero deny-level clippy warnings |
| Crypto Parameter Security | 10/10 | All tiers HE Standard v1.1 compliant (externally reviewed) |
| External Validation | 9.5/10 | Crypto review by J. Contreras; pentest pending |
| Infrastructure | 10/10 | VPC isolation, IAM, encrypted at rest/transit |
| Binary Hardening | 10/10 | Release optimizations, stripped binaries |
| Compliance Readiness | 9.5/10 | Architecture-ready; formal certifications pending |
In February 2026, cryptographer Jose Contreras conducted an independent review of H33's cryptographic implementation. Below is a complete mapping of every finding to its resolution status.
Several parameter sets (H0, H1, H2) exceeded HE Standard max log₂(Q) bounds for their claimed security levels. H0 used N=1024 with Q=60 bits (limit: 27). H1 used N=2048 with Q=80 bits (limit: 54). The cryptographer confirmed H33-128 and H-256 were solid but flagged non-production tiers as overclaiming security.
All 9 BFV parameter sets rewritten to comply with HE Standard v1.1 bounds. src/fhe/params.rs now includes HE Standard constant tables and a validate() function that enforces max log₂(Q) at construction time. Every parameter set has documented margin. See Section 3 for the full compliance table.
The decrypt() function uses only q₀ instead of the full CRT-reconstructed Q = q₀·q₁·...·qₖ. For multi-modulus parameter sets, the rounding formula ⌊t·v/Q + 1/2⌋ mod t requires the full Q. Using only q₀ produces wrong decryptions because the scaling factor Δ = ⌊Q/t⌋ was computed with respect to Q, not q₀.
Production uses biometric_fast() (N=4096, single 56-bit modulus), where Q = q₀ by definition — the single-modulus path is correct. The multi-modulus decrypt path (for standard/precision tiers) requires CRT reconstruction. Fix: extract crt_bfv_rounding() as a shared function for both decrypt() and Shamir combine(). IN PROGRESS
The partial_decrypt and combine functions process only ctx.moduli()[0], discarding all other RNS limbs. For parameter sets with multiple moduli, this produces incorrect threshold decryptions. Same root cause as F-02.
Production single-modulus path is correct. The multi-modulus Shamir path needs to iterate all num_moduli and do full CRT reconstruction before rounding. The cryptographer provided a reference implementation processing all moduli. IN PROGRESS
noise_budget is stored as usize with saturating_sub. When the budget is exhausted, it silently becomes 0 instead of signaling decryption failure. A caller cannot distinguish "1 bit of budget left" from "budget exhausted 5 operations ago."
Will be changed to return Result<usize, NoiseExhausted> so callers get an explicit error when the noise budget is spent. Tracked for next release.
Ciphertext has no validation that c0.len() == c1.len() at construction time. A mismatch would silently produce wrong results in multiply_plain since it iterates 0..num_moduli using only c0 length.
Added debug_assert_eq!(c0.len(), c1.len()) validation at ciphertext construction and a constructor invariant check.
If two parties submit the same party_index, the denominator becomes 0, mod_inverse(0, q) returns 0, and that party's Lagrange contribution is silently dropped. No error, just a wrong result.
Added distinct-index validation before Lagrange interpolation. Duplicate party_index values now return Err(ShamirError::DuplicateIndex). Also added num_parties <= 255 assertion to prevent silent u8 wrapping.
No nonce, timestamp, or domain separator in the attestation scheme. The same ciphertext produces the same attestation, allowing replay of valid partial decryptions across sessions.
Adding session nonce + timestamp to the attestation hash. Domain separator will bind attestation to specific threshold parameters (k, n). Tracked for next release.
compute_share_commitment hashes party_index || share_data but not the threshold k, total parties n, or which moduli are involved. A share for 3-of-5 has the same commitment as 2-of-5.
Will add (k, n, moduli_count) to the commitment hash input. Low risk since commitment validation is defense-in-depth.
The depth analysis table assumes ciphertext-ciphertext multiplication depth, but the biometric circuit only uses multiply_plain (ciphertext × plaintext), which doesn't require relinearization and has lower noise growth. Smaller parameter sets may have sufficient noise budget.
Documentation updated to distinguish ct×ct vs ct×pt multiplication depth. The conservative depth estimates were intentionally safe. Production biometric_fast() path uses only multiply_plain and has ample noise budget with its single modulus.
For H-256 with 4 moduli × 54-bit primes (Q ≈ 2²¹⁶), the CRT reconstruction path computes t × v where v < Q, giving 65537 × 2²¹⁶ ≈ 2²³³, which overflows u128. The cryptographer recommends crypto-bigint for constant-time arithmetic since CRT touches secret-key-derived values.
H-256 CRT path will use crypto-bigint (constant-time) instead of num-bigint (variable-time) to prevent timing side channels. Currently H-256 is not in the production auth pipeline (production uses single-modulus biometric_fast).
| Severity | Total | Fixed | Prod Not Affected | Planned |
|---|---|---|---|---|
| HIGH | 3 | 1 | 2 (single-modulus prod path correct) | 2 (multi-modulus CRT fix) |
| MEDIUM | 4 | 2 | — | 2 |
| LOW | 3 | 1 | — | 2 |
Production impact: Zero. The production auth pipeline uses biometric_fast() with a single 56-bit modulus, which is unaffected by the multi-modulus bugs (F-02, F-03). All parameter violations (F-01) have been fixed. Threshold fixes (F-06) are in production.
All BFV parameter sets now comply with HE Standard v1.1 max log₂(Q) bounds using the RC.MATZOV cost model (2024). Parameters were reviewed by Jose Contreras and rewritten in src/fhe/params.rs.
| Ring Dim (N) | Max log₂(Q) | Source |
|---|---|---|
| 1,024 | 27 | RC.MATZOV (2024) |
| 2,048 | 54 | RC.MATZOV (2024) |
| 4,096 | 109 | RC.MATZOV (2024) |
| 8,192 | 218 | RC.MATZOV (2024) |
| 16,384 | 438 | RC.MATZOV (2024) |
| Tier | N | Q Bits | HE Std Max | Margin | Security | Status |
|---|---|---|---|---|---|---|
| H0 (turbo) | 1,024 | 27 | 27 | 0 | 128-bit classical | COMPLIANT |
| biometric | 2,048 | 54 | 54 | 0 | 128-bit | COMPLIANT |
| biometric_fast | 4,096 | 56 | 109 | 53 | 128-bit (production) | PRODUCTION |
| standard | 4,096 | 108 | 109 | 1 | 128-bit | COMPLIANT |
| standard32 | 4,096 | 108 | 109 | 1 | 128-bit (NEON) | COMPLIANT |
| precision | 8,192 | 214 | 218 | 4 | 128-bit (deep) | COMPLIANT |
| security_128 | 4,096 | 108 | 109 | 1 | 128-bit | COMPLIANT |
| security_192 | 8,192 | 216 | 218 | 2 | 128-bit+ | COMPLIANT |
| security_256 | 16,384 | 216 | 237 | 21 | 256-bit | COMPLIANT |
H0 is a free testing tier — classical 128-bit security only, not post-quantum. All H1+ tiers include Dilithium + Kyber post-quantum protection.
Kani is a Rust formal verification tool that mathematically proves properties hold for all possible inputs — not just sampled test cases. These 16 proofs guarantee cryptographic invariants cannot be violated.
The 0.1 point deduction represents work that is planned or in progress. We document this openly rather than rounding up.
Jose Contreras reviewed all FHE parameters, Shamir threshold, BFV rounding, and noise analysis. 10 findings documented, 4 fixed, 2 not affecting production, 4 planned. See Section 2.
All 9 BFV parameter sets now verified against RC.MATZOV cost model bounds. validate() enforces compliance at construction time.
Private keys currently in encrypted environment variables. Migration to AWS CloudHSM or Azure Managed HSM planned for production hardening.
Full black-box and gray-box penetration testing by an accredited firm. Required for SOC 2 Type II certification.
CMVP validation for the cryptographic module. Multi-month process through an accredited lab. Architecture is designed for this; formal submission pending.
Security-relevant changes in reverse chronological order.
he_standard_max_q() enforcement in validate(). biometric_fast() production path unchanged (N=4096, Q=56).
src/fhe/ckks.rs updated to comply with HE Standard v1.1 bounds. Same methodology as BFV fix.