LWE to LWE Key Switching

A detailed walkthrough of the key concepts for LWE to LWE key switching.

By Roman Akhtariev

This article is a detailed walkthrough of the key concepts for converting LWE-to-LWE under a different secret. The design is described in this paper.

LWE-to-LWE key switching is essential in several cryptographic settings:

  1. Fully homomorphic encryption: After computing on encrypted data, you often need to switch keys — either to refresh ciphertexts, change encryption parameters, or allow a different party to decrypt.
  2. Private information retrieval: key switching enables efficient database queries where the server doesn't learn what the client is searching for.
  3. Multi-party computation: When encrypted data needs to be handed off between parties with different keys.

The key insight is that rather than performing the expensive key switch directly in LWE space, you convert the LWE ciphertext to RLWE first. This enables an asymptotically faster key switch. You then convert back to LWE, encrypted under the new secret.

Pre-requisites

  • LWE Ciphertext: A pair (b,a)Zq×ZqN(b, a) \in \mathbb{Z}_q \times \mathbb{Z}_q^N that encrypts a value μ\mu. Decryption computes μ=b+a,s(modq)\mu = b + \langle a, s \rangle \pmod{q}. (Note: some papers use the opposite sign convention μ=ba,s\mu = b - \langle a, s \rangle; we follow the convention from the referenced paper.)

  • RLWE Ciphertext: A pair (bp,ap)Rq×Rq(b_p, a_p) \in R_q \times R_q that encrypts a polynomial μ\mu. Decryption computes μ=bp+aps(modq)\mu = b_p + a_p \cdot s \pmod{q}.

  • Negacyclic ring property: In Z[X]/(XN+1)\mathbb{Z}[X]/(X^N + 1), we have XN=1X^N = -1, so X1=XN1X^{-1} = -X^{N-1}.

Notation

SymbolMeaning
Zq\mathbb{Z}_qIntegers modulo qq
RqR_qZq[X]/(XN+1)\mathbb{Z}_q[X]/(X^N + 1), the negacyclic polynomial ring
a,s\langle a, s \rangleInner product of vectors aa and ss
(b,a)(b, a)LWE ciphertext with scalar bb and vector aa
(bp,ap)(b_p, a_p)RLWE ciphertext with polynomials bpb_p and apa_p
s,ss, s'Secret keys (old and new)
eeError/noise term
B,dB, dGadget base and digit count
g1()g^{-1}(\cdot)Gadget decomposition (pseudo-inverse: gg maps vectors to scalars, g1g^{-1} maps scalars to vectors)

Overview

Given an LWE ciphertext (b,a)(b, a) encrypting μ0\mu_0 under secret ss, we want to convert it to a new LWE ciphertext (b,a)(b', a') encrypting the same value μ0\mu_0 under a different secret ss'.

Why convert to RLWE? The polynomial embedding (described below) enables fast key switching via NTT-accelerated polynomial multiplication, reducing runtime from O~(N2)\tilde{O}(N^2) to O~(N)\tilde{O}(N).1 The naive LWE approach requires NN scalar-times-vector operations.

Algorithm:

  1. Embed into Ring: Convert vector aa into polynomial a(X)=i=0N1aiXia(X) = \sum_{i=0}^{N-1} a_i \cdot X^i.
  2. Secret Embedding: Convert ss to polynomial s(X)=i=0N1siXis(X) = \sum_{i=0}^{N-1} s_i \cdot X^{-i} using the negacyclic property X1=XN1X^{-1} = -X^{N-1}.
  3. Key Switching: Apply RLWE key-switching to switch from s(X)s(X) to s(X)s'(X).
  4. Extract: Read coefficients from the resulting RLWE ciphertext to get your new LWE ciphertext under ss'.

Polynomial Embedding

Polynomial embedding is a technique that converts LWE (vector-based) operations into RLWE (polynomial-based) operations.

The key insight is that an LWE inner product can be computed as the constant term of the product of the LWE ciphertext and the secret.

We'll demonstrate this with N=4N=4: the constant term of a(X)s(X)a(X) \cdot s(X) will equal the inner product a,s\langle a, s \rangle.

Let a=[a0,a1,a2,a3]a = [a_0, a_1, a_2, a_3] and s=[s0,s1,s2,s3]s = [s_0, s_1, s_2, s_3].

Define polynomials:

  • a(X)=a0+a1X+a2X2+a3X3a(X) = a_0 + a_1 X + a_2 X^2 + a_3 X^3
  • s(X)=s0+s1X1+s2X2+s3X3s(X) = s_0 + s_1 X^{-1} + s_2 X^{-2} + s_3 X^{-3}

The LWE inner product a,s\langle a, s \rangle is then given by the constant term of the product a(X)s(X)a(X) \cdot s(X).

a(X)s(X)=(a0+a1X+a2X2+a3X3)(s0+s1X1+s2X2+s3X3)a(X) \cdot s(X) = (a_0 + a_1 X + a_2 X^2 + a_3 X^3) \cdot (s_0 + s_1 X^{-1} + s_2 X^{-2} + s_3 X^{-3})

=a0s0= a_0 s_0

+a0s1X1+a0s2X2+a0s3X3\quad + a_0 s_1 X^{-1} + a_0 s_2 X^{-2} + a_0 s_3 X^{-3}

+a1X(s0+s1X1+s2X2+s3X3)\quad + a_1 X (s_0 + s_1 X^{-1} + s_2 X^{-2} + s_3 X^{-3})

+a2X2(s0+s1X1+s2X2+s3X3)\quad + a_2 X^2 (s_0 + s_1 X^{-1} + s_2 X^{-2} + s_3 X^{-3})

+a3X3(s0+s1X1+s2X2+s3X3)\quad + a_3 X^3 (s_0 + s_1 X^{-1} + s_2 X^{-2} + s_3 X^{-3})

=a0s0= a_0 s_0

+a0s1X1+a0s2X2+a0s3X3+ a_0 s_1 X^{-1} + a_0 s_2 X^{-2} + a_0 s_3 X^{-3}

+a1s0X+a1s1X0+a1s2X1+a1s3X2+ a_1 s_0 X + a_1 s_1 X^{0} + a_1 s_2 X^{-1} + a_1 s_3 X^{-2}

+a2s0X2+a2s1X1+a2s2X0+a2s3X1+ a_2 s_0 X^2 + a_2 s_1 X^{1} + a_2 s_2 X^{0} + a_2 s_3 X^{-1}

+a3s0X3+a3s1X2+a3s2X1+a3s3X0+ a_3 s_0 X^3 + a_3 s_1 X^2 + a_3 s_2 X^1 + a_3 s_3 X^{0}

Now collect terms by power and convert negative powers using Xk=XNkX^{-k} = -X^{N-k} with N=4N=4:

  • X1=X3X^{-1} = -X^{3}
  • X2=X2X^{-2} = -X^{2}
  • X3=X1X^{-3} = -X^{1}

The conversion is enabled by the negacyclic ring property X1=XN1X^{-1} = -X^{N-1}.

PowerTerms from expansionAfter converting XkXNkX^{-k} \to -X^{N-k}
X0X^0a0s0+a1s1+a2s2+a3s3a_0 s_0 + a_1 s_1 + a_2 s_2 + a_3 s_3a,s\langle a, s \rangle
X1X^1a1s0+a2s1+a3s2a_1 s_0 + a_2 s_1 + a_3 s_2 and a0s3X3a0s3X1a_0 s_3 X^{-3} \to -a_0 s_3 X^1a1s0+a2s1+a3s2a0s3a_1 s_0 + a_2 s_1 + a_3 s_2 - a_0 s_3
X2X^2a2s0+a3s1a_2 s_0 + a_3 s_1 and a0s2X2,a1s3X2X2a_0 s_2 X^{-2}, a_1 s_3 X^{-2} \to -X^2a2s0+a3s1a0s2a1s3a_2 s_0 + a_3 s_1 - a_0 s_2 - a_1 s_3
X3X^3a3s0a_3 s_0 and a0s1X1,a1s2X1,a2s3X1X3a_0 s_1 X^{-1}, a_1 s_2 X^{-1}, a_2 s_3 X^{-1} \to -X^3a3s0a0s1a1s2a2s3a_3 s_0 - a_0 s_1 - a_1 s_2 - a_2 s_3

Final result:

a(X)s(X)=(a0s0+a1s1+a2s2+a3s3)constant term =a,sa(X) \cdot s(X) = \underbrace{(a_0 s_0 + a_1 s_1 + a_2 s_2 + a_3 s_3)}_{\text{constant term } = \langle a, s \rangle}

+(a1s0+a2s1+a3s2a0s3)X+ (a_1 s_0 + a_2 s_1 + a_3 s_2 - a_0 s_3) X

+(a2s0+a3s1a0s2a1s3)X2+ (a_2 s_0 + a_3 s_1 - a_0 s_2 - a_1 s_3) X^2

+(a3s0a0s1a1s2a2s3)X3+ (a_3 s_0 - a_0 s_1 - a_1 s_2 - a_2 s_3) X^3

Key insight: The constant term of a(X)s(X)a(X) \cdot s(X) equals the LWE inner product a,s\langle a, s \rangle. This is why embedding LWE into RLWE works.

RLWE Key Switching

After embedding the LWE ciphertext into RLWE (via polynomial embedding above), we have an RLWE ciphertext (bp,ap)(b_p, a_p) under secret s(X)s(X). We now need to switch it to secret s(X)s'(X).

Decrypting with ss gives the encrypted value: μ0=bp+aps(modq)\mu_0 = b_p + a_p \cdot s \pmod{q}

Key switching transforms an RLWE ciphertext under secret ss to an RLWE ciphertext (bp,ap)(b'_p, a'_p) under secret ss' while preserving μ0\mu_0:

bp+apsμ0(modq)b'_p + a'_p \cdot s' \approx \mu_0 \pmod{q}

The challenge: You need to "remove" the apsa_p \cdot s term and "replace" it with something involving ss', but the switching party cannot compute apsa_p \cdot s directly without knowing ss.

Insight: Pre-compute an encryption of ss under the new secret ss', called Encs(s)\text{Enc}_{s'}(s). Then exploit RLWE's homomorphic property — multiplying a ciphertext by a polynomial multiplies the underlying message:

apEncs(s)Encs(aps)a_p \cdot \text{Enc}_{s'}(s) \approx \text{Enc}_{s'}(a_p \cdot s)

This gives you an encryption of apsa_p \cdot s under ss'.

But what does Encs(s)\text{Enc}_{s'}(s) actually mean? It's an RLWE ciphertext (bp,ap)(b_p, a_p) where:

bp=aps+s+eb_p = -a_p \cdot s' + s + e'

ComponentDescription
apa_pRandom polynomial
ss'New secret — creates the "mask" apsa_p \cdot s'
ee'Small noise
ssOld secret — the "message" being encrypted

When you decrypt with ss': bp+aps=s+es\quad b_p + a_p \cdot s' = s + e' \approx s

Gadget Decomposition

The key switching technique above has a critical flaw: apa_p can be as large as qq, and multiplying by it causes a major noise blowup.

To solve this, we can use gadget decomposition. This is a technique for decomposing a large number into a vector of smaller numbers under a pre-computed basis BB:

g=(1,B,B2,,Bd1)g = (1, B, B^2, \ldots, B^{d-1})

Gadget Decomposition g1g^{-1}

For any apa_p, compute: g1(ap)=(ap(0),ap(1),,ap(d1))g^{-1}(a_p) = (a_p^{(0)}, a_p^{(1)}, \ldots, a_p^{(d-1)})

where:

  • Each ap(i)a_p^{(i)} is a small polynomial (coefficients in [0,B)[0, B)).
  • i=0d1ap(i)Bi=ap\sum_{i=0}^{d-1} a_p^{(i)} \cdot B^i = a_p (reconstruction)

Example with B=256B = 256 and d=4d = 4:

If a coefficient of apa_p is 0x12345678:

  • ap(0)=0x78a_p^{(0)} = \texttt{0x78} (least significant byte)
  • ap(1)=0x56a_p^{(1)} = \texttt{0x56}
  • ap(2)=0x34a_p^{(2)} = \texttt{0x34}
  • ap(3)=0x12a_p^{(3)} = \texttt{0x12}

So g1(0x12345678)=(0x78,0x56,0x34,0x12)g^{-1}(\texttt{0x12345678}) = (\texttt{0x78}, \texttt{0x56}, \texttt{0x34}, \texttt{0x12}).

Key Switching Key

Following the gadget decomposition, the key switching key KK consists of dd RLWE ciphertexts instead of just one encryption of ss:

K[0]=Encs(sB0)=Encs(s)K[0] = \text{Enc}_{s'}(s \cdot B^0) = \text{Enc}_{s'}(s)

K[1]=Encs(sB1)=Encs(sB)K[1] = \text{Enc}_{s'}(s \cdot B^1) = \text{Enc}_{s'}(s \cdot B)

K[2]=Encs(sB2)K[2] = \text{Enc}_{s'}(s \cdot B^2)

K[3]=Encs(sB3)K[3] = \text{Enc}_{s'}(s \cdot B^3)

Now, instead of computing apsa_p \cdot s (huge multiplier), we can:

  1. Decompose apa_p into ap(0),ap(1),,ap(d1)a_p^{(0)}, a_p^{(1)}, \ldots, a_p^{(d-1)}
  2. Combine using the pre-computed keys:

ap(0)K[0]+ap(1)K[1]+ap(2)K[2]+ap(3)K[3](modq)a_p^{(0)} \cdot K[0] + a_p^{(1)} \cdot K[1] + a_p^{(2)} \cdot K[2] + a_p^{(3)} \cdot K[3] \pmod{q}

  1. This equals (homomorphically):

ap(0)(sB0+e0)+ap(1)(sB1+e1)+ap(2)(sB2+e2)+ap(3)(sB3+e3)(modq)a_p^{(0)} \cdot (s \cdot B^0 + e_0) + a_p^{(1)} \cdot (s \cdot B^1 + e_1) + a_p^{(2)} \cdot (s \cdot B^2 + e_2) + a_p^{(3)} \cdot (s \cdot B^3 + e_3) \pmod{q}

=s(ap(0)B0+ap(1)B1+ap(2)B2+ap(3)B3)+(ap(0)e0+ap(1)e1+ap(2)e2+ap(3)e3)(modq)= s \cdot (a_p^{(0)} \cdot B^0 + a_p^{(1)} \cdot B^1 + a_p^{(2)} \cdot B^2 + a_p^{(3)} \cdot B^3) + (a_p^{(0)} \cdot e_0 + a_p^{(1)} \cdot e_1 + a_p^{(2)} \cdot e_2 + a_p^{(3)} \cdot e_3) \pmod{q}

=sap+i=0d1ap(i)eitotal noise= s \cdot a_p + \underbrace{\sum_{i=0}^{d-1} a_p^{(i)} \cdot e_i}_{\text{total noise}}

Noise growth analysis:

Without gadget decomposition, computing apEncs(s)a_p \cdot \text{Enc}_{s'}(s) directly would give noise ape\sim a_p \cdot e, where apa_p can be as large as qq — catastrophic for correctness.

With gadget decomposition, the total noise is iap(i)ei\sum_{i} a_p^{(i)} \cdot e_i. Since each ap(i)<Ba_p^{(i)} < B and we have d=logBqd = \lceil \log_B q \rceil digits:

noisedBemax|\text{noise}| \leq d \cdot B \cdot |e|_{\max}

Trade-off: Larger BB means fewer digits dd, but larger multipliers. Smaller BB means more digits but smaller multipliers. The optimal choice balances dBd \cdot B.

Example

With B=256B = 256 and d=4d = 4:

ap=0x12345678a_p = \texttt{0x12345678}

g1(0x12345678)=(0x78,0x56,0x34,0x12)g^{-1}(\texttt{0x12345678}) = (\texttt{0x78}, \texttt{0x56}, \texttt{0x34}, \texttt{0x12})

ap(0)K[0]=0x78Encs(s1)a_p^{(0)} \cdot K[0] = \texttt{0x78} \cdot \text{Enc}_{s'}(s \cdot 1)

ap(1)K[1]=0x56Encs(s256)a_p^{(1)} \cdot K[1] = \texttt{0x56} \cdot \text{Enc}_{s'}(s \cdot 256)

ap(2)K[2]=0x34Encs(s65536)a_p^{(2)} \cdot K[2] = \texttt{0x34} \cdot \text{Enc}_{s'}(s \cdot 65536)

ap(3)K[3]=0x12Encs(s16777216)a_p^{(3)} \cdot K[3] = \texttt{0x12} \cdot \text{Enc}_{s'}(s \cdot 16777216)

Summing all terms:

i=03ap(i)K[i]Encs(sap)\sum_{i=0}^{3} a_p^{(i)} \cdot K[i] \approx \text{Enc}_{s'}(s \cdot a_p)

The maximum noise multiplier is max(ap(i))=0x78=120\max(a_p^{(i)}) = \texttt{0x78} = 120, compared to ap=0x12345678305,419,896a_p = \texttt{0x12345678} \approx 305{,}419{,}896 without decomposition — a 2.5 million× reduction in noise growth.

Extracting the LWE Ciphertext

Recall, by now you have an RLWE ciphertext (bp,ap)(b'_p, a'_p) under secret ss'.

The constant term of the result polynomial contains the original encrypted value μ0\mu_0.

Recall the Polynomial Embedding step: the new LWE ciphertext (b,a)(b', a') is constructed by reading coefficients from the RLWE ciphertext:

  • bb' equals the constant term of bpb'_p
  • aa' comes from the coefficients of apa'_p, with appropriate negation due to the negacyclic structure:
    • a0a_0' is coefficient 0 of apa'_p
    • aia_i' for i>0i > 0 is -(coefficient NiN - i) of apa'_p

The negation arises because we embedded ss using negative powers of XX (i.e., s(X)=i=0N1siXis(X) = \sum_{i=0}^{N-1} s_i \cdot X^{-i}), which map to negated coefficients under the negacyclic property Xk=XNkX^{-k} = -X^{N-k}. When extracting back to LWE form, we must "undo" this transformation, hence the negation for indices i>0i > 0.

You now have an LWE ciphertext (b,a)(b', a') encrypting the same value μ0\mu_0 under secret ss'.

Putting It All Together

We have shown how to convert an LWE ciphertext to an RLWE ciphertext and back by following these steps:

  1. Embed LWE → RLWE via polynomial embedding
  2. Key-switch RLWE using gadget decomposition for noise control
  3. Extract coefficients to get new LWE ciphertext

The key insight is that the constant term of the result polynomial contains the original encrypted value μ0\mu_0, and the new LWE ciphertext is constructed by reading coefficients from the RLWE ciphertext.

This conversion has enabled us to reduce the LWE Key Switching runtime from O~(N2)\tilde{O}(N^2) in a naive approach to O~(N)\tilde{O}(N).

See reference implementation here.

Footnotes

  1. The O~\tilde{O} notation hides logarithmic factors, i.e., O~(f(N))=O(f(N)polylog(N))\tilde{O}(f(N)) = O(f(N) \cdot \text{polylog}(N)).