TenSEAL库之CKKS参数介绍及代码示例

CKKS介绍

CKKS是一个可以实现有限次同态运算的加密方案,支持同态加法和同态乘。CKKS和其他同态加密方案的最大的区别就是,CKKS是直接支持复数的,当然也包括实数。但是,CKKS是一种近似同态计算,得到的结果是一个近似值,并不是准确值。

CKKS将复数向量首先编码成明文多项式,然后对明文多项式加密。解密的结果再解码成复数向量。CKKS具体的编码过程使用的是多项式的正规嵌入,也就是,明文多项式在单位根上的值就是实际的明文。

CKKS可以进行对称加密,也可以进行非对称加密(公钥加密),一般默认使用的是公钥加密。

CKKS的参数

由于CKKS是一个近似的同态,所以需要在开始的时候指定精度,或者说叫做缩放因子。在进行明文的编码的时候,由于是浮点数(有小数部分),所以乘上缩放因子,再配合射入操作,得到一个整数系数的明文多项式。CKKS实际的密文域是整系数多项式环。然后在解码的时候除以缩放因子得到原来的明文。

所以缩放因子的大小,决定了计算的精度。

CKKS还需要指定多项式的度数,也就是多项式的最高次数是多少。在TenSEAL的实现中,多项式的度数只能是2的整数次幂,比如1024,2048,4096,……

多项式的度数决定了明文多项式的系数的个数,同时也决定了一个密文可以打包多少个明文。也就是一个密文的明文向量是多长。度数越大,那么一个密文可以打包的明文就越多,通常是多项式度数的一半。

显然,多项式的度数也决定了密文的大小。多项式的度数越大,就需要更多的数来表示这个多项式,也就意味着密文会更大。

同时,多项式的度数越大,那么每一次运算需要的时间就越长,计算的效率就越低。

不过,正因为如此,多项式的度数越大,那么加密的安全性就越高。

CKKS的另一个参数是系数模的大小,这是一个向量。由于CKKS支持的是层级的同态加密,也就是可以执行的同态运算的次数是有限的(没有自举的时候)。由于噪声会随着运算的进行不断增加,所以CKKS在每次进行乘法运算都会进行一次模交换操作,密文多项式的系数模从一个较大的素数p变到q。所以每一次乘法会消耗一个素数。所以CKKS需要传入一个指定素数大小的向量,向量的长度指定了最多可以进行同态乘法的次数。

系数模的大小直接影响了密文元素的大小,同时,系数模越大,那么安全性就越低。

在TenSEAL中,每个系数模必须是最多60比特的素数,并且模2倍的多项式度数后等于1.

CKKS的密钥key

CKKS中一共有四个密钥。

私钥,用来解密密文的小多项式。这个密钥是私有的,一般不会公开。

公钥,用于加密明文,通常是公开的,同时公钥也会包含一些需要的公共参数,比如多项式的度数等信息。

重线性化密钥,用于将密文变成一个只有两个元素的多项式向量。由于一个密文是两个多项式,所以,在进行密文和密文相乘的时候,就会变成三个多项式。随着乘法的进行,多项式越来越多,这就是所说的密文维度灾难。所以,在每次乘法后,会默认调用一个重线性化函数,使得密文始终保持在两个多项式。这个密钥默认是自动生成的,并且默认在每次乘法后会调用重线性化。当然,如果你有特殊需求(比如特定的效率优化策略),那么可以手动关闭。

伽罗瓦密钥,用来在同一个密文中移动明文。比如一个明文向量是(1,2,3),对应的密文是c,那么在密文域计算的时候,我们希望2对应的是第一个位置,就可以使用伽罗瓦密钥来移动明文的位置。注意的是,每一个位置的明文是进行相同的操作的。比如c+2,那么得到的明文就是(3,4,5).如果是c+(1,2,3),那么就是(2,4,6).所以有时候会需要移动明文的位置,来对齐。这个密钥是可选的,没有移动明文的需求的时候,不需要生成。TenSEAL中是手动生成的。

代码示例

生成加密的上下文:

import tenseal as ts
ctx=ts.context(ts.SCHEME_TYPE.CKKS, poly_modulus_degree=8192, coeff_mod_bit_sizes=[60, 40, 40, 60])
ctx.global_scale=2**40

多项式的度数维8192,这个参数同时也指定了一个密文中最多可以加密4096个明文。

系数模有4个,除去第一个和最后一个,指定了最多可以进行的乘法次数为2.

global_scale指定了缩放因子。

下面这段代码将私钥从加密上下文中分离出来:

sk=ctx.secret_key()
ctx.make_context_public()

下面是加密和解密,以及加法和乘法的演示:

m1=[1.1,2.2,3.3]
m2=[-1,-2.01,3.5]
print("m1 is ",m1)
print("m2 is ",m2)

c1=ts.ckks_vector(ctx,m1)
c2=ts.ckks_vector(ctx,m2)

c3=c1+c2
sum=c3.decrypt(sk)
print("The sum of m1 and m2 is ",sum)

c4=c1*c2
prod=c4.decrypt(sk)
print("The product of m1 and m2 is ",prod)

猜你喜欢

转载自blog.csdn.net/watqw/article/details/129800906
今日推荐