Est.

CKKS Parameter Selection for Private Neural Network Inference

Homomorphic encryption's four interdependent parameters demand coordination, not checklist defaults.

Reporter · · 13 min read · Updated
Cover illustration for “CKKS Parameter Selection for Private Neural Network Inference”
Cryptographic Primitives for Private AI · August 15, 2026 · 13 min read · 3,028 words

CKKS parameter selection isn't a checklist you fill out once. Change one number and three others move with it, and the right starting point is the neural network you're actually running, not whatever defaults ship in the library README. This piece walks through how four parameters get picked for private neural network inference, why they pull on each other the way they do, and where things stand as of 2025 and early 2026 research.

Homomorphic encryption runs computation on encrypted data without ever decrypting it, and that's the whole reason private inference exists as a field. CKKS, introduced by Cheon and colleagues back in 2017, does this natively for real and complex numbers, which happens to be exactly what neural network weights and activations are made of. The scheme encodes a vector of real values into an integer polynomial, and from there supports three operations: addition, multiplication, and rotation, a cyclic shift across the encoded slots. Put those three together and you can build every layer of a network. Getting there means choosing four parameters jointly, before a single encrypted inference ever runs.

How the four core parameters relate to each other before any are chosen

Diagram: How Network Architecture Flows Into Cryptographic Parameters. Visualizes: Show the one-directional dependency chain that governs CKKS parameter selection: the network architecture sets multiplicative depth L; L combined with scaling…

Four numbers govern everything: polynomial degree N, coefficient modulus Q, scaling factor (sometimes written as precision ρ), and multiplicative depth L. None of them get picked alone, and trying will leave you redoing the other three by Tuesday.

Security sets the outer wall. The level you're targeting, usually 128 bits, caps how big Q can get relative to N. Want a bigger Q? You need a bigger N to hold the same margin, and a bigger N means every operation afterward costs more compute.

But the actual starting point, the thing you look at before touching any of this, is the network. Its architecture decides how much multiplicative depth L you need, and L, together with your target precision ρ, sets the minimum bit-size of Q. Roughly, |Q| ≈ L × ρ bits. That required |Q|, combined with your security target, sets the minimum N, and N, once fixed, decides ciphertext size, how many values you can pack into one ciphertext, and the cost of every operation downstream.

So you start with the network, not the crypto library. Open a CKKS implementation, accept the sample parameters sitting in the README, and one of two things happens: you burn compute on security margin the workload never needed, or you quietly undercut the security guarantee you think you have. I've sat across from engineers who got the math exactly right and still shipped a system running at half the security level they thought they had, because nobody went back and re-derived N once the network changed underneath them. Every decision from here trades off against security, precision, or performance. You rarely gain on one without giving something back on another.

Choosing polynomial degree N: security budget, slot count, and compute cost

N has to be a power of two, so in practice you're picking among 4096, 8192, 16384, and 32768, a handful of buckets rather than a dial you turn continuously.

The security constraint doesn't bend. For a given security level, a bigger Q needs a bigger N, full stop, and there's no way around that once you're spending a deep network's worth of modulus budget. To put a number on it: N = 2^16 supports a ciphertext modulus of roughly 2^1782 bits at 128-bit security, and deep networks tend to push right up against that ceiling.

N also fixes your slot count at N/2, the number of real values you can batch into one ciphertext and run in parallel. So a bigger N isn't pure overhead; it buys throughput. But the number-theoretic transform CKKS leans on for polynomial multiplication, along with rotation keys and key-switching, all scale with N too. None of that throughput comes free.

Pick the smallest N that covers the modulus budget your network's depth and precision actually need. Easy to write down, harder to live by, mostly because the bigger number always feels safer even when it's just wasted compute sitting on a GPU somewhere. PrivSpike, a 2025 implementation, ran N = 2^15 at 128-bit security, a mid-range pick that fit comfortably for many inference-only workloads. An encrypted ResNet-50 needed N = 2^16 instead, to cover a multiplicative depth of 34, which sits near the edge of what's practical today.

Structuring the coefficient modulus Q: the prime chain and how levels are consumed

Q isn't one number. In every practical CKKS library it's a product of primes, handled through the Residue Number System (RNS), which lets the implementation work with several smaller primes instead of one enormous integer.

The chain has a specific shape. There's a special first prime, q0, usually larger, something like 60 bits, whose job is handling the final modulus reduction cleanly. After that comes a run of L same-size primes, q1 through qL, each satisfying qi ≡ 1 mod 2N so the number theory works for the transform. Every multiplication you run spends exactly one of these primes, one level, through rescaling.

A common layout looks like [60, 40, 40, 40, 60]: bigger primes bookending a run of smaller, uniform ones, so the first and last rescaling steps don't lose precision. Individual primes usually run from about 20 to 60 bits. Smaller primes give finer control over how you spend your level budget; larger ones buy more precision per level but chew through modulus budget faster.

That budget has a hard ceiling, and it isn't negotiable. Per the 2024 security guidelines from HomomorphicEncryption.org, estimated with the Lattice Estimator (commit dated August 27, 2024), every (N, λ) pair has a maximum log₂ Q you can't cross without breaking the security level you're claiming. This is the line between encrypted and encrypted-but-crackable-in-practice. A shallow-inference example: N = 2048, log Q = 54, satisfies classical 128-bit security, but that footprint only works for very shallow networks, nowhere near enough to stretch across a ResNet.

The modulus chain does double duty: security ceiling and compute budget at once. Once every prime in the chain gets spent, multiplication stops, unless you bootstrap. That coupling is what makes CKKS parameter selection feel less like cryptography and more like managing a currency you can't overdraw.

Setting the scaling factor: precision, noise, and what happens when they compound

The scaling factor, Δ, decides how much of the available integer space goes toward encoding precision for your real numbers. CKKS is an approximate scheme by design: plaintexts get rounded before encryption, and every operation afterward adds a bit of noise. Decryption doesn't remove that noise; it just reveals it, once it's grown too large to ignore.

In practice, scaling precision lands somewhere between 2^20 and 2^60, chosen by trial and error based on the actual numeric range of weights and activations in the network at hand. Every prime in your modulus chain needs to be at least as large as Δ, or precision collapses after rescaling. Scaling factor and prime size aren't independent choices; they're locked together whether you plan for it or not.

Practice bears this out. PrivSpike used a 40-bit scaling factor alongside its N = 2^15, a balanced pairing for its depth budget. The ResNet-50 implementation at depth 34 needed 59-bit scaling factors instead, because a wider activation range needs more precision surviving each level down the chain.

The real design question was never what scaling factor someone else used on a different model. It's what precision this model needs. Quantization-aware training shrinks that requirement, letting you get away with a smaller Δ and a shallower prime chain, which saves both security budget and compute. Models with uncontrolled activation ranges inflate noise for no good reason; models trained with weight normalization or bounded activations are measurably easier to encrypt correctly. And because noise compounds multiplicatively as it moves through the chain, a scaling factor that's slightly off early can leave later layers numerically unstable even when the modulus budget looks fine on paper.

Multiplicative depth as the architectural constraint that drives every other decision

Every homomorphic multiplication spends one level, and the rescaling that follows is mandatory; it can't be undone. A ciphertext starts life at level L and moves one direction only, toward zero. Hit zero, and no further multiplication happens without bootstrapping.

Depth requirements swing wildly by layer type. Linear layers, fully connected or convolutional, cost no multiplicative depth on their own, which is a relief given how much of a network is built from them. Activation functions are the real depth consumers; more on why in the next section. Normalization and pooling layers add some depth too, depending on how they're implemented.

The gap between inference and training is where this constraint really bites. PrivFT needed just L = 5 levels for transformer inference. Training that same model took L = 46, nearly an order of magnitude more. Training eats depth in a way inference just doesn't, and that gap is a big part of why private inference is the nearer-term target while private training still lags behind.

Depth is finite unless you bootstrap, and bootstrapping buys levels back at a steep latency cost, so the tradeoff between depth budget and bootstrapping frequency sits at the center of the whole design. Total depth L times precision ρ roughly equals total modulus bit-size: architectural depth flows straight into cryptographic parameter size through that one equation. There's a consequence here that catches people coming from plaintext ML off guard, too. Networks built for ordinary inference often need re-architecting, not just re-parameterizing, before CKKS makes them workable at all.

Approximating activation functions: how polynomial degree translates into depth cost

Diagram: Activation Polynomial Degree vs. Depth Cost. Visualizes: Visualize the tradeoff between polynomial degree d and multiplicative depth cost (⌈log₂ d⌉ + 1 levels) for activation function approximation in CKKS, with named real examples: degree…

ReLU doesn't survive the trip into FHE. It relies on a conditional, an if-statement, and FHE only supports addition and multiplication, no branching. So any activation running under CKKS has to be a polynomial, and the degree of that polynomial sets its depth cost directly.

The formula: a degree-d polynomial, evaluated with methods like Paterson-Stockmeyer or baby-step giant-step, costs ⌈log₂ d⌉ + 1 levels. The floor is a quadratic, degree 2, costing just 1 level, and that's what CryptoNets and LoLa used successfully in shallow CNNs. Push a quadratic into a deep network, though, and it falls apart outside a narrow input range, sometimes called the escaping activation problem. The approximation only holds near zero, and deep networks push activations well past that window.

PILLAR's degree-4 polynomial gets to a depth cost of 3 levels, reported as the lowest multiplicative depth for a ReLU approximation that generalizes to deep CNNs rather than just shallow ones. From here the field splits roughly into two camps. One keeps degree low and fixed: accept some accuracy loss, stay inside a fixed level budget, skip bootstrapping between activations entirely. The other reaches for high-degree minimax composite polynomials, chasing approximation accuracy and paying for it with bootstrapping at or near every activation.

That second path gets expensive fast. An early ResNet-20 implementation using high-degree minimax composite polynomials needed over a thousand bootstrapping calls and took roughly 3 hours per image, on hardware that runs the same network unencrypted in a few milliseconds. That gap alone explains why so much current research goes toward avoiding bootstrapping or making it cheaper, rather than chasing polynomial accuracy for its own sake.

One approach sidesteps the approximation problem entirely. Polynomial Neural Networks, PNNs, swap in polynomial operations from the start, so there's no approximation gap to manage, though it also means retraining the architecture from scratch instead of adapting an existing one. Dynamic programming for layer-wise degree selection, including work from Lee and colleagues in 2024, along with learnable polynomial coefficients, is active research aimed at cutting this cost without giving up accuracy.

Bootstrapping: when and how often to refresh the level budget

Bootstrapping resets a ciphertext's level back up toward L, the only way to keep computing once the modulus budget runs dry. It isn't a free reset button, though. Bootstrapping is itself a homomorphic computation, and it burns levels to perform. In many implementations it accounts for over 80% of total inference latency, a number that alone tells you how much of system design is really just bootstrapping-frequency design wearing a different hat.

The trajectory on ResNet-20 over CIFAR-10 shows both the scale of the problem and real progress against it. Lee and colleagues reported 91.31% accuracy in 2022, at a cost of 2,271 seconds per image. By 2023, Kim and colleagues brought that same task's latency down to 255 seconds, roughly a ninefold improvement in under two years. Not nothing, but still nowhere near what you'd call fast.

More recent work goes after the structure of the problem instead of just tuning the existing pipeline. BootNet, described in IACR ePrint 2026, fuses convolution, ReLU approximation, and bootstrapping into a single operation per CNN layer, collapsing three sequential costs into one invocation. It builds on partial fusions that came before: NeuJeans (CCS 2024) fused convolution directly into bootstrapping using CinS encoding, while RBOOT (USENIX Security 2026) fused ReLU into functional bootstrapping. BootNet is the first to combine both, aimed at end-to-end ImageNet inference. Separately, functional bootstrapping work from Alexandru and colleagues (Crypto 2025) brings lookup table evaluation inside CKKS bootstrapping itself, letting accurate non-polynomial functions run without the approximation error polynomial methods carry.

What does this mean for parameter choice? Networks that bootstrap often need wider modulus chains, bigger Q and bigger N, just to hold the extra primes bootstrapping itself requires. It isn't enough to budget modulus for the network's own depth; you have to budget for the bootstrapping stacked on top of it too. So the move that follows is placing bootstrap calls where level consumption runs lowest, cutting the total calls needed, which means profiling depth usage layer by layer before any parameter gets finalized. Skip that profiling step and you end up bootstrapping reflexively, everywhere, instead of where it's actually cheap.

Ciphertext packing strategy and its effect on the effective parameter choice

CKKS can pack up to N/2 real values into one ciphertext, which is what makes SIMD-style parallel processing possible and makes a bigger N genuinely attractive for throughput, not just an unfortunate side effect of chasing security margin.

But that packing capacity doesn't use itself well. A poor layout wastes slots, forces you to juggle more ciphertexts than you need, and calls for extra rotations, all of which drag on latency no matter how well-chosen your cryptographic parameters are. HW layout, one input channel per ciphertext with h times w spatial values packed in, beats a naive one-value-per-ciphertext scheme, but still leaves slots empty when channel count is small. CHW layout does better: it maps multiple channels into a single ciphertext, cutting both ciphertext counts and the multiplications and additions the network needs, trading faster inference for messier encoding logic on the implementation side.

Rotations are the cost that catches people off guard. Summing across slots, or pulling out specific values, needs rotation operations, and rotations cost more than multiplications, ending up dominating convolution latency in practice. FEnc², a 2026 proposal, tackles this with fragment-based encoding: it analytically picks a block size that decouples spatial dependencies and minimizes rotations across layers jointly rather than layer by layer, and restores ciphertext density after operations that shrink channel count.

Here's the thing worth sitting with: a packing strategy with high slot use can let you get away with a smaller N for the same workload. Pick N first, without thinking through packing at all, and you risk over-provisioning parameters for a workload a smarter layout would have handled with room to spare. Prototype the packing layout for your target network before locking in N, and measure rotation count and slot use directly, rather than trusting depth requirements alone to tell you what N should be.

Reading the security guidelines and using the Lattice Estimator

Everything above assumes you have a way to check your work, and that check comes from the security guidelines published by HomomorphicEncryption.org, backed by the Lattice Estimator tool. This is where parameter selection stops being an engineering optimization and turns into a security claim about your own system.

The guidelines exist because the hardness of the underlying lattice problem, Ring-LWE in CKKS's case, depends on the relationship between N and Q in a way you can't just eyeball. The Lattice Estimator takes a proposed (N, Q) pair and computes the concrete bit-security level against the best known attacks, factoring in specific lattice reduction algorithms and their real running times, not just asymptotic complexity. This matters because "128-bit security" isn't a fixed line drawn once and left alone. It's a moving estimate, revised as attacks improve, which is exactly why the guidelines carry a commit date (August 27, 2024, in this case) instead of getting treated as permanent truth.

So how do you actually use it? Take the modulus chain built from your depth and precision requirements, sum the bit-sizes of every prime including the special primes reserved for bootstrapping, and check that total against the Lattice Estimator's output for your chosen N. If it exceeds the ceiling, you don't get to shrug and accept the risk. You go back, and either raise N and eat the compute cost, or find a way to shrink the modulus requirement: a shallower activation polynomial, tighter quantization, a packing strategy that needs fewer bootstrapping calls.

Every choice earlier in this piece, the polynomial degree, the prime chain, the scaling factor, the depth budget, the packing layout, funnels into one final check against a security estimate that isn't yours to negotiate. The network tells you what it needs; the Lattice Estimator tells you what you're allowed to give it. Getting CKKS parameters right is the ongoing work of reconciling those two demands, re-checked every time the guidelines change. A private inference system that actually protects data does that reconciliation honestly. One that only looks private skips it and hopes nobody checks the math. Confidant AI, a privacy-preserving AI assistant built so user data is never collected or monetized, is one example of a system designed around the principle that the architecture itself has to carry the privacy guarantee, not just the marketing.

Venn diagram: CKKS Parameters: Security vs. Performance Tradeoffs. Compares Security Constraints and Network Architecture; overlap: Joint Constraints.

Sources

  1. arxiv.org

More in Cryptographic Primitives for Private AI