In this section, we will explain how to homomorphically rotate the elements of an input vector after it is already encoded as a polynomial and encrypted as an RLWE ciphertext. In §A-5.2, we learned how to rotate the coefficients of a polynomial. However, rotating the plaintext polynomial or RLWE ciphertext polynomials does not necessarily rotate the input vector, which is the source of them.
The key requirement of homomorphic rotation of input vector slots (i.e., input vector) is that this operation should be performed on the RLWE ciphertext such that after this operation, if we decrypt the RLWE ciphertext and decode it, the recovered input vector will be in a rotated state as we expect. We will divide this task into the following two sub-problems:
In this task, our goal is to modify the plaintext polynomial such that the first-half elements of the input vector are shifted to the left by positions in a wrapping manner among them, and the second-half elements of are also shifted to the left by positions in a wrapping manner among them. Specifically, if is defined as follows:
Then, we will denote the -shifted vector as follows:
Remember from §D-2.2 that the BFV encoding scheme’s components are as follows:
# -dimensional input vector
, where ( is a generator of )
# The encoding matrix that converts into ( i.e., coefficients of the plaintext polynomial )
# A vector containing the scaled integer coefficients of the plaintext polynomial
# The integer polynomial that isomorphically encodes the input vector
We learned from §A-10.6 that decoding the polynomial back to is equivalent to evaluating at the following distinct primitive -th root of unity: . Thus, the above decoding process is equivalent to the following:
Now, our next task is to modify to such that decoding will give us a modified input vector that is a rotation of the first half elements of by positions to the left (in a wrapping manner among them), and the second half elements of it also rotated by positions to the left (in a wrapping manner among them). To accomplish this rotation, we will take a 2-step solution:
, where is the number of rotation positions to be applied to .
Converting into : Our first task is to convert into , which is equivalent to applying our new mapping , such that decoding gives a rotated input vector whose first half of the elements in are rotated by positions to the left (in a wrapping manner among them), and the second half of the elements are also rotated by positions to the left (in a wrapping manner among them). To design that satisfies this requirement, we will use the number which has the following two special properties (based on number theory):
For example, suppose the modulus . Then,
As shown above, generate all odd numbers between . Also, for each in , .
Let’s define , and . Based on and , we will define the mapping as follows:
Given a plaintext polynomial , in order to give its decoded version of input vector the effect of the first half of the elements being rotated by positions to the left (in a wrapping manner) and the second half of the elements also being rotated by positions to the left (in a wrapping manner), we update the current plaintext polynomial to a new polynomial by applying the mapping, where is the number of positions for left rotations for the first half and second half of the elements of .
Decoding into : Our second task is to modify our original decoding scheme in order to successfully decode into the rotated input vector . For this, we will modify our original isomorphic mapping , from:
# designed in §A-10.6
, to the following:
The common aspect between and is that they both evaluate the polynomial at distinct primitive -th roots of unity (i.e., for all odd between ). In the case of the mapping, note that and for each in cover all odd numbers between . Therefore, and between cover all distinct primitive -th roots of unity.
Meanwhile, the difference between and is the order of the output vector elements. In the mapping, the order of evaluated coordinates for is , whereas in the mapping, the order of evaluated coordinates is . We will later explain why we modified the ordering like this.
In the original Decoding2 process (§D-2.2), applying the mapping to a plaintext polynomial was equivalent to computing the following:
# where is the -th row of
Similarly, the modified mapping to the plaintext polynomial is equivalent to computing the following:
, where
From this point, we will replace in the Encoding1 process (§D-2.2) by , and in the Decoding2 process by .
To demonstrate that is a valid encoding matrix like and is a valid decoding matrix like , we need to prove the following 2 aspects:
(to satisfy Theorem A-11.4 in §A-11.4): This proof is split into 2 sub-proofs:
We provide the Python script that empirically demonstrates this.
Therefore, and are valid encoding & decoding matrices that transform into .
Now, let’s think about what will be the structure of (i.e., the first-half elements of being rotated positions to the left in a wrapping manner among them and the second-half elements of it also being rotated positions to the left in a wrapping manner among them). Remember that is as follows:
Thus, the state of which is equivalent to rotating by positions to the left for the first-half and second-half element groups will be the following:
Notice that the above computation of is equivalent to vertically rotating the upper rows of by positions upward (in a wrapping manner among them), rotating the lower rows of by positions upward (in a wrapping manner among them), and multiplying the resulting matrix with . However, it is not desirable to directly modify the decoding matrix like this in practice, because then the decoding matrix loses its consistency. Therefore, instead of directly modifying , we will modify to (i.e., modify to ) such that the relation holds. Let’s extract the upper-half rows of and denote this matrix as . Then, is equivalent to a Vandermonde matrix (Definition A-10.2 in §A-10.2) in the form of . Similarly, let’s extract the lower-half rows of and denote this matrix as . Then, is equivalent to a Vandermonde matrix (Definition A-10.2 in §A-10.2) in the form of .
Now, let’s vertically rotate the rows of by positions upward and denote it as ; and vertically rotate the rows of by positions upward and denote it as . And let’s denote the -dimensional vector comprising the first-half elements of as , and the -dimensional vector comprising the second-half elements of as . Then, computing (i.e., decoding) is equivalent to modifying to (whose coefficient vector is ) and then computing (i.e., decoding) . This is because:
# This is equivalent to evaluating the polynomial at the following distinct -th roots of unity:
# note that
# where contains the coefficients of the polynomial
Similarly, computing (i.e., decoding) is equivalent to modifying to (whose coefficient vector is ) and then computing (i.e., decoding) . This is because,
# This is equivalent to evaluating the polynomial at the following distinct -th roots of unity:
# note that
The above derivations demonstrate that , and . Combining these two findings, we reach the conclusion that : rotating the first-half elements of the input vector by positions to the left and the second-half elements of it by positions also to the left is equivalent to updating the plaintext polynomial to and then decoding it with the decoding matrix .
However, now a new problem is that we cannot directly update the plaintext to , because is encrypted as an RLWE ciphertext. Therefore, we need to instead update the RLWE ciphertext components to indirectly by updating to . We will explain this in the next subsection.
Given an RLWE ciphertext , our goal is to update to such that decrypting it gives the input vector . That is, the following relation should hold:
Remember that in the RLWE cryptosystem (§B-3)’s alternative version (§B-4.4), the plaintext and ciphertext pair have the following relation:
If we apply in the above relation, we can derive the following relation:
This relation implies that if we decrypt the ciphertext with as the secret key, then we get . Therefore, is the RLWE ciphertext we are looking for, because decrypting it and then decoding its plaintext will give us the input vector .
We can easily convert into by applying to for each of the and polynomials. However, after that, notice that the decryption key of the RLWE ciphertext has been changed from to . Thus, we need to additionally switch the ciphertext ’s key from , which is equivalent to converting into . For this, we will apply the BFV key switching technique (Summary D-2.8) learned in §D-2.8 as follows:
We summarize the procedure of rotating the BFV input vectors as follows:
Summary D-2.9 BFV’s Homomorphic Rotation of Input Vector Slots
To support input vector slot rotation, we update the original encoding matrix in Encoding1 as follows:
, and update the original decoding matrix in Decoding2 as follows:
, where is the rotation helper formula: ,
Suppose we have an RLWE ciphertext and a key-switching key as follows:
,
Then, the procedure of rotating the first-half elements of the ciphertext’s original input vector by positions to the left (in a wrapping manner among them) and the second-half elements of by positions to the left (in a wrapping manner among them) is as follows:
Suppose we have the following setup:
The roots of are , as demonstrated as follows:
Definition A-8.1 (in §A-8.1) states that the roots of the -th cyclotomic polynomial are the primitive -th roots of unity. And Definition A-7.1 (in §A-7.1) states that the order of the primitive -th roots of unity is . These definitions apply to both the cyclotomic polynomials over (complex numbers) and the cyclotomic polynomials over (ring).
Since are the roots of the -th cyclotomic polynomial over the ring , they are also the -th primitive roots of unity of . Therefore, their order (§A-4.1) is as demonstrated as follows:
Definition A-8.1 (in §A-8.1) and Theorem A-8.2 (§A-8.2) also state that for each primitive -th root of unity , generates all roots of the -th cyclotomic polynomial. Notice that in the case of the -th cyclotomic polynomial , its roots generate all -th roots of unity as follows:
Among as the roots of , let’s choose as the base root to construct the encoding matrix and the decoding matrix as follows:
# where
Notice that Theorem A-11.5 (in §A-11.5) is demonstrated as follows:
Now suppose that we encode the following two input vectors (i.e., input vector slots) in :
These two vectors are encoded as follows:
# where
Note that the coefficients of the scaled polynomials and are still within the range of the ciphertext domain (which must hold throughout all homomorphic computations to preserve correctness).
We decode and as follows:
The decoded and match the expected values.
Suppose we have the following setup:
The roots of are , as demonstrated as follows:
Among as the roots of , let’s choose as the base root to construct the encoding matrix and the decoding matrix as follows:
Notice that Theorem A-11.5 (in §A-11.5) is demonstrated as follows:
Now suppose that we encode the following input vector (i.e., input vector slots) in :
By rotating this vector by 3 positions to the left (i.e., the first-half slots and the second-half slots separately wrapping around within their own group), we get a new vector:
is encoded as follows:
# where
Note that the coefficients of the scaled polynomials are still within the range of the ciphertext domain (which must hold throughout all homomorphic computations to preserve correctness).
We decode as follows:
The decoded matches the expected rotated input vector .
In practice, we do not directly update to , because we would not have access to the plaintext polynomial unless we have the secret key . Therefore, we instead update to , which is equivalent to homomorphically rotating the encrypted input vector slots. Then, decrypting and decoding it would output .
Source Code: Examples of BFV’s batch encoding and homomorphic input vector rotation can be executed by running this Python script.