1 介绍
本文是谷歌团队发在CCS2017上的文章,旨在解决联邦学习中安全聚合的问题。
安全聚合:多方参与者将信息传递给聚合者,聚合者除了知道这个信息的总和不能知道任何一个特定参与者的信息。
在这篇文章中,谷歌将用户手机作为联邦学习的客户端媒介,从而提出了联邦学习下安全聚合需要做到:
-
通信:希望对参数进行安全处理后相比直接发送参数不超过两倍的通信开销
-
掉线:手机作为客户端可能经常掉线,协议需要抵抗掉线
也提出了联邦学习下安全聚合协议的要求:
-
能在高维向量下进行运算
-
通信高效,即使每次实例化都有一组新的用户集合
-
对用户掉线鲁棒
-
在以服务器为中介、未经身份验证的网络模型的约束下提供了最强的安全性
2 预备知识
本文提出的安全聚合协议需要一定的密码学知识,好消息是文章中给出了这些预备知识。
2.1 秘密分享
\(\text{Shamir}\)秘密分享:用户将秘密\(s\)分成\(n\)份,任意\(t\)份可以重建秘密,但任意\(< t\)份的秘密得不到秘密的任何信息。
首先定义一个有限域\(F\),大小\(l>2^k\),\(k\)是安全参数
在有限域中有\(n\)个元素可以来表示\(1,\cdots,n\)(代表\(n\)个参与方)
-
分享(share)算法:\(\text{SS.share}(s,t,U)\rightarrow \lbrace (u,s_u)\rbrace_{u\in U}\),输入是秘密\(s\),集合\(U\)有\(n\)个元素表示\(n\)个参与方的userID,阈值\(t\leq|U|\)。输出是每个参与方得到的秘密分享\(s_u\)。
-
重建算法:\(\text{SS.recon}(\lbrace (u,s_u)\rbrace_{u\in V},t)\rightarrow s\),输入阈值\(t\),以及全局\(U\)的一个子集\(V\)中各个元素的分享\(s_u\),这里要求子集\(V\)大小\(|v|\ge t\)。输出是秘密\(s\)。
2.2 密钥协商
密钥协商由算法元组\((\text{KA.param,KA.gen,KA.agree})\)组成。
-
\(\text{KA.param}\):\(\text{KA.param(k)}\rightarrow pp\),由\(k\)生成一些公共参数\(pp\)
-
\(\text{KA.gen}\):\(\text{KA.gen}(pp)\rightarrow (s_u^{SK},s_u^{PK})\),用公共参数\(pp\)为参与方\(u\)生成私钥-公钥对。
-
\(\text{KA.agree}\):\(\text{KA.agree}(s_u^{SK},s_u^{PK})\rightarrow s_{u,v}\),允许用户\(u\)将其私钥\(s_u^{SK}\)和任何用户\(v\)的公钥\(s_v^{PK}\)组合,获得两者之间私有的共享密钥\(s_{u,v}\)。这里不同用户的私钥和公钥都是用相同的\(pp\)生成的。
2.3 \(\text{Diffie-Hellman}\)密钥协商算法
假设用户\(u,v\)协商一个密钥:
(1)首先\(u,v\)共享一个素数\(p\)以及素数的原根\(g\),\(g<p\)。这两个数的发送可以不加密。
原根: 对于\(i\neq j,1\leq i,j\leq p-1\),有\(g^i \space \text{mod}\space p\neq g^j \space \text{mod}\space p\),则\(g\)为\(p\)的原根。
(2)\(u\)产生一个私有随机数\(A\),满足\(1\leq A \leq p-1\),计算\(X=g^A \space \text{mod}\space p\)并发送给\(v\);同样地,\(v\)产生一个私有随机数\(B\),满足\(1\leq B\leq p-1\),计算\(Y=g^B \space \text{mod}\space p\)并发送给\(v\)。
随后,\(u\)可以通过\(K_u=Y^A\space \text{mod}\space p\)得到密钥,\(v\)可以通过\(K_v=X^B\space \text{mod}\space p\)得到密钥。显然,两者的计算结果都是\(K=g^{A\times B}\space \text{mod}\space p\)
介绍完\(\text{Diffie-Hellman}\),再来看本文具体使用的密钥协商
这里采用的密钥协商与Diffie-Hellman相似:
-
\(\text{KA.param}\):\(\text{KA.param(k)}\rightarrow (G^{'},g,q,H)\),由\(k\)生成公共参数:素数阶\(q\)的群\(G^{'}\)(阶表示群元素个数),原根\(g\)和一个哈希函数\(H\)。
-
\(\text{KA.gen}\):\(\text{KA.gen}(G^{'},g,q,H)\rightarrow (x,g^x)\),从\(Z_q\)采样一个\(x\)当做私钥\(s_u^{SK}\),将\(g^x\)当做其公钥\(s_u^{PK}\)。这里\(Z_q\)表示\(q\)的整数环,即包含了\(0-q-1\)的整数。根据原根的定义,当私钥不同,公钥也不同。
-
\(\text{KA.agree}\):\(\text{KA.agree}(x_u,g^{x_v})\rightarrow s_{u,v}\),其中\(s_{u,v}=H((g^{x_v})^{x_u})\)。即用户\(u\)将其私钥\(x_u\)和用户\(v\)的公钥\(g^{x_v}\)组合,经过哈希得到共享密钥。可以看出,当用户\(v\)获得了\(u\)的公钥,能计算出一样的共享密钥。
2.4 认证加密
由3个算法组成:
-
密钥生成算法:输出私钥
-
加密算法\(\text{AE.enc}\):输入明文和密钥,输出密文
-
解密算法\(\text{AE.dec}\):输入密文和密钥,输出明文或者特殊的错误标志符
2.5 签名机制
本文协议依赖标准UF-CMA安全签名机制。
-
密钥生成算法:\(\text{SIG.gen}(k)\rightarrow (d^{PK},d^{SK})\),输入安全参数,输出私钥\(d^{SK}\)和公钥\(d^{PK}\)
-
签名算法:\(\text{SIG.sign}(d^{SK},m)\rightarrow \sigma\),输入私钥和信息,输出签名
-
验签算法:\(\text{SIG.ver}(d^{PK},m,\sigma)\rightarrow \lbrace0,1\rbrace\),输入公钥,信息和签名,输出签名是否有效的结果
2.6 公钥基础设施
每一方\(u\)可以注册\((u,d_u^{PK})\)作为身份信息,基础设施能根据身份对消息进行签名,使得其他方可以验证但无法冒充签名。这样做使得攻击方无法冒充诚实方。
3 技术直觉
为了保护用户的数据\(x_i\),最开始的方案是使用一次mask操作,即用户\(u\)和\(v\)协商得到一个随机数\(s_{u,v}\),然后用该随机数对真实数据\(x_i\)进行扰动,得到扰动后的结果\(y_i\)
\[y_u=x_u+\sum\limits_{v\in U:u<v}s_{u,v}-\sum\limits_{v\in U:u>v}s_{v,u}(\text{mod} \space R) \]
各客户端会将扰动后的数据\(y_i\)发送给服务器,服务器随后可以进行计算:
\[\begin{aligned} z&=\sum_{u\in U} y_u \\ &=\sum_{u\in U} y_u(x_u+\sum\limits_{v\in U:u<v}s_{u,v}-\sum\limits_{v\in U:u>v}s_{v,u}) \\ &=\sum_{u\in U} x_u (\text{mod} \space R) \\ \end{aligned} \]
我们可以对单次mask举例方便理解。假设有3个客户端,那么依据上述扰动方法,他们交给服务器的数据分别为:
\[y_1=x_1+s_{12}+s_{13} \]
\[y_2=x_2-s_{12}+s_{23} \]
\[y_3=x_3-s_{13}-s_{23} \]
服务器进行求和:\(y_1+y_2+y_3=x_1+x_2+x_3\)
这个方案可以让服务器在不知道各方数据\(x_i\)的情况下得到总和\(\sum x_i\),但有一些问题:
-
通信开销过大
-
扰动值\(s_{uv}\)若通过服务器分发,那么服务器直接得到了扰动值
-
如果有用户掉线,那么扰动值无法在总和中被消去
4 问题解决
4.1 通信开销大
直接发送扰动值\(s_{uv}\)的通信开销较大,因此可以改变为发送\(\text{PRG}\)的种子,让客户端自己使用\(\text{PRG}\)对种子进行扩展来得到扰动值。该方法也能回答为什么需要使用一次mask进行扰动而不是直接采用
安全的方法分发数据\(x_i\),因为\(x_i\)可能是维数很大的数据。
4.2 扰动值保护
为了防止服务器直接获得扰动值,采用密钥协商的方法传递。那么各客户端本地持有密钥协商生成的私钥,仅通过服务器传递公钥,服务器无法用公钥获取扰动值。
4.3 用户掉线
我们假设有3个客户端,此时客户端3掉线,那么服务器求和为:
\[y_1+y_2=x_1+x_2+s_{13}+s_{23} \]
为了消去上式的多余项,想法是让服务器去客户端1处获得\(s_{13}\),去客户端2处获得\(s_{23}\)。然而这时又诞生两个新问题:
-
若服务器还未获得扰动值,客户端1或3又掉线,那么无法获得扰动值。在真实场景中客户端数量众多,可能每次获取扰动值都有新的掉线用户。我们姑且称这种情况为循环掉线
-
若\(y_3\)实际上是延迟到达而非掉线。若在服务器获得扰动值后,\(y_3\)延迟到达,那么服务器可以计算\(y_3+s_{13}+s_{23}\)求出\(x_3\),即得到了真实数据
5 最终方案
5.1 循环掉线
使用上面介绍过的秘密分享方法。当把扰动值\(s_{uv}\)当做秘密分享出去,那么只要最后的在线客户端数量大于等于门限值\(t\),就能把扰动值恢复。
5.2 double-masking
对每个数据\(x_i\),为其再加入一个掩码\(b_i\),然后再加入之前的扰动值,即:
\[\begin{aligned} y_u=x_u&+\text{PRG}(b_u) \\ &+\sum\limits_{v\in U:u<v} \text{PRG}(s_{u,v}) \\ &-\sum\limits_{v\in U:u>v} \text{PRG}(s_{v,u}) \\ \end{aligned} \]
此时的流程变为:
-
用户\(u\)将扰动\(s\)和\(b\)都以秘密分享的形式分发出去
-
在恢复的一轮,对于诚实的用户\(v\):若用户\(u\)掉线,\(v\)会将\(s_{uv}\)的share上传给服务器;若\(u\)在线,\(v\)会将\(b_u\)的share上传给服务器
服务器收集了在线用户的\(b\)的share,可以减去\(\sum \text{PRG}(b_u)\);收集了掉线用户相关的扰动的share,可以安全地按一次mask掉线那样消去扰动。
6 总流程
注:红色表示应对主动攻击者需要采取的措施
翻译与解读:
\(\text{setup}\):
- 所有参与方获得安全参数\(k\),用户总数\(n\)和阈值\(t\),诚实生成公共参数\(pp\leftarrow \text{KA.gen}(k)\)、\(m,R\)用来规定输入采样空间\(Z_R^m\),秘密分享的域\(F\)。所有参与方都有和server交互的私密通道。
- 用户\(u\)从可信第三方处获得签名密钥\(d_u^{SK}\),同时获得对\(v\)进行验签的公钥\(d_v^{PK}\)
\(\text{Round 0}\):
用户\(u\):
- 生成两对公私钥\((c_u^{PK},c_u^{SK})\leftarrow \text{KA.gen}(pp),(s_u^{PK},s_u^{SK})\leftarrow \text{KA.gen}(pp)\),并生成签名\(\sigma_u \leftarrow \text{SIG.sign}(d_u^{SK},c_u^{PK}||s_u^{PK})\)(\(PS\):\(c\)用来做后面加密时的密钥,\(s\)用来做扰动值)
- 将\((c_u^{PK}||s_u^{PK}||\sigma_u)\)发送给server,移至下轮
server:
- 收集至少\(t\)份信息(收集到的集合为\(U_1\))。否则终止
- 对\(U_1\)中所有用户广播集合用户信息\(\lbrace (v,c_v^{PK},s_v^{PK},\sigma_v)\rbrace_{v\in U_1}\)
\(\text{Round 1}\):
用户\(u\):
- 收到信息\(\lbrace (v,c_v^{PK},s_v^{PK},\sigma_v)\rbrace_{v\in U_1}\)。判断\(|U_1|\ge t\),且所有公钥是不同的,并进行验签\(\forall v\in U_1,\text{SIG.ver}(d_v^{PK},c_v^{PK}||s_v^{PK},\sigma_u)=1\)
- 从\(F\)中随机采样一个\(b_u\)
- 生成share \(s_u^{SK}:\lbrace(v,s_{u,v}^{SK})_{v\in u_1}\rbrace\leftarrow \text{SS.share}(s_u^{SK},t,U_1)\)
- 生成share \(b_u:\lbrace(v,b_{u,v})_{v\in u_1}\rbrace\leftarrow \text{SS.share}(b_u,t,U_1)\) (\(PS\):这里生成share,但没有直接分发)
- 对每个\(v\in U_1 \backslash \lbrace u\rbrace\),计算\(e_{u,v}\leftarrow \text{AE.enc}(\text{KA.agree}(c_u^{SK},c_v^{PK}),u||v||s_{u,v}^{SK}||b_{u,v})\)
- 若上述有步骤失败,则终止
- 所有密文\(e_{u,v}\)发给服务器
- 存储本轮生成所有的信息,并移至下轮
server:
- 从至少\(t\)个用户处收集密文(收集到的集合为\(U_2 \subseteq U_1\) )
- 给\(U_2\)中每个用户\(u\)发送密文\(\lbrace e_{u,v}\rbrace_{v\in U_2}\),移至下轮
\(\text{Round 2}\):
用户\(u\):
- 从服务器处收集并存储密文信息\(\lbrace e_{u,v}\rbrace_{v\in U_2}\),并推断出集合\(U_2\)。如果大小小于\(t\),终止
- 对每个\(v\in U_2 \backslash \lbrace u\rbrace\),计算\(s_{u,v}\leftarrow \text{KA.agree}(s_u^{SK},s_v^{PK})\),并使用PRG将这个值扩展为一个随机向量\(p_{u,v}=\Delta_{u,v}\cdot \text{PRG}(s_{u,v})\),其中若\(u>v\)则\(\Delta_{u,v}=1\),若\(u<v\)则\(\Delta_{u,v}=-1\)。且定义\(p_{u,u}=0\)(\(PS\):\(s_u^{SK}\)是\(u\)自己持有的,\(s_v^{PK}\)在\(\text{Round 1}\)收到,密钥协商生成的\(s_{u,v}\)就是扰动值的种子)
- 计算用户自己的私有掩码向量\(p_u=\text{PRG}(b_u)\)。然后计算输入\(y_u\leftarrow x_u+p_u+\sum_{v\in U_2}p_{u,v}\)
- 若上述有步骤失败,则终止。否则将\(y_u\)发送给服务器并移至下轮
server:
- 从至少\(t\)个用户处收集\(y_u\)(收集到的集合为\(U_3 \subseteq U_2\) )。给\(U_3\)中每个用户发送\(U_3\)用户列表
\(\text{Round 3}\):
用户\(u\):
- 从服务器收集用户列表\(U_3 \subseteq U_2\)(包括自身),若\(U_3\)大小小于\(t\),终止
- 将自己的签名\(\sigma_u^{'}\leftarrow \text{SIG.sign}(d_u^{SK},U_3)\)发送给服务器
server:
- 从至少\(t\)个用户处收集\(\sigma_u^{'}\)(收集到的集合为\(U_4\subseteq U_3\))。给\(U_4\)中每个用户发送集合\(\lbrace v, \sigma_v^{'}\rbrace_{v\in U_4}\)
\(\text{Round 4}\):
用户\(u\):
- 从服务器处得到列表\(\lbrace v, \sigma_v^{'}\rbrace_{v\in U_4}\)。验证\(U_4 \subseteq U_3,|U_4|\ge t,\text{SIG.ver}(d^{PK},U_3,\sigma_v^{'})=1\)。如果验证失败则终止
- 对于用户\(v\in U_2 \backslash \lbrace u\rbrace\), 解密密文得到\(v^{'}||u^{'}||s_{v,u}^{SK}||b_{v,u}\leftarrow \text{AE.dec}(\text{KA.agree}(c_u^{SK},c_v^{PK}),e_{v,u})\),并验证\(u=u^{'},v=v^{'}\)(PS:解密后各方才得到share)
- 如果有解密操作失败,终止
- 给服务器发送shares,发送的内容包括:对用户\(v\in U_2 \backslash U_3\)发送\(s_{v,u}^{SK}\),对用户\(v\in U_3\)发送\(b_{v,u}\)(PS:\(U_3\)在Round 2被告知,这里可以看出在Round 2结束时必须明确哪些是掉线用户哪些是在线用户)
server:
- 从至少\(t\)个用户处收集回复(收集到的集合为\(U_5\))
- 对每个用户\(u\in U_2\backslash U_3\),重建\(s_u^{SK}\leftarrow \text{SS.recon}(\lbrace s_{u,v}^{SK}\rbrace_{v\in U_5},t)\),并使用该值和PRG,来计算和\(U_3\)中用户\(v\)组成的扰动\(p_{v,u}\)
- 对每个用户\(u\in U_3\),重建\(b_u \leftarrow \text{SS.recon}(\lbrace b_{u,v}\rbrace_{v\in U_5},t)\),并使用PRG计算\(p_u\)
- 计算输出\(z=\sum_{u\in {U_3}}x_u=\sum_{u\in {U_3}}y_u-\sum_{u\in {U_3}}p_u+\sum_{u\in {U_3},v\in U_2 \backslash U_3}p_{v,u}\)