Keywords

1 Introduction

Fully Homomorphic Encryption. A fully homomorphic encryption (FHE) scheme presents a way to perform arbitrary calculations on encrypted data without the requirement of decryption. The first construction of FHE [11, 12] was given by Gentry in 2009. Several improvements [4,5,6, 10, 13, 14, 25, 27] have followed since then, developing a diversity of features and complexity assumptions. HElib [17,18,19] is a library for FHE widely used in applications, which implements the BGV scheme [3]. It allows for the “packing” of ciphertexts and single instruction multiple data (SIMD) computations, amortizing the cost for certain tasks.

There are numerous applications of FHE, but one of the most remarkable is privacy-preserving delegated computations, such as privacy-preserving machine learning as a service. In the service, users do not wish to reveal their sensitive data to the server, and the server does not want to reveal the cognitive model to users. FHE enables these scenarios in an elegant way with non-interactivity. However, because of the inefficiency of existing FHE schemes, most applications are constructed evading the non-crypto-friendly calculations such as comparison, division, and some non-linear functions.

Bit-Wise Encryption vs. Integer-Wise Encryption. Most FHE schemes, including the BGV scheme, feature integer-wise and bit-wise encryption; the size of the plaintext space in the scheme is variable. In bit-wise encryption the plaintext space is \(\mathbb {Z}_2\), and in integer-wise encryption the plaintext space is \(\mathbb {Z}_p\) where \(p>2\). Because the main libraries of FHE, including HElib, do not support some basic integer arithmetic operations such as division and comparison, several studies [8, 9, 28] have been performed on improved arithmetic. The proposed algorithms are primarily for bit-wise encryption, and they simply leverage the existing algorithms for such operations on the bit-wise circuit such as Ripple carry adder, long multiplication, and non-restoring division. Although bit-wise encryption can perform integer comparison very efficiently [7], integer addition and multiplication are not practical since they require homomorphic multiplication. On the other hand, integer-wise arithmetic can naturally perform integer addition and multiplication efficiently, and recent remarkable privacy-preserving machine learning such as [1, 2, 15, 20] use integer-wise encryption. However, the algorithm for these applications evades arithmetic such as division and comparison, which are believed to be inefficient. While a concrete algorithm for secure integer-wise comparison has been recently proposed in [22], to the best of our knowledge there is no known concrete algorithm for secure integer-wise division algorithm. Emergence of efficient algorithms for basic arithmetic operations such as division and comparison will undoubtedly increase options to optimise higher level applications of secure computation.

Our Contribution. We present a new concrete algorithm for privacy preserving integer-wise division. Although several studies have been performed on privacy preserving bit-wise division algorithms [8, 9, 28], there is no known concrete algorithm for the integer-wise version. We implement our division algorithm using HElib, and test its performance. The experimental results show that our algorithm performs 2.45 times faster than the fastest bit-wise algorithm [8]. We also theoretically analyse the multiplicative depth, which is a barometer for the complexity for the FHE-based algorithm. While the order of the multiplicative depth of existing division algorithms [8, 9, 28] is \(O(l^2)\) for l-bit size integers, we show that our algorithm can perform with O(l).

Furthermore, we generalise our secure division algorithm and propose an algorithm for secure calculation of a general 2-variable function; the order of multiplicative depth of the algorithm is O(l), which is the same as our secure division algorithm. This is the first result to construct a concrete algorithm for performing the general 2-variable function, expanding the FHE application diversity.

2 Preliminaries

2.1 Notation

In the FHE construction, a ring R is used, whose elements are written in lower case; for example, \(r \in R\). For an integer q, we use \(R_q\) to denote R / qR. For \(a \in R\), we use the notation \([a]_q\) to refer to \(a \bmod {q}\), with coefficients reduced to the range \((-\frac{q}{2}, \frac{q}{2}]\). A concrete instantiation for our applications is the quotient polynomial ring \(R_q=\mathbb {Z}_q[x] /\varPhi _m(x)\), where q is a prime and \(\varPhi _m(x)\) is the m-th cyclotomic polynomial. We denote a ciphertext of r, which is encrypted with a FHE scheme, by \(C_r\).

We denote the logarithm to base 2 and the natural logarithm as \(\log (\cdot )\) and \(\ln (\cdot )\), respectively. We denote vectors in bold. The notation \(\varvec{v}[i]\) refers to the \(i^{\mathrm {th}}\) coefficient of \(\varvec{v}\), while the scalar product of two vectors \(\varvec{u},\varvec{v} \in R^n\) is denoted as \(\langle \varvec{u}, \varvec{v} \rangle = \sum _{i=1}^n \varvec{u}[i]\cdot \varvec{v}[i]\in R\). By \((\varvec{a} \Vert \varvec{b})\) we denote the concatenation of two vectors \(\varvec{a}\) and \(\varvec{b}\). We write \(\varvec{s} \xleftarrow []{U}\mathcal {S}\) to denote the process of sampling \(\varvec{s}\) uniformly at random over \(\mathcal {S}\); when the set \(\mathcal {S}\) is clear from the context, we will write \(e \leftarrow \mathcal {\chi }\) to denote the process of sampling e according to the probability distribution \(\mathcal {\chi }\) over \(\mathcal {S}\).

2.2 The BGV Scheme

A FHE scheme is a public-key cryptographic scheme that includes two operations \((+, \cdot )\) on ciphertexts such that: \(\mathsf{Dec}(C_a + C_b) = a + b\), \(\mathsf{Dec}(C_a \cdot C_b) = a \cdot b\). The BGV scheme [3] is a widely used FHE scheme for practical applications, which is implemented in the FHE library HElib [16]. The security of the scheme is based on the standard assumptions of the Learning with Error (LWE) problem [23] or Ring-LWE (RLWE) problem [21]. This is in contrast to the earlier FHE constructions [11, 12] which were based on ad-hoc average-case assumptions on ideal lattice problems.

The Basic Encryption Scheme. BGV is a public-key cryptography scheme E = (E.Setup, E.SecretKeyGen, E.PublicKeyGen, E.Enc, E.Dec) defined as follows.

  • Setup(\(1^\lambda \)). Given the security parameter \(\lambda \) as input, set an integer \(m = m(\lambda )\) that defines the cyclotomic polynomial \(\varPhi _m(x)\), and the odd modulus \(q=q(\lambda )\). If \(R=\mathbb {Z}[x] /\varPhi _m(x)\), the underlying working ring is \(R_q=\mathbb {Z}_q[x] /\varPhi _m(x)\). Set a plaintext modulus p that is relatively prime to q, with the plaintext space given by \(R_p=\mathbb {Z}_p[x] /\varPhi _m(x)\). Set a noise distribution \(\chi = \chi (\lambda )\) over the underlying working ring, and \(N = N(\lambda ) = \text {polylog}(q)\). Output \(params = (R, m, q, p, \chi , N)\).

  • SecretKeyGen(params). Sample \(s \leftarrow \chi \). Output the secret key \(sk = \varvec{s} := (1,s) \in R_q^2.\)

  • PublicKeyGen(paramssk). Take as input the secret key \(sk=\varvec{s}=(1,s)\) and params. Sample \(\varvec{a} \xleftarrow []{U}R_q^N\) and \(\varvec{e} \leftarrow \chi ^N\). Set \(\varvec{b}:= s\varvec{a} + p\varvec{e} \in R_q^N\), and output the public key defined as \( pk = \varvec{A}: = (\varvec{b} , - \varvec{a} ) \in R_q^{N\times 2}. \) Notice that \(\varvec{A}\cdot \varvec{s} = \varvec{b}-s\varvec{a} = p\varvec{e}\), from the definition of \(\varvec{b}\).

  • Enc(paramspkm). To encrypt a message \(m \in R_p\), set \(\varvec{m}=(m,0) \in R_p^2\), sample \(\varvec{r} \xleftarrow []{U}R_p^N\) and output the ciphertext \( \varvec{c}:= \varvec{m} + \varvec{r}^{\top }\varvec{A} \in R_q^2. \)

  • Dec \((params,sk,\varvec{c})\). Output the message \(m := [[\langle \varvec{c},\varvec{s} \rangle ]_q]_p.\)

The decryption works because

$$\begin{aligned}{}[[\langle \varvec{c},\varvec{s} \rangle ]_q]_p&= [[(\varvec{m} + \varvec{r}^{\top }\varvec{A})\cdot \varvec{s}]_q]_p = [[m + p\varvec{r}^{\top }\varvec{e}]_q]_p = [m + p\varvec{r}^{\top }\varvec{e}]_p =m, \end{aligned}$$

where the third equality holds since \(\varvec{r}\) and \(\varvec{e}\) have small enough entries so that the value \(m + p\varvec{r}^{\top }\varvec{e}\) is smaller than the modulus q.

The FHE Scheme. As a FHE scheme, the BGV scheme supports addition and multiplication over the plaintext and ciphertext spaces. Let \(\varvec{c}_a\) and \(\varvec{c}_b\) be ciphertexts of plaintexts a and b under the same key sk, respectively. The addition of two ciphertexts is simply a component-wise addition, i.e.

$$\begin{aligned} \varvec{c}_a + \varvec{c}_b = (\varvec{c}_a[0], \varvec{c}_a[1]) + (\varvec{c}_b[0], \varvec{c}_b[1]) = (\varvec{c}_a[0] + \varvec{c}_b[0], \varvec{c}_b[1]+ \varvec{c}_a[1]) = \varvec{c}_{a+b} , \end{aligned}$$

which is a ciphertext of \(a + b \in R_p\). The homomorphic multiplication is performed by the tensor product of two ciphertexts. The tensor product of ciphertexts

$$\begin{aligned} \varvec{c}_{a\cdot b}:= \varvec{c}_a \otimes \varvec{c}_b&:= (\varvec{c}_a[0]\varvec{c}_b[0], \varvec{c}_a[0]\varvec{c}_b[1] + \varvec{c}_a[1]\varvec{c}_b[0], \varvec{c}_a[1]\varvec{c}_b[1]) \end{aligned}$$
(1)

is a ciphertext of \(a \cdot b \in R_p\) under the new secret key \(\varvec{s}':= \varvec{s} \otimes \varvec{s}\). In this way, the homomorphic multiplication increases the size of ciphertexts exponentially. In order to deal with this expanding ciphertext, the BGV scheme features key switching. The key switching function SwitchKey \((\tau _{\varvec{s}' \rightarrow \varvec{\overline{s}}}, \varvec{c}',q)\) takes the ciphertext \(\varvec{c}'\) under \(\varvec{s}'\) and outputs a new ciphertext \(\varvec{\overline{c}}\) that encrypts the same message under the secret new key \(\varvec{\overline{s}}\). Using this function, we can reduce the size of ciphertext \(\varvec{c}_{a\cdot b} \in R_q^3\) to \(\varvec{\overline{c}}_{a\cdot b}\in R_q^2 \leftarrow \) \(\mathsf{SwitchKey}(\tau _{\varvec{s}' \rightarrow \varvec{\overline{s}}}, \varvec{c}_{a\cdot b})\). The BGV scheme also features modulus switching techniques, which reduce the magnitude of the noise of the ciphertext by switching the modulus from q to the smaller modulus \(q'\). The modulus switching function \(\mathsf{Scale}(\varvec{c}, q, q', p)\), takes a ciphertext \(\varvec{c}\) for modulus q and outputs a ciphertext under same secret for modulus \(q'\).

We now briefly describe the BGV FHE scheme. The scheme is a levelled FHE scheme.

  • FHE.Setup(\(1^\lambda , 1^L\)). Takes as input the security parameter \(\lambda \) and a number of levels L. Set an integer \(m = m(\lambda ,L)\) that defines the cyclotomic polynomial \(\varPhi _m(x)\). Let \(\mu = \mu (\lambda ,L,b) = \theta (\log \lambda + \log L)\) be a parameter to define the bit size of the moduli. For \(j = L\) (input level of circuit) to 0 (output level), run \({params}_j \leftarrow \mathsf{E}.\mathsf{Setup}(1^\lambda ,1^{(j+1)\cdot \mu },b)\) to obtain a list of parameters, including a list of moduli \(\{ q_L\) \(((L + 1)\cdot \mu \) bits), \(q_{L-1}\), \(\dots \), \(q_0\) \((\mu \) bits\()\}\).

  • FHE.KeyGen(\({params}_j\)). For \(j = L\) down to 0, do the following:

    1. 1.

      Run the basic schemes \(\varvec{s}_j \leftarrow \mathsf{E}.\mathsf{SecretKeyGen}({params}_j)\), and \(\varvec{A}_j \leftarrow \mathsf{E}.\mathsf{PublicKeyGen}({params}_j, \varvec{s}_j)\).

    2. 2.

      Set \(\varvec{s}_j' \leftarrow \varvec{s}_j \otimes \varvec{s}_j\).

    3. 3.

      Run \(\tau _{\varvec{s}'_{j} \rightarrow \varvec{s}_{j-1}} \leftarrow \mathsf{SwitchKeyGen}(\varvec{s}'_{j}, \varvec{s}_{j-1})\), where \(\mathsf{SwitchKeyGen}\) is a generator function of auxiliary information \(\tau _{\varvec{s}'_{j} \rightarrow \varvec{s}_{j-1}}\) that will be used for \(\mathsf{SwitchKey}\). (Note that we omit this step when \(j = 0\).)

    4. 4.

      Output \(sk:= \{\varvec{s}_j\}_{j=0}^L\), \(pk=\{\varvec{A}_j\}_{j=0}^L.\)

  • FHE.Enc(paramspkm). Take a message m in \(R_p\). Run \(\varvec{c}\) \(\leftarrow \) E.Enc \((params_L, \varvec{A}_L, m)\) of the basic scheme.

  • FHE.Dec(\(params, sk, \varvec{c}\)). Suppose that the input ciphertext \(\varvec{c}\) is under key \(\varvec{s}_j\). Here, we know the level (the index j) of the ciphertext from its augmented information. Run E.Dec \(({params}_j, \varvec{s}_j, \varvec{c})\).

  • \(\mathsf{FHE}.\mathsf{Eval}(pk, f , \varvec{c}_1, \dots , \varvec{c}_l)\). Take as input a circuit f for ciphertexts \(\varvec{c}_1, \dots , \varvec{c}_l\). It is assumed that f is a levelled circuit composed of layers of alternating addition and multiplication gates. \(\mathsf{FHE}.\mathsf{Eval}\) will invoke \(\mathsf{FHE}.\mathsf{Add} \) and \(\mathsf{FHE}.\mathsf{Mult} \), which is described next, to compute the circuit. The ciphertext refreshing procedure FHE.Refresh (described later) is invoked after every multiplication layer, in order to reduce the noise in the ciphertexts and move it to a different level.

    • \(\mathsf{FHE}.\mathsf{Add} (pk, \varvec{c}_1, \varvec{c}_2)\). Takes two ciphertexts encrypted under the same \(\varvec{s}_j\). If they are not under the same key, use \(\mathsf{FHE}.\mathsf{Refresh}\) to make one of them, the level of which is higher than the other, to be encrypted under \(\varvec{s}_j\). Output \(\varvec{c}_3 \leftarrow \varvec{c}_1 + \varvec{c}_2 \bmod {q_j}\).

    • \(\mathsf{FHE}.\mathsf{Mult} (pk,\varvec{c}_1,\varvec{c}_2)\). Takes two ciphertexts encrypted under the same \(\varvec{s}_j\). If they are not under the same key, use \(\mathsf{FHE}.\mathsf{Refresh}\) to make one of them, the level of which is higher than the other, to be encrypted under \(\varvec{s}_j\). Multiply the two ciphertexts, then obtain the new ciphertext \(\varvec{c}_3\) under the long secret key \(\varvec{s}'_j = \varvec{s}_j \otimes \varvec{s}_j\). \(\varvec{c}_3\) is the coefficient vector of \(\langle \varvec{c} \otimes \varvec{c}, \varvec{x} \otimes \varvec{x} \rangle \). Then, output \(\varvec{c}_4 \leftarrow \mathsf{FHE}.\mathsf{Refresh}(\varvec{c}_3, \tau _{\varvec{s}'_{j} \rightarrow \varvec{s}_{j-1}}, q_j, q_{j-1})\).

  • \(\mathsf{FHE}.\mathsf{Refresh}(\varvec{c}, \tau _{\varvec{s}'_{j} \rightarrow \varvec{s}_{j-1}}, q_j, q_{j-1})\). Takes a ciphertext encrypted under \(\varvec{s}'_{j}\), the auxiliary information \(\tau _{\varvec{s}'_{j} \rightarrow \varvec{s}_{j-1}}\) for key switching, and the current and next moduli \(q_j\) and \(q_{j-1}\). Perform the following.

    1. 1.

      (Key switching.) Set \(\varvec{c}_1 \leftarrow \mathsf{SwitchKey}(\tau _{\varvec{s}'_{j} \rightarrow \varvec{s}_{j-1}}, \varvec{c}, q_j)\), a ciphertext under the key \(\varvec{s}_{j-1}\) for modulus \(q_j\).

    2. 2.

      (Moduli switching.) Set \(\varvec{c}_2 \leftarrow \mathsf{Scale}(\varvec{c}_1, q_j, q_{j-1}, p)\), a ciphertext under the key \(\varvec{s}_{j-1}\) for modulus \(q_{j-1}\). Output \(\varvec{c}_2\).

Multiplicative Depth and Level Parameter \({\varvec{L}}\). As mentioned in [3], we do not need to perform \(\mathsf{FHE}.\mathsf{Refresh}\) after addition. We do not perform \(\mathsf{SwitchKey}\) after addition either, since addition does not increase the size of the ciphertext. Moreover, since addition increases the noise much more slowly than multiplication, we do not need to perform \(\mathsf{Scale}\) after addition either. Finally we also note that in HElib, \(\mathsf{FHE}.\mathsf{Refresh}\) is performed only after \(\mathsf{FHE}.\mathsf{Mult} \) is performed.

The parameter L, which indicates the number of levels of arithmetic circuit that the scheme is capable of evaluating, is very important when we estimate the complexity of the FHE circuit. Every time we perform \(\mathsf{FHE}.\mathsf{Mult} \), we perform \(\mathsf{SwitchKey}\) and move the index j to \(j-1\). Thus, basically, we set the level parameter L according to the multiplicative depth of the circuit. The level L is related with the complexity of \(\mathsf{FHE}.\mathsf{Add} \) or \(\mathsf{FHE}.\mathsf{Add} \). Brakerski et al. [3] showed the order of complexity is \(O(\lambda L^3)\).

2.3 HElib

HElib [16] is a software library that implements the BGV scheme in C++. HElib is based on the number theory library NTL [24]. In addition to the basic scheme, HElib also supports the SIMD feature proposed by Smart and Vercauteren [26]. The SIMD feature enables packing multiple plaintexts into a single element of \(R_p\) with the Chinese Remainder Theorem; it also enables parallel component-wise evaluation of the plaintexts in the SIMD “slots”. It produces a much better amortised performance, due to parallelisation.

HElib has an interface for the “constant” evaluation, where addition or multiplication by a plaintext is performed for ciphertext. Note that Table 1 shows basic interfaces for homomorphic evaluation in the HElib. These constant evaluations are efficient when the addend or multiplier are not encrypted values. In particular, constant multiplication is quite efficient compared to the homomorphic multiplication; the constant multiplication does not increase the dimension of the ciphertext, and we do not need to perform \(\mathsf{SwitchKey}\) after the constant multiplication.

Table 1. Basic interfaces for homomorphic evaluation in HElib.
figure a

2.4 Polynomial Interpolation and Integer-Wise Secure Comparison

The first integer-wise homomorphic comparison algorithm was proposed in [22]. We refer to the algorithm as Algorithm 1, which is based on the polynomial interpolation technique.

Polynomial interpolation is a process of constructing a polynomial f(x) of degree at most n which satisfies \(y_i =f(x_i), i \in \{0,1,\dots ,n\}\), where \(\{x_i, y_i\}\) is given for \(n+1\) data points such that \(x_i \ne x_j\) when \(i\ne j\). We can calculate the polynomial f(x) by

$$\begin{aligned} f(x) = \sum _{i=0}^n \left( \prod _{0\le j\le n, j\ne i} \frac{x-x_j}{x_i-x_j}\right) y_i . \end{aligned}$$
(2)

Note that in Algorithm 1, the polynomial intepolation technique is used to construct the Heaviside step function (i.e, comparison with 0). Our sub-algorithms \(\mathsf{ConstDiv} \) and \(\mathsf{ConstEq} \) are also constructed based on the polynomial interpolation, as discussed in the next section.

3 Our Algorithm for Integer-Wise Homomorphic Division

In this section we present our integer-wise secure division algorithm. In the algorithm, the polynomial interpolation technique is used as a precomputation, similar to the integer-wise comparison algorithm from [22] (Algorithm 1).

In the following, we present in Sect. 3.1 the overview of the algorithms employed in our secure homomorphic division. We describe the algorithms in detail in Sect. 3.2. Finally, we analyse their complexity and provide empirical results in Sect. 3.3.

3.1 Overview

Our integer-wise homomorphic division algorithm \(\mathsf{Div}(C_a,C_d)\) is given in Algorithm 2, and is constructed based on the following subroutines:

  • (Algorithm 3) \(\mathsf{Pows} (C_a)\): Computes powers of a ciphertext \(C_a\).

  • (Algorithm 4) \(\mathsf{ConstDiv} (C_a^{\mathsf{pow}},y)\): Integer-wise division by public divisor y.

  • (Algorithm 5) \(\mathsf{ConstEq} (C_d^{\mathsf{pow}},y)\): Integer-wise equality check with a public input y.

\(\mathsf{ConstDiv} (C_a^{\mathsf{pow}},y)\) homomorphically computes the ciphertext of a quotient \(\lfloor a/y \rfloor \) denoted as \(C_{\lfloor a/y \rfloor }\), from the ciphertext of \(a\in \mathbb {Z}_p\) denoted as \(C_a\), and public divisor \(y\in \mathbb {Z}_p\). \(\mathsf{ConstEq} (C_d^{\mathsf{pow}},y)\) homomorphically computes the ciphertext of the Boolean value \((y=d)\) denoted as \(C_{(y=d)}\), where

$$ C_{(y=d)} := {\left\{ \begin{array}{ll} C_1 &{} \text {if } y=d;\\ C_0 &{} \text {otherwise}. \end{array}\right. } $$

Note that given \(C_a, C_d\) for unknown \(a,d \in \mathbb {Z}_p\), then for an arbitrary public value \(y\in \mathbb {Z}_p\), we have

$$ C_{\lfloor a/y \rfloor } * C_{(y=d)} = {\left\{ \begin{array}{ll} C_{\lfloor a/d \rfloor } &{} \text {if } y=d;\\ C_0 &{} \text {otherwise}. \end{array}\right. } $$

Our main algorithm for homomorphic division of a by d is then based on a simple idea: calculate \(C_{\lfloor a/y \rfloor } * C_{(y=d)}\) for all public values y and sum them:

$$\begin{aligned} C_{\mathsf{sum}}&:= \sum _{y \in \mathbb {Z}_p} C_{\lfloor a/y \rfloor } * C_{(y=d)} = C_{\lfloor a/d \rfloor }. \end{aligned}$$
figure b
figure c
figure d
figure e

3.2 Algorithms

Main Algorithm. Algorithm 2 shows the integer-wise secure division algorithm \(\mathsf{Div}(C_a,C_d)\). The algorithm takes two ciphertexts \(C_a\) and \(C_d\), which are ciphertexts of a and d, respectively, then homomorphically calculates a ciphertext \(C_{\lfloor a/d \rfloor }\), the decryption of which gives \(\lfloor a/d \rfloor \).

The algorithm first calls \(\mathsf{Pows} \) for both inputs \(C_a\) and \(C_d\), to obtain the list of powers \(\varvec{C_a}^{\mathsf{pow}}\) and \(\varvec{C_d}^{\mathsf{pow}}\). This part performs a high number of homomorphic multiplications, but we store these values and can reuse them. Next, in the for loop, for all \(i\in \{0,1,2,\dots ,p-1\}\), we exhaustively calculate \(C_{\lfloor a/{i} \rfloor }\) and \(C_{(d=i)}\) with \(\mathsf{ConstDiv} \) and \(\mathsf{ConstEq} \), then perform the homomorphic multiplication of \(C_{\lfloor a/{i} \rfloor } *C_{(i= d)} := \mathsf{FHE}.\mathsf{Mult} (C_{\lfloor a/i\rfloor }, C_{(i=d)})\). Recall that \(C_{\lfloor a/i\rfloor } *C_{(i=d)}\) equals to \(C_{\lfloor a/d \rfloor }\) if \(y=d\), and \(C_0\) otherwise. Thus, at the end of the algorithm we obtain \(C_{\lfloor a/d \rfloor }=C_{\mathsf{sum}}\).

Pows\(\varvec{(C_a)}\). Algorithm 3 shows the sub-algorithm \(\mathsf{Pows} (C_a)\). The algorithm takes a ciphertext \(C_a\) as an input and homomorphically calculates the powers of \(C_a\), returning the list of powers \(\varvec{C_a}^{\mathsf{pow}}:=(C_{a},C_{a}^2,C_{a}^3,\dots ,C_{a}^{p-1})\). This sub-algorithm is the most complex part of the main division algorithm \(\mathsf{Div}\). In \(\mathsf{Div}\), this algorithm is called only once per ciphertext. Note that the multiplicative depth of \(\mathsf{Pows} (C_a)\) is \(\lceil \log {(p-1)} \rceil \). For example, when \(p=17\), since \(C_a^{2}=\mathsf{FHE}.\mathsf{Mult} (C_a,C_a)\), \(C_a^{4}=\mathsf{FHE}.\mathsf{Mult} (C_a^{2},C_a^{2})\), \(C_a^{8}=\mathsf{FHE}.\mathsf{Mult} (C_a^{4},C_a^{4})\), and \(C_a^{16}=\mathsf{FHE}.\mathsf{Mult} (C_a^{8},C_a^{8})\), multiplicative depth is \(\log (16)=4\). See Sect. 3.3 for a more detailed complexity analysis.

ConstDiv\(\varvec{(C}_{\varvec{a}}^{\varvec{\mathsf{pow}}}\varvec{,d}\)). Algorithm 4 shows the sub-algorithm \(\mathsf{ConstDiv} (C_a^{\mathsf{pow}},d)\). The algorithm takes a list of powers of ciphertext \(\varvec{C_a}^{\mathsf{pow}}:=(C_{a},C_{a}^2,C_{a}^3,\dots ,C_{a}^{p-1})\) and a plaintext divisor d as input, then homomorphically calculates a ciphertext \(C_{\lfloor a/d \rfloor }\), the decryption of which gives \(\lfloor a/d \rfloor \). Note that this algorithm does not perform homomorphic multiplication, it only requires multiplication by constant \(\mathsf{multConst} \), which can be performed efficiently without increasing the size of the ciphertexts and \(\mathsf{SwitchKey}\). Moreover we note that line 1 of Algorithm 4 is performed before the algorithm start, i.e. we precompute coefficient vectors \(\{\varvec{a}_{f_d}\}_{d\in \mathbb {Z}_p}\), which appear in (3), of the interpolation polynomial.

ConstEq\({\varvec{(C}_{\varvec{a}}^{\varvec{\mathsf{pow}}}\varvec{,y}}\)). Algorithm 5 shows the sub-algorithm \(\mathsf{ConstEq} (C_a^{\mathsf{pow}},y)\). The algorithm takes a list of powers of ciphertext \(\varvec{C_a}^{\mathsf{pow}}:=(C_{a},C_{a}^2,C_{a}^3,\dots ,C_{a}^{p-1})\) and a plaintext input y as inputs, then homomorphically calculates a ciphertext \(C_{( a = y) }\), the decryption of which gives 1 when \(a=y\), or 0 when \(a\ne y\). This algorithm is similar to \(\mathsf{ConstDiv} \), except that the values of the precomputed coefficient vectors \(\varvec{a}_{f_y}\) are different. Thus, the complexity of the algorithm is almost the same as the \(\mathsf{ConstDiv} \), and there is no homomorphic multiplication.

3.3 Complexity Analysis and Experiments

Complexity. Although Algorithm 2 might seem exhaustive and inefficient due to its for loop, this homomorphic computation can be performed efficiently. This is mainly because:

  • ConstDiv and ConstEq do not include \(\mathsf{FHE}.\mathsf{Mult} \), but include \(\mathsf{FHE}.\mathsf{multConst} \). Thus, \(\mathsf{ConstDiv} \) and \(\mathsf{ConstEq} \) do not increase the multiplicative depth.

  • The most complex part Pows is executed only once for each input ciphertext \(C_a\) and \(C_d\) before the for loop.

In the following, we analyse the multiplicative depth and the total complexity of our algorithm \(\mathsf{Div}\). Table 2 shows a summary. In our analysis we denote by l the bit length of the input integers.

Table 2. The multiplicative depth and the number of calls of \(\mathsf{Mult} \), \(\mathsf{Add} \) and \(\mathsf{multConst} \) in our algorithms for l-bit size input.

Multiplicative Depth. The multiplicative depth of \(\mathsf{Pows} \) is \(O(\log p)=O(l)\), as shown in Sect. 3.2. The multiplicative depth of \(\mathsf{Div}\) is also O(l), because we perform only one \(\mathsf{FHE}.\mathsf{Mult} \) after \(\mathsf{Pows} \) in one loop in the \(\mathsf{Div}\) algorithm, and \(\mathsf{ConstDiv} \) and \(\mathsf{ConstEq} \) do not include \(\mathsf{FHE}.\mathsf{Mult} \). Chen et al. showed that the multiplicative depth of their bit-wise division algorithm [9] is \(O(l^2)\). The other bit-wise division algorithms [8, 28] are the same as that of [9], the idea of which is based on the non-restoring division, since their improvements are mainly for bit-wise addition and multiplication. Therefore, our algorithm provides quadratic improvement in regard to the multiplicative depth of homomorphic division.

Total Complexity. It is not trivial to adequately analyse the total complexity of the FHE circuit, because the cost of the homomorphic calculation depends on the level parameter L: the order of the cost of the homomorphic calculation is \(O(\lambda L^3)\), as we mentioned in Sect. 2.2. Moreover, as mentioned in \(\mathsf{FHE}.\mathsf{Setup}\), the level L also defines the parameter m. The parameter m defines the cyclotomic polynomial \(\varPhi _m(x)\), which in turn defines the ciphertext space. HElib has a bound on the value L, and HElib halts if we set L too high because of the bound on the size of the cyclotomic polynomial, as noted in [9, 28]. Probably based on this fact, the existing works [8, 9, 28] do not show the results on higher \(({>}4)\) bits input integers (see Table 3).

Although \(\mathsf{ConstDiv} \) and \(\mathsf{ConstEq} \) do not include homomorphic multiplication and do not increase the multiplicative depth, we perform them exhaustively in the for loop (from \(i=0\) to \(p-1\)), and thus we cannot ignore their cost. However, since this for loop is parallelisable, this issue could be decreased by parallelisation. In contrast, existing secure division algorithms are not suitable for parallelisation because of their full-adder circuit (e.g. Ripple Carry adder), as discussed in [8].

We also note that the memory complexity of our algorithm is relatively high. In the precomputation of polynomial interpolation, we generate the coefficient vectors and store them as a matrix, the space for which is \(\mathbb {Z}_p^{p\times p}\).

Experiments. We implemented our secure division algorithm on HElib [16], and compared timings with existing secure division algorithms based on FHE schemes. We can compare the results only for 4-bit size input, since all the existing works report only for 4-bit integer division. We also implement for higher bit values \(l=5,\dots ,8\), and observe that the results follow our complexity analysis.

Parameters. We set the security parameter \(\lambda = 80\), following the existing works of the secure division algorithm [8, 9, 28]. Let l be a the bit size of the input integer. Since our algorithm is integer-wise and stores an input integer in \(\mathbb {Z}\) into \(\mathbb {Z}_p\), we define the size p of the plaintext space \(R_p\) as \(p= \mathrm {nextprime}(2^l)\). We set the Hamming weight of the secret vector \(w=64\). For the level parameter L, which is related to the multiplicative depth of the circuit, we search the minimum level by trial and error. As L is the lower level, we can perform the circuit faster. However, setting L too small leads to incorrectness of the outputs. For the rest of the parameter including “nslots”, which means the number of the SIMD slots, we use the default values automatically calculated by HElib. For further details, we refer the reader to [16].

Table 3. Performance comparison.

Results. Table 3 shows our timing results, in addition to results given in existing work for bit-wise integer division. All timings were generated on a PC with a 3.4 GHz Intel Core i5 and 16 GB RAM. To the best of our knowledge, the work by Chen et al. [8] provides the fastest results for 4-bit size input integers; thus our algorithm is the fastest secure division algorithm. While existing works report only for \(l = 4\), we implemented our algorithm also for the higher bit sizes \(l=5,\dots ,8\). We can observe that our algorithm requires only \(L=O(l)\), following our analysis given in Sect. 3.3. Moreover, we can observe that required L of our algorithm is lower than that of the bit-wise algorithm for \(l=4\). Based on this fact, and that the bit-wise algorithm requires \(L=O(l^2)\), we can expect that L of our algorithm is globally less than that of the bit-wise algorithm.

We also note that nslots of our algorithm, which are automatically calculated by HElib depending on the other parameters, is lower than in bit-wise algorithms. This means that the amortised cost of our algorithm might be larger than existing algorithms.

4 Integer-Wise Homomorphic Evaluation of Arbitrary \(2\)-variable Function

We show that our secure division algorithm can be generalised to integer-wise secure computation of any 2-variable function with the same computation cost.

4.1 Algorithms

Our integer-wise homomorphic evaluation algorithm of any (predefined) 2-variable function \(\mathsf{Func}(C_a,C_d)\) given in Algorithm 7 is constructed based on \(\mathsf{Div}\), by replacing ConstDiv with \(\mathsf{ConstFunc} (\varvec{C_a}^{\mathsf{pow}}, y,g(\cdot ,\cdot ))\) (Algorithm 6), which performs 1-variable function \(g_y(x):=g(x,y)\) over a ciphertext \(C_a\).

figure f

ConstFunc. Algorithm 6 shows the \(\mathsf{ConstFunc} \) algorithm. The algorithm takes a list of powers of ciphertext \(\varvec{C_a}^{\mathsf{pow}}:=(C_{a},C_{a}^2,C_{a}^3,\dots ,C_{a}^{p-1})\), a plaintext y and a 2-variable function \(g(\cdot ,\cdot )\) (i.e., coefficient vectors of its interpolation polynomial), and then homomorphically calculates a ciphertext \(C_{g(a,y)}\), the decryption of which gives g(ay). Recall that, in the \(\mathsf{ConstDiv} (C_a^{\mathsf{pow}},d)\), we used polynomial interpolation to construct a function \(f_d(x)=\lfloor \frac{x}{d} \rfloor \) for all \(d \in \mathbb {Z}_p\), giving data points \(\{f_d(0),f_d(1),\dots ,f_d(p-1)\}\). We can simply generalise \(\mathsf{ConstDiv} \) as a general function: in \(\mathsf{ConstFunc} \), we use polynomial interpolation to construct a required function \(g_y(x)\) defined by given data points \(\{g_y(0),g_y(1),\dots ,g_y(p-1)\}\), for all \(y \in \mathbb {Z}_p\). Only the data points (or, coefficient vectors) are different between \(\mathsf{ConstDiv} \) and \(\mathsf{ConstFunc} \). Thus, the order of multiplicative depth of \(\mathsf{ConstFunc} \) is exactly the same as \(\mathsf{ConstDiv} \). Note that we precompute the coefficient vectors \(\varvec{a}_{f_y}\) for all \(y \in \mathbb {Z}_p\) using the polynomial interpolation, as with \(\mathsf{ConstDiv} \).

figure g

Func. Algorithm 7 shows our algorithm for integer-wise homomorphic evaluation of the arbitrary 2-variable function, \(\mathsf{Func}\). The algorithm takes two ciphertexts \(C_a\) and \(C_b\), which are ciphertexts of a and b, respectively, and a 2-variable function \(g(\cdot ,\cdot )\) (i.e., coefficient vectors of its interpolation polynomial) as inputs. It then homomorphically calculates a ciphertext \(C_{g(a,b)}\), which decrypts to g(ab). This algorithm is almost the same as \(\mathsf{Div}\) (Algorithm 2), except that \(\mathsf{ConstDiv} \) is replaced by \(\mathsf{ConstFunc} \). Since the order of multiplicative depth of \(\mathsf{ConstFunc} \) is exactly the same as \(\mathsf{ConstDiv} \), that of \(\mathsf{Func}\) is exactly the same as \(\mathsf{Div}\).

5 Conclusion

We propose a first secure integer-wise homomorphic division algorithm on fully homomorphic encryption schemes. We implemented the algorithm on HElib, and show that our algorithm is over twice as fast as the fastest existing algorithm given in [8]. We also showed that the multiplicative depth of our algorithm is O(l) for l-bit size integer, while that of existing division algorithms is \(O(l^2)\).

Furthermore, we generalise our secure division algorithm and propose an algorithm for secure calculation of general 2-variable functions. We showed that the complexity of the algorithm is the same as our division algorithm. This means that the homomorphic calculation of any 2-variable functions taking integer inputs can be performed with multiplicative depth O(l).