D-3.1 Encoding and Decoding

CKKS’s encoding and decoding is fundamentally very similar to BFV’s batch encoding scheme. BFV designs its batch encoding scheme (Summary D-2.3 in §D-2.3) based on the updated W~ and W~ matrices (Summary D-2.9.3 in §D-2.9). That is, BFV decodes a polynomial into an input slot vector by evaluating the polynomial at each root of Xn + 1, which is the primitive (μ = 2n)-th root of unity (i.e., v = W~m), and encodes an input slot vector into a polynomial by inversing this operation (i.e., m = n1 W~ InR v). This encoding and decoding scheme is designed based on Summary A-10.7 (§A-10.7) which designs the isomorphic mapping between n-dimensional vectors in a ring (finite field) and (n 1)-degree (or lesser degree) polynomials as follows:

σ : f(x) t[X]F(X)  (f(ω1),f(ω3)),,f(ω2n1)) tn

, where ω = gt1 2n is a root of (i.e., primitive (μ = 2n)-th root of unity) of the (μ = 2n)-th cyclotomic polynomial Xn + 1 defined over a prime modulo t ring.

CKKS’s batch encoding scheme uses exactly the same formula for encoding and decoding (i.e., v = WT m and m = W InR v n ), but the n-dimensional input slot vector comprises not in a ring (i.e., pn), but complex numbers (i.e., ^n). In Summary A-10.7 (§A-10.7), we also designed the mapping σc between polynomials and vectors over complex numbers as follows:

σc : f(X) [X](Xn + 1)(f(ω),f(ω3),f(ω5),,f(ω2n1)) ^n (n 2 )

, where ω = e𝑖𝜋n is a root (i.e., the primitive (μ = 2n)-th root) of the (μ = 2n)-th cyclotomic polynomial Xn + 1 defined over complex numbers, and ^n is n-dimensional complex special vector space whose second-half elements are reverse-ordered conjugates of the first-half elements. And ^n is isomorphic to n 2 , because the second-half elements of ^n are automatically determined by its first-half elements. Therefore, the σc mapping is essentially an isomorphism between n 2-dimensional complex vectors v n 2 and (n 1)-degree (or lesser degree) real-number polynomials [X](Xn + 1). Therefore, CKKS’ batch encoding scheme encodes an n 2-dimensional complex input slot vector into an (n 1)-degree (or lesser degree) real-number polynomial, and the decoding process is a reverse of this.

In addition, remember that in BFV, we updated W and WT to W~ and W~ (Summary D-2.9.3 in §D-2.9.3) to support homomorphic rotation of input vector slots. Likewise, the CKKS batch encoding scheme uses W~ and W~ instead of W and WT in order to support homomorphic rotation. Therefore, the CKKS batch encoding scheme’s isomorphic mapping is updated as follows:

σc : f(X) [X](Xn + 1)(f(ωJ(0)),f(ωJ(1)),f(ωJ(2)),,f(ωJ(n 2 1)),

f(X) [X](Xn + 1)( ,f(ωJ(0)),f(ωJ(1)),f(ωJ(2)),,f(ωJ(n 2 1))) ^n (n 2 )

, where J(h) = 5h mod 2n, a rotation helper formula.

The encoding schemes of BFV and CKKS have the following differences:

Structure of v ^n: Note that the original decoding scheme for v described in Summary A-10.7 (§A-10.7) was:

v = ( M(ω), M(ω3), M(ω5),,M(ω2n3), M(ω2n1))

, which decodes to a Hermitian vector:

v = (v0,v1,,vn 2 1,v¯n 2 1,,v¯1,v¯0)

, whose second-half elements are reverse-ordered conjugates of the first-half elements.

However, by replacing W and WT with W~ and W~, we changed the above decoding scheme to the following that supports homomorphic rotation:

v = ( M(ωJ(0)), M(ωJ(1)), M(ωJ(2)),,M(ωJ(n 2 1)), M(ωJ(0)), M(ωJ(1)),,M(ωJ(n 2 1)) )

v = ( M(ωJ(0)), M(ωJ(1)), M(ωJ(2)),,M(ωJ(n 2 1)), M(ω¯J(0)), M(ω¯J(1)),,M(ω¯J(n 2 1)) )

# because ω1 = (e𝑖𝜋 n )1 = e𝑖𝜋 n = ω¯

, which decodes to a forward-ordered (not reverse-ordered) Hermitian vector as follows:

v = (v0,v1,,vn 2 1,v¯0,v¯1,,v¯n 2 1,)

, whose second-half elements are conjugates of the first-half elements with the same order. Upon homomorphic rotation (which will be explained in §D-3.9), just like in BFV’s homomorphic rotation, the first-half elements and the second-half elements of v rotate within their own group in a wrapping manner.

We summarize CKKS’s encoding and decoding procedure as follows, which is similar to BFV’s encoding and decoding procedure (described in Summary D-2.2.5 in §D-2.2.5):

Summary D-3.1 CKKS’s Encoding and Decoding

Input: An n 2-dimensional complex vector v = (v0,v1,,vn 2 1) n 2


Encoding:

1.
Convert (i.e., isomorphically transform) v into an n-dimensional forward-ordered Hermitian vector v as follows:

v = (v0,v1,,vn 2 1,v¯0,v¯1,,v¯n 2 1) ^n

2.
Convert v into a real number vector m by applying the transformation m = W~ InR v n

, where W~ is a basis of the n-dimensional vector space crafted as follows:

W~ = [ 1 1 1 1 1 1 (ωJ(n2 1)) (ωJ(n2 2)) (ωJ(0)) (ωJ(n2 1)) (ωJ(n2 2)) (ωJ(0)) (ωJ(n2 1))2 (ωJ(n2 2))2 (ωJ(0))2 (ωJ(n2 1))2 (ωJ(n2 2))2 (ωJ(0))2 (ωJ(n2 1))n1 (ωJ(n2 2))n1 (ωJ(0))n1 (ωJ(n2 1))n1 (ωJ(n2 2))n1 (ωJ(0))n1 ]

# where ω = e𝑖𝜋n = cos (π n) + isin (π n)

= [ 1 1 1 1 1 1 (ωJ(n 2 1)) (ωJ(n 2 2)) (ωJ(0)) (ω¯J(n 2 1)) (ω¯J(n 2 2)) (ω¯J(0)) (ωJ(n 2 1))2 (ωJ(n 2 2))2 (ωJ(0))2 (ω¯J(n 2 1))2 (ω¯J(n 2 2))2 (ω¯J(0))2 (ωJ(n 2 1))n1 (ωJ(n 2 2))n1 (ωJ(0))n1 (ω¯J(n 2 1))n1 (ω¯J(n 2 2))n1 (ω¯J(0))n1 ]

# because ω1 = e𝑖𝜋 n = e𝑖𝜋 n ¯ = ω¯

3.
Convert m into a scaled integer vector ΔmΔm, where Δ is a scaling factor bigger than 1 such that Δmi never overflows or underflows q0 (i.e., 0 Δmi < q0 or q0 2 Δmi < q0 2 ) in all cases, even across all homomorphic operations. The finally encoded plaintext polynomial is ΔM = i=0n1ΔmiXi  q[X](Xn + 1). The rounding process of Δm during the encoding process causes an encoding error, which makes CKKS an approximate encryption scheme.


Decoding: From the plaintext polynomial ΔM = i=0n1ΔmiXi, recover m = Δm Δ . Then, compute v = W~m, where:

W~ = [ 1 (ωJ(0)) (ωJ(0))2 (ωJ(0))n1 1 (ωJ(1)) (ωJ(1))2 (ωJ(1))n1 1 (ωJ(2)) (ωJ(2))2 (ωJ(2))n1 1 (ωJ(n 2 1)) (ωJ(n 2 1))2 (ωJ(n 2 1))n1 1 (ωJ(0)) (ωJ(0))2 (ωJ(0))n1 1 (ωJ(1)) (ωJ(1))2 (ωJ(1))n1 1 (ωJ(2)) (ωJ(2))2 (ωJ(2))n1 1 (ωJ(n 2 1)) (ωJ(n 2 1))2 (ωJ(n 2 1))n1 ]

= [ 1 (ωJ(0)) (ωJ(0))2 (ωJ(0))n1 1 (ωJ(1)) (ωJ(1))2 (ωJ(1))n1 1 (ωJ(2)) (ωJ(2))2 (ωJ(2))n1 1 (ωJ(n 2 1)) (ωJ(n 2 1))2 (ωJ(n 2 1))n1 1 (ω¯J(0)) (ω¯J(0))2 (ω¯J(0))n1 1 (ω¯J(1)) (ω¯J(1))2 (ω¯J(1))n1 1 (ω¯J(2)) (ω¯J(2))2 (ω¯J(2))n1 1 (ω¯J(n 2 1)) (ω¯J(n 2 1))2 (ω¯J(n 2 1))n1 ]

, and extract only the first n 2 elements in the forward-ordered Hermitian vector v to recover the input vector v.

CKKS’s Approximation Property: In the encoding process, when we convert v m Δm, we multiply v by W~ which contains real numbers with infinite decimals (e.g., 2) coming from Euler’s formula, which we should round to the nearest integer by computing Δm (which we will denote as Δm throughout this section for simplicity) and thus we lose some precision. This implies that if we later decode Δm into vd, this value would be slightly different from the original input vector v . As CKKS’s encoding scheme is subject to such a small rounding error, the decryption does not perfectly match the original input vector. Such errors also propagate across homomorphic computations, because those computations are done based on approximately encoded plaintext Δm. As these errors are caused by throwing away the infinitely long decimal digits, they can be corrected during the decoding process only if we use an infinitely big scaling factor Δ, which is impossible because Δmi should not overflow the ciphertext modulus q0 of the lowest multiplicative level. Due to this limitation, CKKS is considered an approximate homomorphic encryption.

D-3.1.1 Example

Suppose our input complex vector’s dimension n 2 = 2, the bounding polynomial degree n = 4, and the scaling factor Δ = 1024.

Our basis of the n-dimensional vector space

W~ = [ 1 1 1 1 ωJ(1) ωJ(0) ω¯J(1) ω¯J(0) (ωJ(1))2 (ωJ(0))2 (ω¯J(1))2 (ω¯J(0))2 (ωJ(1))3 (ωJ(0))3 (ω¯J(1))3 (ω¯J(0))3 ] = [ 1 1 1 1 ω5 ω ω¯5 ω¯ ω2 ω2 ω2¯ ω¯2 ω7 ω3 ω¯7 ω¯3 ]

, where ω = e𝑖𝜋n = cos (π n) + isin (π n)

Given this setup, suppose we have the input complex vector v = (1.1 + 4.3i, 3.5 1.4i) to encode.

First, construct the forward-ordered Hermitian vector v = (1.1 + 4.3i, 3.5 1.4i, 1.1 4.3i, 3.5 + 1.4i).

Next, convert the complex vector v into a real number vector m by applying the transformation:

m = W~ InR v n = 1 4[ 1 1 1 1 ω5 ω ω¯5 ω¯ ω2 ω2 ω¯2 ω¯2 ω7 ω3 ω¯7 ω¯3 ] [ 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 ][ 1.1 + 4.3i 3.5 1.4i 1.1 4.3i 3.5 + 1.4i ]

= W InR v n = 1 4[ 1 1 1 1 ω¯ ω¯5 ω ω5 ω¯2 ω¯2 ω2 ω2 ω¯3 ω¯7 ω3 ω7 ] [ 1.1 + 4.3i 3.5 1.4i 1.1 4.3i 3.5 + 1.4i ]

= 1 4 [ (1.1 + 4.3i) + (3.5 1.4i) + (1.1 4.3i) + (3.5 + 1.4i) (1.1 + 4.3i)ω¯ + (3.5 1.4i)ω¯5 + (1.1 4.3i)ω + (3.5 + 1.4i)ω5 (1.1 + 4.3i)ω2¯ + (3.5 1.4i)ω2¯ + (1.1 4.3i)ω2 + (3.5 + 1.4i)ω2 (1.1 + 4.3i)ω¯3 + (3.5 1.4i)ω¯7 + (1.1 4.3i)ω3 + (3.5 + 1.4i)ω7 ]

= 1 4 [ (1.1 + 4.3i) + (3.5 1.4i) + (1.1 4.3i) + (3.5 + 1.4i) (1.1 + 4.3i) + (3.5 1.4i)ω¯5 + (1.1 4.3i)ω + (3.5 + 1.4i)ω5 (1.1 + 4.3i)ω2¯ + (3.5 1.4i)ω2¯ + (1.1 4.3i)ω2 + (3.5 + 1.4i)ω2 (1.1 + 4.3i)ω¯3 + (3.5 1.4i)ω¯7 + (1.1 4.3i)ω3 + (3.5 + 1.4i)ω7 ]

= 1 4 [ 9.2 1.1(ω¯ + ω) + 4.3i(ω¯ ω) + 3.5(ω¯5 + ω5) 1.4i(ω¯5 ω5) 1.1(ω¯2 + ω2) + 4.3i(ω¯2 ω2) + 3.5(ω¯2 + ω2) 1.4i(ω¯2 ω2) 1.1(ω¯3 + ω¯3) + 4.3i(ω¯3 ω¯3) + 3.5(ω¯7 + ω¯7) 1.4i(ω¯7 ω¯7) ]

= 1 4 [ 9.2 1.1 (2cosπ 4) 4.3i (2isinπ 4) + 3.5 (2cos5π 4 ) + 1.4i (2isin5π 4 ) 1.1 (2cosπ 2) 4.3i (2isinπ 2) + 3.5 (2cosπ 2) + 1.4i (2isinπ 2) 1.1 (2cos3π 4 ) 4.3i (2isin3π 4 ) + 3.5 (2cos7π 4 ) + 1.4i (2isin7π 4 ) ]

= 1 4 [ 9.2 1.1 (22 2 ) + 4.3 (22 2 ) + 3.5 (22 2 ) 1.4 (22 2 ) 1.1(2 0) + 4.3(2 1) + 3.5(2 0) 1.4(2 1) 1.1 (2 2 2 ) + 4.3 (22 2 ) + 3.5 (22 2 ) 1.4 (22 2 ) ]

= 0.25[ 9.2 1.12 + 4.32 3.52 + 1.42 1.1(0) + 4.3(2) 3.5(0) 1.4(2) 1.12 + 4.32 + 3.52 + 1.42 ] = [ 2.3 0.8252 1.45 2.0252 ] (2.3, 1.1657, 1.45, 2.8638)

Convert the real number vector m into a scaled integer vector Δm by Δ-scaling and rounding as follows:

Δm Δm= 1024 (2.3, 1.1657, 1.45, 2.8638)= (2355, 1195, 1485, 2933)

Finally, v = (1.1 + 4.3i, 3.5 1.4i) has been encoded into the plaintext polynomial M(X) as follows:

ΔM(X) = 2355 + 1195X + 1485X2 + 2933X3 R4

To decode m, we compute:

v = WT Δm Δ = [ 1,ω,ω2,ω3 1,ω3,ω6,ω 1,ω¯,ω2¯,ω3¯ 1,ω3¯,ω6¯,ω¯ ] [ 2355 1195 1485 2933 ] 1 1024

= [ 1,2 2 + i2 2 ,i,2 2 + i2 2 1,2 2 + i2 2 ,i,2 2 + i2 2 1,2 2 i2 2 ,i,2 2 i2 2 1,2 2 i2 2 ,i,2 2 i2 2 ] [ 2.2998046875 1.1669921875 1.4501953125 2.8642578125 ]

(1.0997 + 4.3007i, 3.5000 1.4003i, 1.0997 4.3007i, 3.5000 + 1.4003i)

Extract the first n 2 = 2 elements in the Hermitian vector v to recover the input vector:

(1.0997 + 4.3007i, 3.5000 1.4003i)

(1.1 + 4.3i, 3.5 1.4i) = v # The original input vector

Because of the rounding drifts for converting square roots into integers, the decoded value is slightly different from the original input complex values. This is why CKKS is called an approximate homomorphic encryption.

Source Code: Examples of CKKS encoding can be executed by running this Python script.