Parameters
Here “≥120-bit” means a concrete
lattice-estimate, computed by the in-repo
via-estimator crate
code: a classical
core-SVP primal-uSVP model, calibrated against
the Homomorphic Encryption Security Standard 128-bit anchors and
validated by reproducing the authors’ own
correctness figure (\(\log_2 P_{\text{fail}}=-43.4\)) exactly. It
reads the shipped presets, so it audits the same
constants the code runs. It is deliberately conservative (a
single-attack estimate, ±~5 bits); an independent
malb/lattice-estimator
run (the original external analyst) reported somewhat
higher security numbers, but the two agree on every
qualitative verdict below. Run it with
cargo run -p via-estimator.
The gap
VIA exposes two independent lattice instances to the server, and the scheme’s security is the minimum of the two1: the large ring \(\mathcal R_{n_1,q_1}\) (the query, conversion keys, and gate keys), and the small ring \(\mathcal R_{n_2,q_3}\) carried by the ring-switching key under the small-ring secret \(S_2\). Running each through the lattice estimator inference2:
| Instance | \((n,\ \log_2 q)\) | Secret | Estimate (classical) |
|---|---|---|---|
| Large ring | \((2048,\ 75)\) | Gaussian \(\sigma{=}32\) paper | 96.2 bits |
| Small ring | \((512,\ 23)\) | Gaussian \(\sigma{=}26\) paper | 95.3 bits |
| Large ring | \((2048,\ 75)\) | ternary code | 89.2 bits |
| Small ring | \((512,\ 23)\) | ternary code | 77.5 bits ← binding |
Two facts fall out inference
(figures from via-estimator; it is conservative, so
read them as a floor):
- Under the paper’s Gaussian distributions our estimator puts both rings at \(\approx\!95\–96\). The external malb run reported \(\approx\!110\) here (matching the paper’s claim); the ~14-bit gap is our model’s built-in conservatism. Both tools agree the paper’s own parameters are a sub-128 operating point.
-
But
via-rsruns ternary keys, not the paper’s Gaussians (the Gaussian preset is inert — A4). That substitution drops the large ring to \(\approx\!89\) and the small ring to \(\approx\!77\) (malb: ~101 / ~87). The small ring at \(n_2=512\) is the binding instance, and no choice of modulus rescues 512 dimensions to 120 bits. (Yue et al.’s measured ~72/88 were taken on the C++ owniai/VIA, a third parameter set again3.)
Either way, the shipped code is a sub-90-bit scheme on the binding small ring (our \(\approx\!77\), malb’s \(\approx\!87\)) — 40+ bits short of a 120-bit target.
Method
A credible “≥120-bit” claim has to clear two independent gates, computed with tools, not asserted:
-
Security.
via-estimator::latticecode: a classical core-SVP primal-uSVP (Bai–Galbraith) estimate, run on each exposed \((n,q,\chi_s,\chi_e)\). Calibrated against the Homomorphic Encryption Security Standard 128-bit anchors (\(n{=}2048,\ q{=}2^{54},\ \text{ternary}\to128.0\) bits after a single documented offset; residual spread ±3, so ±~5 bits overall)2. -
Correctness.
via-estimator::noisecode: the paper’s Appendix-C recursion, reimplemented and validated against the authors’ own erratum: with the erratum gadget bases at the paper’s \(n_1{=}2048\) it reproduces \(\log_2 P_{\text{fail}} = -43.4\) against the \((q_3{-}q_4)/p\) threshold — exactly the authors’ stated number, once the failure bound is taken as a union over the \(n_2\) decoded record coefficients4. Decoding is then also evaluated at the final modulus \(q_4\) (threshold \(\Delta/2 = \lfloor q_4/2p\rfloor\)), which Yue Chen argues — and we concur — is the correct decode point (A5).
Why both rings must grow (and ternary is forced)
The instantiation below raises both ring dimensions. Each increase is forced by a collision of constraints, not chosen for comfort — which is exactly why the 120-bit profile departs from the paper’s.
1. The large ring cannot stay at \(n_1=2048\)
At \(n_1=2048\) with ternary keys, 120-bit security needs \(\log_2 q_1 \lesssim 56\) inference (our estimator gives 128.0 bits at \(q_1{=}2^{54}\), 123.0 at \(2^{56}\), and only 89.2 at the published \(2^{75}\); malb reports ~101 there). But \(q_1\) is also bounded from below by correctness: the DMux output and the first-dimension/CMux sum must survive modulo \(q_1\)/\(q_2\) before they are switched down. Tracing the Appendix-C variance, the first-dimension–CMux noise at \(q_2\) only stays under the message budget \(q_2/2p\) when \(q_1 \gtrsim 2^{60}\) inference5 (the smaller \(q_1\) is, the less the DMux noise is scaled down at the \(q_1\!\to\!q_2\) switch, so it overflows \(q_2\)).
Security wants \(q_1 \le 2^{56}\); correctness wants \(q_1 \ge 2^{60}\). No \(q_1\) satisfies both at \(n_1=2048\).
Because ring dimensions must be powers of two for the NTT, the next feasible dimension is \(n_1=4096\) — where 120-bit security tolerates \(\log_2 q_1\) up to \(\sim\!112\), so the published \(2^{75}\) sits comfortably inside the window that the correctness lower bound (\(\gtrsim 2^{63}\) at \(n_1{=}4096\)) opens.
2. The small ring cannot stay at \(n_2=512\)
\(n_2=512\) is only 87-bit at \(q_3=2^{23}\). One could try to buy security by shrinking \(q_3\) (smaller modulus ⇒ harder lattice at fixed \(n\)): the estimator confirms \((512,\ 2^{14})\) reaches ~159 bits. But \(q_4 < q_3\) always, so \(q_3 = 2^{14}\) caps the response modulus at \(q_4 \le 2^{13}\) — and (see below) the \(n_1{=}4096\) noise needs \(q_4 = 2^{15}\) to decode. Shrinking \(q_3\) to secure \(n_2{=}512\) breaks the decode; keeping \(q_3\) large enough to decode leaves \(n_2{=}512\) at 87 bits. The smallest power-of-two that resolves the squeeze is \(n_2=1024\): it is 174-bit even at \(q_3=2^{23}\), leaving full room for \(q_4=2^{15}\).
3. The secret must be ternary
A mod-switch rounding term has variance \((1+n\,\theta_S)/12\), where \(\theta_S=\mathbb E[s_i^2]\). With the paper’s Gaussian secret (\(\sigma_S{=}32,\ \theta_S{=}1024\)) this is \(\sigma\approx591\) at \(n{=}4096\) inference; with a ternary secret (\(\theta_S=\tfrac23\)) it is only \(\sigma\approx15\). So ternary keys do not just satisfy the security squeeze of (1)–(2) — they also shrink the per-stage rounding noise, which is why the budget closes at all. (The rounding term is not the binding one; the Correctness check shows that is the DMux gadget residual — which also scales with \(\mathbb E[s^2]\), so ternary shrinks it too, while the paper’s Gaussian secret blows it up.) 120-bit is therefore reached with ternary keys (by raising \(n\)), not by adopting the paper’s wide Gaussian.
This closes the loop between three findings that looked separate: the inert Gaussian preset (A4), the decode-threshold question (A5), and Yue’s “increase \(q_4\)” remark are one mechanism.
The instantiation
| Parameter | VIA-C published code | ≥120-bit secure inference | Why it changed |
|---|---|---|---|
| \(n_1\) (large ring) | 2048 | 4096 | large-ring security + \(q_2\)-survival |
| \(n_2\) (small ring) | 512 | 1024 | small-ring security vs. \(q_4\) decode |
| \(q_1\) | \(137438822401\cdot274810798081\approx2^{75}\) | \(173964607489\cdot173964656641\approx2^{74.7}\) | new NTT primes \(\equiv1\bmod 8192\) |
| \(q_2\) | \(17175674881\approx2^{34}\) | \(17175674881\) (reused) | already \(\equiv1\bmod2048\) |
| \(q_3\) | \(8380417\approx2^{23}\) | \(8380417\) (reused) | already \(\equiv1\bmod2048\) |
| \(q_4\) | \(2^{12}\) | \(2^{15}\) | hold \(q_3\!\to\!q_4\) rounding at \(n_1{=}4096\) |
| \(p\) | 16 | 16 | — |
| Gadget bases (DMux/CMux/rs) | 55879 / 81 / 8 (draft) | 18073 / 307 / 4 (erratum) | draft fails \(2^{-40}\) (A1) |
| Secret \(\chi_S\) | ternary | ternary | mandatory for \(q_4\) decode |
| \(\texttt{security\_param}\) | 128 (unbacked) | 120 (estimator-backed) | — |
Shipped as SECURE_PARAMS / ViaCSecure120Params
code in
crates/via-protocol/src/presets.rs, with the new
moduli in via-primitives
(algebra/zq/modulus.rs::paper::ViaSec*,
algebra/rns/basis.rs::paper::ViaSecQ1Rns) and the
\(n_1{=}4096\) LWE→RLWE cascade key
(conversion/cascade.rs, LweToRlweKeyRnsN4096).
inference \(d = n_1/n_2 = 4\) is
preserved, so the protocol structure (records-per-cell, CRot range)
is unchanged; only dimensions and \(q_4\) move.
Security check
| Instance | \((n,\ \log_2 q)\) | Estimate (classical, ternary) | ≥120? |
|---|---|---|---|
| Large ring | \((4096,\ 74.7)\) | 192.5 bits | ✓ |
| Small ring | \((1024,\ 23)\) | 156.0 bits | ✓ |
| min over instances | 156.0 bits | ✓ | |
code Figures from
via-estimator (ternary, calibrated core-SVP; malb
cross-check: ~174 / ~214). The estimate overshoots 120
substantially. inference That
margin is not waste — it is forced by the
power-of-two dimension: \(n_1=2048\) tops out at
\(\approx\!89\) bits (ternary) and the next step, 4096, lands at
\(\approx\!192\). There is no dimension in between, so a clean
≥120 inevitably overshoots. The binding instance is the small
ring at 156 bits.
Correctness check
via-estimator,
toggle yue_residual_correction) cuts both
ways, and that is the whole story of VIA-C correctness.
code Appendix-C recursion at 32 GiB (\(I{=}2^{11},J{=}2^{14}\)), per-coefficient and as a record-union over \(n_2\):
| Configuration | residual factor | \(\log_2 P_{\text{fail}}\) (union) | \(\le -40\)? |
|---|---|---|---|
| Paper design, Gaussian \(\sigma{=}32\), erratum gadgets — as the authors computed it | \(\times 1\) (paper C.1/C.2) | \(-43.4\) ← matches authors | ✓ |
| Same, with the \(\mathbb E[s^2]{=}1024\) factor restored (Yue) | \(\times 1024\) | \(+8.4\) | ✗ paper design fails |
via-rs SECURE_PARAMS, ternary, under the paper’s bound | \(\times 1\) | \(-29.2\) | ✗ |
via-rs SECURE_PARAMS, ternary, physically-correct factor | \(\times\tfrac23\) | \(-47.4\) | ✓ clears |
inference The residual (\(\sim n_1\,\mathbb E[s^2]\,q^2/B^{2\ell}\)) is the dominant term, so the \(\mathbb E[s^2]\) factor decides everything:
- The paper’s intended Gaussian secret breaks it. With \(\sigma_S{=}32\) (\(\mathbb E[s^2]{=}1024\)) the residual is ~1000× what the authors’ bound assumed, so their \(-43.4\) is a buggy number and the Gaussian design fails \(2^{-40}\) outright (\(+8.4\)) — for the draft and the erratum bases. This is Yue’s finding, reproduced in-repo: VIA’s published parameters are too aggressive because the DMux/CMux noise lemma doesn’t hold for a large-variance key with approximate decomposition.
-
But via-rs runs ternary keys (\(\mathbb E[s^2]{=}\tfrac23<1\)),
which makes the residual smaller than the
paper’s \(\times1\) bound, not larger. So
SECURE_PARAMSlands at \(\approx-47\) and clears \(2^{-40}\). The inert-Gaussian→ternary substitution (A4) — a security bug that costs via-rs ~18 bits on the binding small ring (95.3→77.5, estimator) — is the very thing that rescues correctness, by dodging the blow-up the paper’s own design walks into.
code Empirically
confirmed. The disputed factor is the whole story, so we
measured it directly: a real DMux at the secure dimensions
(n1=4096, q1-RNS, B=18073, ℓ=2), decrypting and taking the
center-lifted output-noise variance, swept over secrets of
increasing \(\mathbb E[s^2]\)
(dmux_noise_empirical.rs):
| secret | \(\mathbb E[s^2]\) | measured var / analytic base |
|---|---|---|
| ternary | 0.67 | 0.68 |
| Gaussian \(\sigma{=}4\) | 16 | 16.2 |
| Gaussian \(\sigma{=}16\) | 256 | 258 |
| Gaussian \(\sigma{=}32\) (paper) | 1024 | 1033 |
The measured residual is \(\mathbb E[s^2]\times\) the analytic base
to within ~1% across three orders of magnitude — so Yue’s
\(\mathbb E[s^2]\) factor is real (the paper’s \(\times1\)
bound, which predicts a constant, is refuted: \(\sigma{=}32\)
carries \(1519\times\) the ternary noise), and our calculator’s
residual constant is right on. The margin is still thin
(\(\approx-47\), and model-sensitive in the \(\tfrac23\) factor).
code Yue’s recommended
conversion-noise test now also exists
(conversion_noise_secure): a real LWE→RLWE
conversion at the secure params has ~56 bits of headroom
below the decode budget — confirming his intuition that the
conversion is the low-noise part, so the budget rests on the gate
gadgets, not the conversion. inference
What remains un-exhibited in code is a full
end-to-end \(P_{\text{fail}}\) at the 32 GiB dimensions (the
dominant input is now measured, the recursion structure is not) —
infeasible not for algorithmic reasons (the server’s
first_dim is eval/NTT, \(O(N)\)) but for resources:
the prepared DB at that size is ~1 TB of RAM. So the analytic
recursion plus these primitive-level measurements are the substitute.
Raising the DMux (L_QUERY) length \(\ell\!:\!2\to3\)
buys an enormous margin for one extra gadget digit — cheap
insurance, but on this (now substantially empirical) analysis
optional, not required.
code The pipeline is
confirmed to run and decode end-to-end at these dimensions: a full
query→answer→recover round-trip at \(n_1{=}4096,\
n_2{=}1024\) with the new moduli, \(q_4{=}2^{15}\), ternary keys
and erratum gadgets, exercising the n4096 LWE→RLWE
cascade, recovers the correct record
(client_server_e2e_secure; the single-threaded n=4096
NTT pipeline runs for minutes per the test
header6). But on
a \(2\times2\) database (\(I{=}J{=}2\)) the accumulated noise is
far below the 32 GiB budget, so this witnesses the
mechanics, not the worst-case budget that
the table above shows is exceeded — precisely the
“no test under paper noise/dimensions” gap of
A3.
What it costs
Raising both rings is not free; quantifying the hit is the whole point of the exercise. In brief inference (measured in full on the Cost page):
- Compute ~2.2×. The multiplicative core (eval-backed
gadget_product) is \(O(n\log n)\): measured 6159 → 13341 µs/op going \(n{=}2048\to4096\), a 2.17× factor. - Conversion key ~2.2×. The LWE→RLWE cascade key grows 24.75 MB → 54.00 MB (one extra fold).
- Response ~2.5×. The answer is an \(n_2\)-coefficient ciphertext at \(q_4\): \(1024\cdot15\) vs \(512\cdot12\) bits.
So real 120-bit security changes VIA-C’s advertised profile by roughly 2× across compute, key size, and response size — the paper’s headline figures are a sub-100-bit operating point (our estimator: ~77–96 bits; malb: ~87–110), not a 120-bit one. The optional DMux \(\ell\to3\) correctness-margin bump would add a further, smaller increment (one extra query gadget digit).
Using it
code The preset is wired
end-to-end behind the same const-generic machinery as
REALISTIC_PARAMS:
use via_protocol::{SECURE_PARAMS, ViaCSecure120Params};
// n1=4096, n2=1024, q1=2^74.7 (RNS), q2=2^34, q3=2^23, q4=2^15, p=16,
// erratum gadgets (18073/307/4), ternary keys, security_param = 120.
assert_eq!(SECURE_PARAMS.security_param, 120);
Unlike the published presets, the \(120\) here is
witnessed and reproducible: the
via-estimator crate — a calibrated core-SVP
lattice estimate plus the Appendix-C noise calculator —
produced every number on this page and gates CI on them
(cargo test -p via-estimator;
cargo run -p via-estimator for the table). It is the
audit trail. Two honest caveats remain: the security side clears
\(\ge120\) with margin; the correctness side clears
\(2^{-40}\) on a thin, model-sensitive margin (and only
because the keys are ternary — the paper’s Gaussian
design would fail), so validate it empirically. The estimator
is also conservative — re-run it, and ideally
malb,
on the exact \((n,q,\sigma)\) you ship. The one number you must
never hard-code is the one that says you are safe.
-
Exposed-instance enumeration: the query, the LWE→RLWE
conversion key, and the RLWE→RGSW key all live on the large
ring under \(S_1\); the ring-switching key is an RLWE sample
under the small-ring secret \(S_2\) at \(q_3\). No
lower-dimension LWE leaves the client (the conversion’s
low-rank intermediates are computed server-side). paper §5.1, p.16; code
via-client/src/client.rs,via-primitives/src/switching/ring_switch.rs. ↩ -
code Estimates from the
in-repo
via-estimator::latticemodule: classical core-SVP primal-uSVP (Bai–Galbraith secret-scaled embedding, BKZ cost \(0.292\beta\)), run per instance with the secret/error distributions shown. A single documented additive offset (\(+29.6\) bits) calibrates bare sieving cost to the HE Security Standard 128-bit anchors (\((2048,2^{54},\text{ternary})\to128.0\); residual spread ±3, so ±~5 bits overall). RLWE/MLWE treated as LWE at the ring dimension (standard). It is a single-attack, conservative model — not a substitute for the full malb suite, which reports somewhat higher numbers here. ↩ -
unverified The ~72/88-bit
figures are reported by Yue et al. on the
owniai/VIA
C++ implementation via the OpenFHE estimator and were not re-run
here; they concern a different artifact than
via-rs. ↩ -
code Appendix-C recursion
reimplemented in
via-estimator::noise(Lemmas C.1–C.5, pp.24–27) and validated: erratum gadgets + paper Gaussian at \(n_1{=}2048\), against the \((q_3{-}q_4)/p\) threshold, give \(\log_2 P_{\text{fail}} = -52.4\) per coefficient, i.e. \(-52.4 + \log_2(n_2{=}512) = -43.4\) as a union over the decoded record — exactly the authors’ stated figure, which fixes the union dimension as \(n_2\). Modelling choices (the \(\theta_{crot}^2\) typo, the conversion-key base, the final-switch rounding) are documented innoise.rs; they do not move the qualitative verdicts. ↩ - inference The binding intermediate constraint is the first-dimension/CMux output at \(q_2\): its noise must stay below the message budget \(q_2/2p\). Lowering \(q_1\) raises the \(q_1\!\to\!q_2\) mod-switch ratio \((q_2/q_1)^2\) applied to the (large) DMux variance, so the carried noise at \(q_2\) grows; the survival margin crosses \(6\sigma\) near \(q_1=2^{60}\) at \(n_1{=}2048\) and \(q_1=2^{63}\) at \(n_1{=}4096\). ↩
-
code Runtime is
machine-dependent and not asserted in-repo; the test header
states the single-threaded n=4096 NTT pipeline “runs for
minutes.”
via-integration/tests/client_server_e2e_secure.rs. The test’s in-repo guarantee is the correctness assertion (it recovers the right record), not a wall-clock figure. ↩