Skip to content

Add encryption and decryption lowering for CKKS - #3609

Draft
j2kun wants to merge 3 commits into
google:mainfrom
j2kun:rlwe_encrypt_ckks
Draft

j2kun wants to merge 3 commits into
google:mainfrom
j2kun:rlwe_encrypt_ckks

Conversation

@j2kun

@j2kun j2kun commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator

Includes #3597 as a base

Fixes google#880.

The existing secret-key lowering of `lwe.rlwe_encrypt` produced
`(u, u*s + m + e)` with a ternary `u`, which does not decrypt correctly. It now
produces `(m + t*e - a*s, a)` where the mask `a` is sampled uniformly from R_Q
and the noise is scaled by the plaintext modulus `t`, as in the public-key path.
The coefficients of `a` are sampled with `random.sample_modq` (which samples
each RNS limb uniformly).

The `lwe.rlwe_decrypt` lowering is also fixed to compute `c0 + c1*s`, matching
the LWE dialect's ciphertext convention and the existing public-key encryption;
it previously computed `s*c0 + c1`. I was on paternity leave when this was implemented so I'm not sure what happened there.

Both lowerings implement BGV-style (`lsb`) encryption only, so they now emit an
error for `msb` (BFV) and `mix` (CKKS) ciphertexts rather than silently
lowering them with BGV semantics.

PiperOrigin-RevId: 1013039909
@j2kun
j2kun marked this pull request as draft November 5, 2026 23:27
@j2kun
j2kun force-pushed the rlwe_encrypt_ckks branch from e9ea605 to 2f68014 Compare November 5, 2026 23:42
The `mix` encryption type was only ever used for CKKS ciphertexts, and
nothing used it. Renamed it to `ckks` and documented what each
encryption type decrypts to, since `lsb`, `msb`, and `ckks` differ in
how the message and noise are scaled at encryption time.
@j2kun
j2kun force-pushed the rlwe_encrypt_ckks branch from 2f68014 to 5e6d9a7 Compare November 5, 2026 23:45
Extend the lowering of `lwe.rlwe_encrypt` (secret and public key) and
`lwe.rlwe_decrypt` to `ckks` ciphertexts. CKKS shares the same
decryption circuit with BGV (c_0 + c_1 * s), and it differs only
in that BGV scales the encryption noise by the plaintext modulus `t` while
CKKS does not, so whether to add a noise scale is derived from the
encryption type enum.
@j2kun
j2kun force-pushed the rlwe_encrypt_ckks branch from 5e6d9a7 to 9f55487 Compare November 6, 2026 03:10

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant