- Reference: Bootstrapping for Approximate Homomorphic Encryption [18]
During CKKS’s ciphertext-to-ciphertext multiplication, each ciphertext is associated with a particular multiplicative level and it decreases by 1 upon each ciphertext-to-ciphertext multiplication (by its internal modulus rescaling operation). Reaching multiplicative level 0 is equivalent to reaching the end of a ciphertext’s modulus chain and no more ciphertext-to-ciphertext multiplication can be performed. To continue with further ciphertext-to-ciphertext multiplication, CKKS provides a special operation called bootstrapping, which is a process of resetting the ciphertext’s end-of-chain modulus to the initial maximum modulus (which is either in the vanilla rescaling scheme, or in the case of using CRT, as explained in §D-3.5.4).
Suppose we have a ciphertext with multiplicative depth 0. If we decrypt a ciphertext whose multiplicative level is 0 (i.e., the ciphertext’s modulus is ), then decrypting it without reduction modulo would output:
# since
, where accounts for wrap-around modulo values– each coefficient of polynomial is some multiple of . CKKS’s bootstrapping procedure is equivalent to safely transforming a ciphertext’s modulus from to (where ).
As the first step of bootstrapping, we forcibly change the modulus of the ciphertext from to . Then, its decryption with reduction modulo would output:
Here, we assume that is large enough such that . This is true given has small coefficients which are either , and thus the coefficients of would not grow much.
In the term, notice that because of the term which is not modulo-reduced by anymore, the ciphertext’s decrypted plaintext polynomial’s each -th term would get a corrupted coefficient instead of . So, we now need to eliminate the garbage term in each coefficient and distill the pure plaintext coefficient .
To do so, we will take an approximated approach by using a sine function described in Figure 16, which has a period of with the amplitude . This sine function has the following two useful properties:
Combining these two properties, given input ,
, provided is very close to 0 relative to (i.e., ). This is true, because by construction of the CKKS scheme, the plaintext modulus (even with scaling it up by ), is significantly smaller than the ciphertext modulus. Therefore, to remove from , we can update each coefficient of the polynomial by evaluating it with the sine function. However, we cannot directly update the coefficients of the polynomial, because the CKKS scheme (the RLWE scheme in general) only supports the input vector’s slot-wise operations. Therefore, to update the polynomial coefficients, we need to express the update logic in terms of slot-wise input vector arithmetic . Considering all these, CKKS’s overall bootstrapping procedure is described in Table 6.
1 | ModRaise: Given ciphertext , we forcibly modify its modulus from to . |
Then, it ends up encrypting instead of . | |
2 | CoeffToSlot: Based on step 1’s ciphertext , we generate a new ciphertext |
that encrypts an input vector whose its each -th slot stores . | |
This is equivalent to moving the coefficients of polynomial to | |
the input vector slots. | |
3 | EvalExp: We convert the sine function into an approximated polynomial by using |
the Taylor series, as well as other optimizations such as | |
Euler’s formula (). Then, we generate a CKKS plaintext that encodes | |
this approximated sine function, and then use this to homomorphically evaluate | |
step 2’s encrypted vector elements (to homomorphically remove every . | |
4 | SlotToCoeff: Based on the resulting ciphertext from step 3, we generate a new ciphertext |
whose encrypted polynomial’s each -th coefficient is (approximately) . | |
This is equivalent to moving the -eliminated values stored in the input vector slots in | |
step 3 back to the positions of the polynomial coefficients. The final ciphertext is | |
our goal ciphertext that (approximately) encrypts under modulus . | |
We will mathematically walk through how the bootstrapping procedure (Table 6) correctly updates the modulus of the input ciphertext from to .
For ease of understanding, we will first explain how we would do modulus bootstrapping for a ciphertext with multiplicative level 0 (i.e., its modulus is ) in case we have access to the secret key . Using this key, we can decrypt the ciphertext as follows:
# where
# where accounts for any potential wrap-around modulo values
Our initial goal is to bootstrap the modulus of the ciphertext from to by using only the following three tools:
After explaining the above, we will then explain how to achieve the same bootstrapping without having access to the secret key .
ModRaise: This step forcibly changes the ciphertext’s modulus from to and then decrypts the ciphertext as follows:
Notice that the ciphertext’s decrypted plaintext polynomial’s each -th coefficient gets corrupted to . So, we now need to eliminate the garbage term in each coefficient and distill the pure plaintext coefficient .
CoeffToSlot: This step generates a new plaintext polynomial whose each -th input vector slot stores the corrupted coefficient . The trick of doing this is to apply CKKS’s batch-encoding mapping (which represents the transformation as explained in §D-3.1) to the input vector slots that encode the polynomial . Let be the input vector that corresponds to polynomial . Then, and satisfy the following relation over the encoding mapping :
# i.e., polynomial
This implies that if we homomorphically apply the transformation to the elements of the input vector , then the resulting input vector will store ’s encoded polynomial coefficient values as follows:
# where represents a linear transformation operation comprising
However, remember that at the end of the ModRaise step, we get the decrypted (but corrupted by ) polynomial and we are not allowed to decode it into . Therefore, we will instead encode the matrix in the encoding transformation () into its equivalent polynomials (treating a matrix as a combination of vectors) and then perform batched slot-wise operation between and the polynomial version of . We express this polynomial-based computation as follows:
# is the polynomial-encoded version of the transformation
Then, the resulting polynomial ’s corresponding input vector slots (i.e., the decoded version of ) will store . In other words, the above computation effectively moves the coefficients of to the input vector slots of a new plaintext polynomial.
However, remember that in CKKS, an input vector can store only up to slots, whereas we need to store a total of coefficients of in the input vector slots. Therefore, we technically need to create 2 pieces of as and , where the input vector of stores , and the input vector of stores .
EvalExp: Our next step is to update ’s each element to by evaluating it with the sine function . Since the output of the CoeffToSlot step is polynomial (technically and ), we need to apply the evaluation transformation in an encoded form. First, we approximate as a linear combination comprising only operations by using the Taylor series and Euler’s formula (will be explained later). Then, we encode (i.e., ) the approximated formula into a polynomial form, and we denote it as . Finally, we apply the transformation to as follows:
# Applying the sine function’s linear transformation to ’s each slot storing
After the linear transformation by the sine function, notice that each term gets eliminated from ’s slots (i.e. modulo reduction by ) and the resulting vector stores only the terms.
SlotToCoeff: Now that we have a polynomial whose corresponding input vector ’s slots store garbage-removed coefficients of (i.e., ) our initial plaintext polynomial, our next step is to put these coefficients stored in back to the polynomial. This is an exact reverse operation of CoeffToSlot as follows:
# is a polynomial-encoded form of the batch-decoding formula (§D-3.1)
The result is polynomial whose coefficients are garbage-eliminated (i.e., -free) versions of . Finally, we re-encrypt as as the final modulus-bootstrapped ciphertext.
Bootstrapping Without a Secret Key: So far, we have assumed that we have access to the secret key . With decryption and re-encryption enabled, the above bootstrapping steps described are mathematically equivalent to computing the following:
However, the ultimate goal of CKKS bootstrapping is to reset the modulus of a ciphertext from to without having access to .
Meanwhile, one important insight is that CKKS’s ModRaise procedure on the ciphertext from effectively transforms the ciphertext into a new one which is an encryption of . Before ModRaise, ciphertext ’s decryption relation is as follows:
After ModRaise to , its decryption relation is as follows:
# because
Therefore, the mod-raised ciphertext with noise . Thus, CKKS’s homomorphic bootstrapping strategy is to run the subsequent CoeffToSlot, EvalExp, and SlotToCoeff steps homomorphically based on the ciphertext . Running these 3 steps consumes a few multiplicative levels due to the ciphertext-to-ciphertext multiplication operations when homomorphically multiplying the coefficient-to-slot and slot-to-coefficient transformation matrices and homomorphically computing powers of (i.e., ) during sine approximation. Therefore, upon completion of these 3 steps, the ciphertext modulus reduces from (where is some integer such that ).
Note that the result of homomorphic bootstrapping is equal to the explicit bootstrapping based on decryption & re-encryption (if we ignore the small differences in the final ciphertext modulus and the noise). In the following subsections, we will explain the algebraic details of CoeffToSlot, EvalExp and SlotToCoeff steps.
Homomorphically moving the coefficients of (i.e., for ) to a new ciphertext’s input vector slots is mathematically equivalent to homomorphically computing , which is equivalent to applying the encoding formula to the input vector slot values of .
As explained in Summary D-3.9 (in §D-3.9), the encoding formula for converting an input vector into a list of polynomial coefficients is , where is a basis of the -dimensional vector space crafted as follows:
# where the rotation helper function
Therefore, given the input ciphertext whose plaintext polynomial contains corrupted coefficients, computing is equivalent to computing . However, one problem here is that each CKKS ciphertext encodes only input vector slots, whereas our goal is to move (corrupted) coefficients of the plaintext polynomial encrypted in . Therefore, we will instead generate 2 ciphertexts, and , such that each ’s input vector slots store and ’s input vector slots store .
We split the matrix into four matrices as follows:
Then, we can compute and as follows:
Each homomorphic matrix-vector multiplication (e.g., ) can be done in an efficient manner that reduces the number of homomorphic rotations (§D-2.10). can be computed by applying homomorphic conjugation to ctc (§D-3.11).
We will use the sine function to approximately eliminate from by computing . This approximation works if is very close to relative to (i.e., ). Still, the elimination of is approximate (i.e., ), because is nearby , not exactly .
One issue is that we need to evaluate homomorphically based on cts1 and cts2 as inputs (i.e., and ), but FHE supports only operations, whereas the sine graph cannot be formulated by only . Therefore, we will approximate the sine function by using the Taylor series (§A-14):
If we approximate around , then the approximated polynomial is as follows:
, where is a -degree polynomial.
Remember that in the RLWE cryptosystem, , or with some polynomial representing the wrapping around values of modulo . Since the secret key is an -degree polynomial whose coefficients are small (i.e., ), the coefficients of will have some reasonably small upper bound, which decreases with the sparsity of (i.e., the frequency of 0 coefficients in ). Therefore, the degree of our approximated only needs to be high enough to accurately evaluate values between . The required minimum degree of our approximated Taylor polynomial increases with (i.e., the upper bound of ). Our one issue is that the computation overhead for homomorphic evaluation of a polynomial generally increases exponentially with the degree of the polynomial, which will slow down bootstrapping. To reduce this computation cost, we will leverage Euler’s formula (§A-11) and its square arithmetic:
By substituting , we will use Euler’s formula. We will also approximate with the Taylor series, but instead of directly approximating , we will first approximate for some large . After that, we will iteratively square a total times. Then, we get an approximation of . The reason why we start with the approximation of instead of is that its approximation requires a small degree of polynomial, as (i.e., the input to the complex exponential function) is small provided is sufficiently large. Specifically, we learned that () is upper-bounded by , thus is upper-bounded by . As the targeted range of for approximation in is small, we need a small degree of Taylor series polynomial.
Using the Taylor series with degree around , we can approximate as:
Then, we iteratively square total times to get:
Then, based on Euler’s formula , we can derive the following relations:
Substituting , we finally get:
Using the final relation above, the EvalExp step homomorphically evaluates the approximation of where as follows:
The result of EvalExp is two ciphertexts whose input vector slots store the bootstrapped coefficients of , which are modulo-reduced from to . Note that is a bootstrapping error introduced by the following three factors: (1) the intrinsic homomorphic computation noises of the CoeffToSlot, EvalExp, and SlotToCoeff steps; (2) the EvalExp step’s Taylor polynomial approximation error of the exponential function ; (3) the EvalExp step’s sine graph error, since the graph is not exactly around , but only .
Note that since the output of the CoeffToSlot step was split into 2 ciphertexts (cts1 and cts2), the output of the EvalExp step is also in 2 ciphertexts: (ctb1 and ctb2). The input vector slots of ctb1 store , whereas the input vector slots of ctb2 store .
This step is an exact inverse of the CoeffToSlot step, which is moving the bootstrapped (i.e. modulo-reduced ) coefficients of stored in the input vector slots back to the final plaintext polynomial . Remember that the decoding formula from a polynomial to an input vector (§D-3.1) is , where:
We denote , , , and as matrices corresponding to the upper-left, upper-right, lower-left, and lower-right sections of . Then, homomorphically applying the decoding formula results in the final bootstrapped ciphertext ctfinal modulo whose plaintext polynomial is garbage-eliminated from to (where is the bootstrapping error polynomial). Note that the ciphertext modulus changed from because we consumed some multiplicative levels for computing ciphertext-to-ciphertext multiplications during polynomial evaluation (i.e., ). We can derive ctfinal by homomorphically applying the decoding transformation to the results of the EvalExp step (ctb1 and ctb2) as follows:
Note that we do not use and , because we only need to derive the input vector slots whose decoding would result in the coefficients of the final -degree polynomial. Once we generate a new ciphertext ctfinal whose input vector slots store , then its latter conjugate slots get automatically filled with the conjugates of the first slot values.
In many cases, the application of CKKS may use only a small number of input vector slots (e.g., ) out of slots. Suppose that such is some number that divides . Then, we can do a series of homomorphic rotations and multiplications to make the input vector slots store repetitions of the -slot values. Specifically, we can do this in total rounds of rotations and additions: initially, we zero-mask between the -th slot and the -th slots and save as ct, and then in each -th round we compute .
Then, we apply the optimization of sparsely packing ciphertext in Summary D-3.12 (§D-3.12): if an -dimensional input vector is structured as consecutive repetitions of the first slot values, then its encoded polynomial has the structure such that all its coefficients whose degree term is not a multiple of are zero as follows:
.
Remember that in the CoeffToSlot step (§D-3.13.3), we use the formula
to move the
-contaminated
polynomial’s coefficients to the input vector slots. But by the principle of sparsely packed ciphertext, we know that all
the slots of which are
not a multiple of
slots would store a zero coefficient. This means that we will get the same computation result even if we only compute the
formula with the rows of
whose row index is a multiple of
. Mathematically, we can update
the encoding formula to where
the matrix
Remember that in the original CoeffToSlot step (§D-3.13.3), we had to split cts into cts1 and cts2 because in CKKS each input vector can store a maximum of slots but we need to move a total of coefficient values to the input vector slots for bootstrapping. On the other hand, the computation result of the above updated encoding formula (using a sparsely packed ciphertext) is , having only coefficient slots instead of coefficient slots, and each slot index in corresponds to the encoded polynomial’s coefficient with degree term (we do not compute any other coefficient terms, because we know that they are 0 anyway, so no need to bootstrap them). And notice that , because divides . Therefore, without computing two ciphertexts and separately, we can directly compute , because all coefficients for bootstrapping fit in slots. Therefore, the number of homomorphic computations and memory requirement for the CoeffToSlot step can be reduced by half. And the same is true for the EvalExp step (§D-3.13.4).
Similarly, as for the SlotToCoeff step (§D-3.13.5), we update the decoding formula to . This again reduces the number of homomorphic computations and memory requirements for the SlotToCoeff step by half. Notice that is a matrix where those columns whose column index is not a multiple of are zero. This zero-enforcement to the columns of still outputs the same computation result, because is a vector such that those slots whose slot index is not a multiple of are zero, which makes the computation result with their corresponding columns of (i.e., the columns whose index is not a multiple of ) zero, anyway.
We summarize the CKKS bootstrapping procedure as follows.
Summary D-3.13.7 CKKS Bootstrapping
, which satisfies the decryption relation:
Move the coefficients of the encrypted plaintext to the input vector slots by homomorphically multiplying to it follows:
Remove the wrap-around garbage value in by homomorphically evaluating the polynomial which approximates a sine function with period as follows:
This step is equivalent to homomorphically performing modulo reduction by to the input value. This step reduces the ciphertext modulus from as it consumes multiplicative levels when homomorphically evaluating the polynomial approximation of the sine function.
Move the modulo--reduced plaintext value stored in the input vector slots back to the plaintext coefficient positions by homomorphically multiplying the encoding matrix as follows:
Limitation: The noise slowly grows over each bootstrapping due to the bootstrapping error and will eventually overflow the message and the ciphertext modulus.
Comparison between BFV and CKKS Bootstrapping: In the case of CKKS’s bootstrapping, it does not reduce the magnitude of the old noise and keeps it the same as before, because the sine approximation function converts into . However, as the ciphertext modulus gets increased from , the noise-to-ciphertext-modulus ratio decreases, since . On the other hand, the bootstrapping procedure introduces a new bootstrapping noise, which can be viewed as a fixed amount. However, this fixed amount of new noise accumulates over each bootstrapping. Therefore, after a very large number of bootstrappings, the noise will eventually overflow the message and even the ciphertext modulus.
In the case of BFV’s bootstrapping, it reduces the noise, but does not change the ciphertext modulus. However, there is no need to reset the ciphertext modulus, because BFV does not have a leveled ciphertext modulus chain, and BFV’s ciphertext-to-ciphertext multiplication does not consume ciphertext modulus. Furthermore, since BFV’s bootstrapping directly removes the noise, the noise is guaranteed to be kept under a certain threshold even after an infinite number of bootstrappings.
Another important difference is that CKKS’s bootstrapping does not require homomorphic decryption, primarily because it maintains the plaintext’s scaling factor to be the same across the entire bootstrapping procedure. On the other hand, BFV’s bootstrapping needs to change the plaintext’s scaling factor to run the digit extraction algorithm. Therefore, homomorphic decryption is required to change the plaintext scaling factor () while preserving the same ciphertext modulus ().
As explained in §D-3.13.4, the bootstrapping procedure generates three types of noises:
The Type-1 noise is inevitable by the design of FHE. The Type-2 noise can be either avoided or unavoidable depending on the tradeoff setup between the bootstrapping accuracy and efficiency. Unlike these two types of noises, the Type-3 noise can be effectively reduced by newer bootstrapping techniques.
Approximation (EUROCRYPT 2021 [19]): Using the function instead of the function can reduce the Type-3 noise, because its line is not curved but straight, as shown in Figure 17 (comprising a series of and segments). This technique also uses the Remez algorithm that evenly distributes the approximation error over a specified region. However, one downside of this technique is that it consumes 3 multiplicative levels.
Meta-BTS (CCS 2022 [20]): This is thus far the most computationally efficient and accurate bootstrapping technique, whose procedure is as follows:
Limitation in Noise Handling: The above bootstrapping techniques can reduce the Type-3 noise, because the bootstrapping error is smaller than the plaintext message and a smaller input value to the approximating sine function outputs a value closer to . Running this algorithm multiple times, the Type-3 noise becomes exponentially smaller, because the size of the target plaintext (i.e., the extracted bootstrapping error as the output of step 3 above) is much smaller than before. Meanwhile, Type-1 and Type-2 noises do not decrease over multiple bootstrapping rounds, relatively keeping their same level, because each round generates new Type-1 and Type-2 noises.