安全级别
密码学中通常使用比特安全来表示安全级别,一般用字母
λ
\lambda
λ来表示。说一个方案的安全级别是
λ
\lambda
λ,意味着,攻破这个方案至少需要
2
λ
2^\lambda
2λ次操作。当然,一般指以很大概率成功,否则,万一一个人运气超好,一下就猜对密钥了呢!
不同的方案,可能有不同的安全级别,同一个安全方案,参数选择不同,那么安全级别也不一样。
具体的安全级别的计算,根该密码方案归约到或者基于的困难问题有关。
CKKS安全级别的影响因素
CKKS的安全是基于LWE问题的,更具体来说,是基于多项式环上的LWE问题。简单来说,假设我们有一个a,s,e。a是从环上均匀采样的随机数,s是私钥,从私钥分布中采样得到,e是从错误分布中采样得到。然后计算
b
1
=
−
a
s
+
e
b_1=-as+e
b1=−as+e。假设我们只知道a和b,那么求s是困难的。这就是LWE问题。
对于错误分布,一般来说是跟高斯分布有关,但是独立地从高斯分布中采样错误多项式的系数是不安全的。通常可以通过在嵌入表示中使用高斯分布采样,然后乘上一个环元素,再取整,通过模运算映射到环上。(有很多高效的采样方式)
注意,错误的模或者范数,应该是小的,这会极大的影响密文中的噪声,和运算时噪声的增长幅度。
然后是私钥分布。私钥分布一般有三种
- 均匀采样:即私钥是在环上通过均匀采样得到的;
- 错误分布:私钥和错误分布相同,也就是在错误分布中采样得到私钥;
- 三元组随机采样:即私钥的每一个系数是从 {-1,0,1}中均匀采样得到的。
不同的私钥分布对安全级别有不同的影响。
除了分布以外,多项式环的大小,也就是使用的分圆多项式的度数和系数模的大小有关。
分圆多项式的度数(多项式的度数是多项式的最高次数)越大,那么显然方案会越安全。
而多项式的系数模越大,方案反而越不安全。
在同态加密标准(Homomorphic Encryption Standard)中给出了比较详细的对应关系。
一般在实现中,通常使用三元组随机采样作为私钥的采样方法,所以这里给出了对应的安全级别的截图,有兴趣的可以直接看原文寻找更详细的对应关系(三个私钥分布的安全级别都有)
其中,n表示分圆多项式的度数,
l
o
g
q
log q
logq表示系数模的比特长度。security level表示安全级别。
TenSEAL中CKKS的参数设置示例
TenSEAL中默认的安全级别是128比特。也就是说当分圆多项式度数为8192的时候,多项式系数模最多不能超过218比特。
import tenseal as ts
ctx=ts.context(ts.SCHEME_TYPE.CKKS, poly_modulus_degree=8192, coeff_mod_bit_sizes=[40,30,30,30,30,50])
ctx.global_scale=2**30
在生成加密上下文的时候,也就是实例化context类的时候,可以传入的参数(与安全有关的)polyn_modulus_degree就是分圆多项式的度数。
而coeff_mod_bit_sizes是系数模的素数分解。用这个例子来讲,就是,会产生一个40比特的素数和4个30比特的素数,还有一个50比特的素数,将他们的乘积作为系数模。
在这个数组中,第一个素数的大小40,和你要控制的精度有关,但是应该比缩放因子,global_size要大。
而中间的30,通常和缩放因子的比特长度一样,而具体有多少个和你要执行的乘法的深度有关。假设刚开始密文的缩放因子是s,那么一次乘法后,比如
m
1
m_1
m1和
m
2
m_2
m2相乘
m
1
s
∗
m
2
s
=
m
1
∗
m
2
s
2
m_1s*m_2s=m_1*m_2s^2
m1s∗m2s=m1∗m2s2。在CKKS中每次乘法后会做重缩放,也就是除以一个素数,也就是coeff_modulus_sizes中的一个素数。如果这个素数和s差不多大,那么新密文的缩放因子也就大概是s了。
最后一个是一个特殊的素数的长度,通常是最大的一个素数(但不是强制要求),这个素数和密钥的生成有关。
coeff_modulus_sizes的和应该是小于对应多项式度数的logq。比如多项式度数为8192的时候,应该小于218.