人工智能会伤害人类吗?怎样控制他们? (3)

以上方案中的最优方案应当是YASHE或FV。YASHE被应用与流行的CryptoNets(加密网络)算法当中,对浮点操作的支持很好。但是这个方法很复杂,为了使本文更加简单有趣,我们选择了稍逊一筹的方案(基于整数向量的高效同态加密,安全性要差一点)。但是,你要注意即使你读本文时出现了新的同态加密算法,但是本文中的整数/浮点数加法和乘法同态加密的实现方案是通用的。我希望通过本文可以提高你对同态加密算法应用的理解以便开发出更多的同态加密算法去优化深度学习。

这个加密算法Yu, Lai, and Paylor的工作里也有一节专门提及,还有相应的代码实现,核心代码位于vhe.cpp当中。下面我们将用Python实现相应的接口并做相应讲解。你也可以选择更高层面的实现方式或者移植到其他语言或场景下,因为这套实现方案是通用的(通用的函数名称,变量名等等)。

第6部分:Python中的同态加密

首先介绍一下同态加密中的术语:

明文: 未加密的数据。这也被称为“信息”(message)。在我们的例子中,这将是代表我们神经网络的数值的集合。

密文: 加密后的数据。我们在密文做的数学操作会改变底层的明文,最初的图示也提到了这一点。

公钥: 伪随机数序列,任何人可以用它加密数据。公钥可以被传播,因为拿到的人只能用它来加密数据(理论上)。

私钥/密钥: 伪随机数序列,允许您解密通过公钥加密的数据。私钥不应该分享给他人,否则你加密的数据就会被他人解码。

以上是使用中可以移动的组件。在不同的同态加密算法中,会有一些标准变量,本文中有以下标准变量:

S: 代表密钥/私钥的矩阵,你需要用它来解密信息。

M: 公钥。你会用它来加密东西,并执行数学运算。虽然一些算法中所有的数学运算都不需要公钥,但是公钥的使用还是相当广泛。

c: 加密数据矢量,“密文”。

x: 对应于你的信息,或者说你的“明文”。有些论文使用变量“m”代替。

w : 用于给我们的输入信息x重新分配权重的常量值。(使其总是更大或更小一点)。我们使用这个变量来帮助调整信噪比。使信号“变大”使得它在任何给定的操作中不易受到噪声的影响。但是,如果数据太大,则会增加我们完全损坏数据的可能性。这是一个折衷后的值。

E/e:通常指随机噪声。在某些情况下,公钥加密的数据在加密之前被混入了噪声。混入的噪声使解密变得困难。但这也使的相同的明文在使用相同的公钥时可以产生不同的密文,这增加了密文被破解的难度。请注意,根据算法和实现,E/e可以是矢量或矩阵。在其他情况下,它也可能是指操作累积的噪声。稍后我们会进一步讨论。

与许多数学论文一样,大写字母对应于矩阵,小写字母对应于矢量,斜体小写字母对应于标量。同态加密有四种我们关心的操作:公钥/私钥对生成,单向加密,解密和数学运算。我们先从解密开始。

img

img

上面的公式描述了私钥S和我们的“明文”x之间的一般关系。下面的公式告诉了我们如何使用私钥来解密数据。注意下面的式子,e去哪了?其实从原理上来说同态加密引入噪声的目的就是使人们在没有私钥的情况下很难解密我们的数据,但是如果你拥有密钥,噪声又显得很小以至于等于或小于舍入误差。下面公式中特殊的括号表示其中的计算结果四舍五入至最近的整数。其他的加密算法可以选择不同的舍入方式。取模运算符更是无处不在,加密的过程实际上就是生成一个满足上述等式的c。如果S是一个随机矩阵,c将很难被解密。简而言之,非对称情况下,生成加密密钥只需要找到私钥的逆即可。我们用Python代码来演示以下:

import numpy as np def generate_key(w,m,n): S = (np.random.rand(m,n) * w / (2 ** 16)) # proving max(S) < w return S def encrypt(x,S,m,n,w): assert len(x) == len(S) e = (np.random.rand(m)) # proving max(e) < w / 2 c = np.linalg.inv(S).dot((w * x) + e) return c def decrypt(c,S,w): return (S.dot(c) / w).astype('int') def get_c_star(c,m,l): c_star = np.zeros(l * m,dtype='int') for i in range(m): b = np.array(list(np.binary_repr(np.abs(c[i]))),dtype='int') if(c[i] < 0): b *= -1 c_star[(i * l) + (l-len(b)): (i+1) * l] += b return c_star def get_S_star(S,m,n,l): S_star = list() for i in range(l): S_star.append(S*2**(l-i-1)) S_star = np.array(S_star).transpose(1,2,0).reshape(m,n*l) return S_star x = np.array([0,1,2,5]) m = len(x) n = m w = 16 S = generate_key(w,m,n)

我在iPython notebook中运行这个代码后执行了以下操作(图示有相应的输出)。

img

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdxwy.html