隐私计算关键技术:隐私集合求交(PSI)的性能扩展

隐私计算关键技术:隐私集合求交(PSI)的性能扩展

更新:本文介绍的PSI方法的Python版完整代码已在Github开源:

作者:Delta - 开箱即用的区块链隐私计算框架(deltampc.com

在上一篇文章中,我们介绍了如何使用不经意传输(OT)来构建不经意伪随机函数(OPRF),并使用不经意伪随机函数来构造隐私集合求交(PSI)。

但是,上文介绍的方法,速度很慢,因为在构造不经意伪随机函数时,需要使用l次不经意传输(l是输入数据的长度),进而导致隐私集合求交需要使用O(nl)次不经意传输(n为集合大小)。我们知道,由于不经意传输使用公私钥加密技术,所以不经意传输的速度是很慢的。所以,我们要对上文介绍的方法进行改进,而改进的主要目标,就是减少使用的不经意传输数量。

要做到这一点,我们就需要引入一个新的方法,不经意传输扩展。能够少量(常数次)“慢速”的不经意传输,来实现大量“快速”的不经意传输。下面,我就来介绍不经意传输扩展。

不经意传输扩展(Oblivious Transfer Extension, OTE)

这里介绍的不经意传输扩展方法,来自文章[2]

不经意传输扩展的目标,是使用少量“慢速”的基础不经意传输,配合对称加密,来实现大量“快速”的不经意传输。 形式化的来说,我们以符号OT_l^m来表示进行m次不经意传输,每次传输l个比特,则不经意传输扩展的定义为:使用OT_k^k来实现OT_l^m,其中k是一个比较小的安全参数,且m \gg k

下面,我们来介绍如何使用OT_k^k来实现OT_l^m。我们首先使用OT^k_m来实现OT_l^m,因为使用OT^k_m比使用OT_k^k更加简单直观,同时使用OT_k^k可以很简单地实现OT_k^m。之后,我们再简单地介绍如何使用OT_k^k实现OT_k^m

我们使用S来表示OT^k_m中的发送者,R表示OT^k_m中的接收者。Sm对输入(x_{j,0},x_{j,1}),1 \leq j \leq mRm个选择比特r = (r_1, ..., r_m)SR之间有一个统一的随机函数H: [m] \times \{0,1\}^k \rightarrow \{0,1\}^l,即将长度为k的比特串随机映射到长度为l的比特串。之后的步骤如下:

  1. R先初始化一个随机的比特矩阵T,矩阵T的大小为m \times k,即mk列,矩阵的每个元素都是0或1。S随机初始化k个选择比特s=(s_1,...,s_k)
  2. R作为发送者,S作为接收者,执行OT_m^k。对于第i次长度为m的不经意传输,R的输入为(t^i,t^i \bigoplus r),其中t^i表示矩阵T的第i列,长度为mS的输入为s_i。当s_i=0时,S得到t^i,当s_i=1时,S得到t^i \bigoplus r。将S收到的所有列组合成一个m \times k的矩阵,称为Q
  3. 现在,R作为接收者,S作为发送者。S要执行m次传输,对于1 \leq j \leq mS发送一对数据(y_{j,0},y_{j,1}),其中y_{j,0} = x_{j,0} \bigoplus H(j,q_j)y_{j,1} = x_{j,1} \bigoplus H(j,q_j \bigoplus s)q_j为矩阵Q的第j
  4. 对于1 \leq j \leq mR输出z_j = y_{j,r_j} \bigoplus H(j,t_j),其中t_j表示矩阵T的第j

现在,我们来证明方法的正确性,即z_j = x_{j, r_j}

从步骤2中我们可以得知,s_i = 0时,q^i = t^is_i = 1时,q^i = t^i \bigoplus r。我们可以将它写成如下形式:q^i = t^i \bigoplus (s_i · r)\\ 其中,符号·表示按位与运算。那么,对于矩阵Q中的第i列,第j行的元素q^i_j,有如下等式:

q^i_j = t^i_j \bigoplus (s_i · r_j) \\

我们把s_i当作选择比特,当s_i = 0时,q^i_j = t^i_j;当s_i = 1时,q^i_j = t^i_j \bigoplus r_j。我们换一个角度,把r_j当作选择比特,当r_j = 0时,q^i_j = t^i_j;当r_j=1时,q^i_j = t^i_j \bigoplus s_i。这一结果,对于所有1 \leq i \leq k都成立,那么我们可以得到:当r_j = 0时,q_j = t_j;当r_j = 1时,q_j = t_j \bigoplus s,它可以写成如下形式

q_j = t_j \bigoplus (r_j · s) \\

从上式,我们可以得到

t_j = q_j \bigoplus (r_j · s) \\

这时我们来看z_j。由于y_{j,0} = x_{j,0} \bigoplus H(j,q_j)y_{j,1} = x_{j,1} \bigoplus H(j,q_j \bigoplus s),那么y_{j,r_j} = x_{j,r_j} \bigoplus H(j,q \bigoplus (r_j · s)),将y_{j,r_j}t_j带入到公式z_j = y_{j,r_j} \bigoplus H(j,t_j)中,可得 z_j = y_{j,r_j} \bigoplus H(j,t_j) =x_{j,r_j} \bigoplus H(j,q \bigoplus (r_j · s)) \bigoplus H(j,q \bigoplus (r_j · s)) = x_{j,r_j},证毕。

从不经意传输的角度看,我们可以把r_j当作接收者R的选择比特,(q_j, q_j \bigoplus s)是发送者S输入的一对数据,当r_j = 0时,t_j = q_jr_j = 1时,t_j = q_j \bigoplus s,这就是了一个不经意传输。由于1 \leq j \leq m,因此我们总共构造了m个不经意传输。

这种不经意传输所传输的数据(q_j, q_j \bigoplus s)是随机的,如果想要传输特定的数据,也就是(x_{j,0},x_{j,1}),我们可以把(q_j, q_j \bigoplus s)当作加密函数的key,用来加密(x_{j,0},x_{j,1}),得到(y_{j,0},y_{j,1}),然后接收者R就可以使用t_j,解密出r_j对应的x_{j,r_j}。这里的加密与解密操作是很简单的,使用对称加密即可,这相比公私钥加密要快的多。

由此,我们通过OT^k_m,外加2m次的对称加密,就实现了OT^m_lOT^k_m的开销是k次OT,加上2m次的对称加密,相比OT^m_lm次OT,还是要小很多的。尤其是当m \gg k时,这种差距就更加明显。

之前还说到,我们可以进一步使用OT^k_k来实现OT^k_m,缩减开销。从OT^k_kOT^k_m是很简单的,步骤如下:

  1. 发送者S随机初始化k对长度为k的密钥(s_{i,0}, s_{i,1})
  2. 接收者Rk个选择比特r = (r_1,...,r_k),通过OT^k_k,得到k个密钥s_{i,r_i}
  3. 对于1 \leq i \leq k,发送者S发送(y_{i,0},y_{i,1}),其中y_{i,b} = x_{i,b} \bigoplus G(s_{i,b})G:\{0,1\}^k \rightarrow \{0,1\}^m为一个伪随机函数
  4. 对于1 \leq i \leq k,接收者R得到z_i = y_{i,r_i} \bigoplus G(s_{i,r_i})

我们可以看到,主要的思路就是通过OT^k_k传输长度为k的密钥,作为对称加密的密钥,然后加密长度为m的数据,再进行传输。这样做其实并没有减少传输的数据量,因为实际上都要传输长度为m的数据给接收方。

更进一步

在有了不经意传输扩展之后,我们可以用它来改进之前的隐私集合求交算法。最简单的想法,就是将之前隐私集合求交算法中所有的不经意传输,都使用不经意传输扩展来替换。这样的确能够提升算法的效率,因为我们将大量“慢速”的不经意传输,替换为了少量的“慢速”不经意传输加大量的对称加密。但是,算法的传输量并没有减少,仍然需要进行O(nl)次传输,每次传输2个长度为k的比特串。单纯使用不经意传输扩展来替换不经意传输,只是减少了每次传输的计算开销,并没有减少传输上的开销。那么,能不能继续减少传输上的开销呢?答案是可以的。我们需要在不经意传输扩展的基础上更进一步,继续扩展。

观察之前的不经意传输与不经意传输扩展,它们都是1-2不经意传输,也就是二选一。基于1-2不经意传输的范式,对于一个长为l的输入数据,我们需要为它的每一个比特进行一次不经意传输,所以传输量是O(l)。不经意传输除了1-2不经意传输,还有1-n不经意传输,也就是n选一。如果我们使用1-n不经意传输,那么,对于一个长为l的输入数据,传输量变为了O(l/n)。如果我们用1-n不经意传输来替换1-2不经意传输,很明显,隐私集合求交算法的传输量会缩减,但是渐进复杂度依然没变,还是O(nl),也就是说,传输量依然与输入数据的长度l有关。但是,如果我们能实现1-\infty的不经意传输呢?那么,隐私集合求交总体的传输量就会缩减到O(n),因为我们只需要一次1-\infty不经意传输,就能实现不经意伪随机函数(OPRF),也就是隐私比较了。

那么,如何构建1-\infty不经意传输呢?我们要在刚刚介绍的不经意传输扩展的基础上,实现大量的1-\infty不经意传输。

由不经意传输扩展到1-\infty不经意传输

现在我们回头看不经意传输扩展,接收方R会先随机初始化一个m \times k的比特矩阵T,矩阵T的每一列t^i都会和选择比特向量r进行异或,通过1-2不经意传输发送给发送方S。我们将t^i \bigoplus r得到的每一列,组成一个矩阵U, 那么u^i = t^i \bigoplus r\\

我们可以发现,T的第jt_j,与U的第ju_j进行异或t_j \bigoplus u_j,得到的都是全零或全一,是零还是一取决于选择r_j。现在我们假设一个编码函数C:\{0,1\} \rightarrow \{0,1\}^kC(b) = b^k,也就是将输入的比特b重复k次,即重复编码。那么,我们可以得到t_j \bigoplus u_j = C(r_j)。现在观察发送者S通过不经意传输得到的矩阵Q,我们知道q_j = t_j \bigoplus (r_j · s),那么,结合编码函数C,我们可以得到:

q_j = t_j \bigoplus (C(r_j) · s) \\

思考一下,如果我们改变编码函数C,上面的等式是否会成立?很显然,只要q^i = t^iq^i = u^i成立,上面的等式就是成立的。那么,我们就可以对编码函数C进行改动。

之前的编码函数C:\{0,1\} \rightarrow \{0,1\}^k是重复编码,输入是一个比特,我们可以将它改为随机编码,且能接受任意长比特的输入,即:

C:\{0,1\}^* \rightarrow \{0,1\}^k \\

那么,现在接收者R的选择位r_j就不需要限制在一个比特了,可以为一个任意长度的数据,即r_j:\{0,1\}^*。 我们知道,接收者R现在有比特矩阵T,发送者S有矩阵Q,每一行t_j = q_j \bigoplus (C(r_j) · s)。对于发送者S来说,它可以对任意长度的输入r'计算q_j \bigoplus (C(r') · s),只有当r_j = r'时,t_j = q_j \bigoplus (C(r') · s)才会成立。从不经意传输的角度来看,这就是一种1-\infty的不经意传输,因为接收者R只能获得t_j一个输出,发送者S却能对任意长的r'计算q_j \bigoplus (C(r') · s),也就是说,发送者S能产生任意多个输出,但是接收者R只能知道其中的一个。

实现不经意伪随机函数(OPRF)

那么,我们就可以使用1-\infty不经意传输,来实现隐私比较。让r_jr'分别为RS需要比较的数据,发送者S输出H(j,q_j \bigoplus (C(r') · s)),接收者R输出H(j,t_j)H是一种哈希函数。只需要比较RS的输出,就可以实现隐私比较。

从上一篇文章,我们可以得知,隐私比较可以看作不经意伪随机函数(OPRF)。那么,我们就可以通过对不经意传输扩展进行改造,构造出大量不经意伪随机函数。形式化的描述如下:

接收者Rm个选择字符串r=(r_1,...,r_m)r_i \in \{0,1\}^*, 接收者R与发送者S有一个共同的随机编码函数C:\{0,1\}^* \rightarrow \{0,1\}^kC的编码长度为k, 有一个共同的哈希函数H:[m]\times\{0,1\}^k \rightarrow \{0,1\}^v

  1. R先初始化一个m \times k随机的比特矩阵TS随机初始化k个选择比特s=(s_1,...,s_k)
  2. R构建矩阵Uu_j = t_j \bigoplus C(r_j),其中u_jt_j分别表示UT的第j
  3. R作为发送者,S作为接收者,执行OT_m^k。对于第i次长度为m的不经意传输,R的输入为(t^i,u^i)t^iu^i分别表示矩阵TU的第i列;S的输入为s_i。当s_i=0时,S得到t^i,当s_i=1时,S得到u^i。将S收到的所有列组合成一个m \times k的矩阵,称为Q
  4. 现在,R作为接收者,S作为发送者,可以执行m次OPRF。对于1 \leq j \leq mR输出H(j,t_j)S输出H(j,q_j \bigoplus (C(r') · s))r' \in \{0,1\}^*r'S选择的任意值。

由此,我们就通过改造不经意传输扩展,实现了大量的不经意伪随机函数。我们只需要进行固定次数(k次)的1-2不经意传输,就能实现m次(m \gg k)不经意伪随机函数。每次不经意伪随机函数,只需要使用一个哈希函数,进行一次传输即可完成,与输入的长度l无关,开销很小。

安全性

我们现在来考虑上述协议的安全性。

假设接收者R是诚实且好奇的,也就是说,R会正确地执行协议,但是同时它会尽可能地尝试从协议的输出中窥探发送者S的信息。假设S发给R的信息是H(q_j \bigoplus (C(r') · s))r' \neq r_jR想要去暴力碰撞r',我们可以发现:

q_j \bigoplus (C(r') · s) = t_j \bigoplus (C(r_j) · s) \bigoplus (C(r') · s) = t_j \bigoplus ((C(r') \bigoplus C(r_j)) · s) \\

其中,只有sR来说是未知的。如果要保证安全,我们需要让C(r') \bigoplus C(r_j)的汉明重量大于\kappa,这样的情况下,R需要至少猜测出s中的\kappa位,才能完成碰撞攻击。\kappa是一个安全参数,\kappa的值越大,攻击者就越难完成攻击。一般来说,\kappa的值需要至少大于等于128。

我们知道随机编码C的输出长度是k,要使C(r') \bigoplus C(r_j)的汉明重量大于\kappa,就需要k > \kappa。根据文章[1]的结论,只要3\kappa < k < 4\kappa,就能保证C(r') \bigoplus C(r_j)的汉明重量小于\kappa的概率是可以忽略的。具体的证明这里不做介绍,感兴趣的读者,可以自行查看论文。

在隐私集合求交中的应用

回到隐私集合求交上,我们使用这种改进过的不经意伪随机函数,可以大大提升算法的效率。

上一篇文章中,已经介绍了如何使用不经意伪随机函数来实现隐私隐私集合求交。隐私集合求交中,需要使用1.2n+s,也就是O(n)次的不经意伪随机函数。现在,改进过的不经意伪随机函数的开销与输入长度无关,是一个均摊的常数。使用改进过的不经意伪随机函数后,隐私集合求交的渐进复杂度也就变为O(n)了,只与需要比较的集合大小相关,与集合中元素的长度无关。

从整体上看,隐私集合求交算法只需要进行k1-2不经意传输,外加O(n)次的对称加密即可完成,其中k是个常数。我们可以将这k次不经意传输看作算法的初始化阶段,后续阶段称为在线阶段,初始化阶段的执行时间基本是固定的,在线阶段的时间会随着集合大小的增大而增大。 根据文章[1]中的试验结果,当集合大小为2^{20}时,在内网环境下(延时0.2ms),使用改进过的不经意伪随机函数的隐私集合求交,在线阶段只需要不到4s时间,离线阶段只需要600ms。与朴素的哈希方法相比,朴素哈希方法的执行时间在700ms左右。可以看出,这种方法的速度是很快的。

结论

综上所述,我们使用固定次数的1-2不经意传输,外加对称加密,就可以实现隐私求交算法了。这样实现的隐私求交算法,速度是很快的,即使和朴素的哈希方法相比,也不会很慢。算法的传输量是O(n)n是发送者的集合大小,因此更加适合参与双方进行比较的集合大小相差不大的情况。

本文只介绍了算法的大致思路,如果需要详细的了解,推荐阅读原文章[1]。同时,原文章还有对应的开源代码,可以作为参考:

github.com/osu-crypto/B

另外,本文介绍的PSI方法是一个两方PSI方法,无法用于多方之间计算PSI。本方法的作者在后续的文章中,用同样的思路加以扩展,支持了多方PSI。详情可阅读这篇介绍的文章:

参考文献:

[1] Kolesnikov V, Kumaresan R, Rosulek M, et al. Efficient batched oblivious PRF with applications to private set intersection[C]//Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security. 2016: 818-829.

[2] Ishai Y, Kilian J, Nissim K, et al. Extending oblivious transfers efficiently[C]//Annual International Cryptology Conference. Springer, Berlin, Heidelberg, 2003: 145-161.


本文经「原本」原创认证,作者一个洋葱,点击“阅读原文”或访问yuanben.io查询【3GTCHEIO】获取授权

编辑于 2021-11-12 20:26