项目地址:https://github.com/OpenMined/TenSEAL
论文地址:https://arxiv.org/pdf/2104.03152v2
TenSEAL 是一个在微软 SEAL 基础上构建的用于对张量进行同态加密操作的开源Python库,用于在保持数据加密的状态下进行机器学习和数据分析。
TenSEAL 库使用了Microsoft SEAL库作为其加密引擎。它提供了一组高级API,可以方便地进行加密、解密及密态操作,如同态加法、同态乘法和同态运算。
TenSEAL 支持多种机器学习算法,包括逻辑回归、线性回归和神经网络等。通过使用TenSEAL,用户可以在保护数据隐私的同时进行分析和计算,而无需担心数据泄漏的风险。
一、
项目工程
功能
-
基于 BFV(Brakerski/Fan-Vercauteren)方案的整数向量进行加密 / 解密;
-
基于 CKKS(Cheon-Kim-Kim-Song)方案的实数向量进行加密 / 解密;
-
密文 - 密文向量以及密文 - 明文向量进行逐元素的加法、减法和乘法操作。
-
点积和矩阵乘法。
-
tenseal.sealapi 封装了完整的 SEAL API。
示例
# pip install tenseal==0.3.15
import tenseal as ts
# Setup TenSEAL context
context = ts.context(
ts.SCHEME_TYPE.CKKS,
poly_modulus_degree=8192,
coeff_mod_bit_sizes=[60, 40, 40, 60]
)
context.generate_galois_keys()
context.global_scale = 2**40
v1 = [0, 1, 2, 3, 4]
v2 = [4, 3, 2, 1, 0]
# encrypted vectors【编码和加密】
enc_v1 = ts.ckks_vector(context, v1)
enc_v2 = ts.ckks_vector(context, v2)
# 密文 + 密文
result = enc_v1 + enc_v2
result.decrypt() # ~ [4, 4, 4, 4, 4]
# 点积:<密文,密文>
result = enc_v1.dot(enc_v2)
print(result.decrypt()) # ~ [10]
matrix = [
[73, 0.5, 8],
[81, -5, 66],
[-100, -78, -2],
[0, 9, 17],
[69, 11 , 10],
]
# 密文向量 * 明文矩阵
result = enc_v1.matmul(matrix)
print(result.decrypt()) # ~ [157, -90, 153]
参数
-
SCHEME_TYPE:ts.SCHEME_TYPE.CKKS。
-
poly_modulus_degree:8192。
-
coeff_mod_bit_sizes:系数模数大小,这里的[60, 40, 40, 60]表示系数模数将包含4个素数,分别为60位、40位、40位和60位。
-
global_scale:缩放因子(scaling_factor),即 。
(1)缩放因子(scaling_factor
)
CKKS方案的第一步是将实数向量编码为明文多项式,采用固定缩放因子进行定点运算。 缩放因子指的是编码精度,用数字二进制表示。如下图所示:
scaling_factor
是CKKS中用于将浮点数编码为整数以进行加密的缩放比例因子,用于控制加密方案的计算精度。即是在加密和解密过程中使用的缩放倍数,通常是某个 2 的幂次(如、 )。它决定了加密时将浮点数扩展为整数时的精度。
它
的作用是在计算过程中对数据进行缩放,以管理噪声的增长。通过适当的缩放,可以在一定程度上减少噪声对计算结果的影响,从而保持计算的准确性。
精度控制:缩放因子越大,计算结果的精度越高。它直接影响浮点数在加密过程中保持的精度,较小的缩放因子可能导致精度损失。
噪声积累:较大的缩放因子能减少噪声的相对影响,因为密文的精度更高。然而,如果缩放因子过大,会增加密文大小和计算复杂度。
数值范围:缩放因子决定了能表示的数值范围。如果缩放因子太小,可能无法表示足够精确的浮点数;而过大的缩放因子可能导致密文噪声增长过快。
计算精度方面,缩放因子的选择直接影响着计算结果的精度。如果缩放因子选择不当,可能会导致计算结果的精度下降,尤其是在进行多次同态计算后。
计算次数方面,缩放因子与 CKKS 算法能够支持的计算次数相关。不合适的缩放因子可能会导致噪声过快增长,从而限制了能够进行的同态计算次数。例如,如果缩放因子过大,可能会在较少的计算步骤后就使噪声超过可接受的范围,无法继续进行准确的计算。因此,需要根据具体的计算需求和数据特点,合理选择缩放因子,以平衡计算精度和计算次数。
(2)多项式模数次数(poly_modulus_degree
)
poly_modulus_degree
表示CKKS加密方案中多项式环的维度,即多项式的最大次数。多项式环通常表示为,其中 N 就是 poly_modulus_degree
。
这个参数定义了多项式的最大次数,从而决定了加密数据的 "容量"。较高的poly_modulus_degree
可以表示更大范围的数值,但同时也会增加计算复杂度。
它决定了多项式环的维度,即加密方案的基本操作空间,通常取为2的幂(例如 1024、2048、4096、8192 、16384、32768)。
性能和存储开销:增大多项式模数次数会增加加密密文的大小和计算的开销,因为多项式操作的复杂度与多项式模数次数成正比。
安全性:多项式模数次数越大,安全性越高。通常,较大的值提供更好的抗量子攻击能力,但也需要权衡计算效率。
并行化计算:较大的多项式模数次数允许更多的并行计算。
如果选择过大的
poly_modulus_degree
,可能会导致计算速度过慢,不适合实际应用场景。例如,在某些资源受限的环境中,如移动设备或边缘计算节点,过高的多项式次数可能会使加密计算变得不切实际。
(3)多项式系数模数(coeff_mod_bit_sizes
)
coeff_mod_bit_sizes
表示CKKS的模数链中每个系数模数的位数(通常以比特为单位)。模数链由多个模数组成,随着每次乘法和重新缩放操作,模数链中的模数逐渐减少。 它是一个列表,表示在模数链中的每个模数的比特大小。例如,[60, 40, 40, 60]
表示模数链有 4 个模数,其中每个模数的比特长度分别为 60、40、40 和 60。
由这个参数决定是一组素数coeff_modulus
,决定了"新鲜密文""的噪音预算。coeff_modulus
至少有两个素数组成,最好是少的,最合理的使用2~8个素数,单个素数可以达到60bit,噪音预算和这些素数的总比特呈线性关系。
支持的乘法深度:多项式系数模数决定了支持的乘法深度(即能执行的最大乘法次数)。模数链越长,支持的乘法次数越多,但计算开销也越大。
噪声控制:每次乘法后,密文的噪声会增加。重新缩放操作减少模数链的长度以控制噪声,因此较大的模数链可以处理更多次乘法。
计算精度:模数链的大小决定了运算精度。如果模数链太短,重新缩放后剩余的模数不足以支持高精度运算。
coeff_mod_bit_sizes
会影响方案的安全性:如果其他参数保持不变,总比特越大,安全性越低。但是为了获得更大的计算力,也就是说要提升噪音预算,就要增加coeff_mod_bit_sizes
的总比特数,所以为了安全性,需要增大poly_modulus_degree
,这可能会对批处理的性能产生影响,所以计算性能也会改变。从计算性能角度看,较大的系数模数比特大小会增加计算的复杂性。因为在同态运算中,涉及到对系数的操作,更大的比特大小意味着更多的计算步骤。在安全性方面,系数模数的选择也会影响加密方案的安全性。不合适的系数模数可能会导致加密系统容易受到攻击。因此,在选择coeff_mod_bit_sizes
时,需要在计算性能和安全性之间进行权衡。
其中,n
表示分圆多项式的度数(poly_modulus_degree
),logq
表示系数模的比特长度(coeff_mod_bit_sizes
的总比特数)。security level
表示安全级别。
总结
-
poly_modulus_degree
:决定多项式环的维度,影响加密系统的安全性、并行计算能力和性能。 -
coeff_mod_bit_sizes
:定义模数链的比特长度,决定加密方案的精度和支持的乘法深度。 -
scaling_factor
:控制加密和运算的精度,较大的缩放因子提供更高的精度,但也增加了计算复杂度和密文大小。
这些参数的选择通常需要在安全性、性能、精度和计算深度之间做出权衡。
密钥
-
公钥:用于加密。
-
私钥:用于解密,不共享,TenSEALContext对象中保存。
-
重线性化密钥(Relinearization Keys)【可公开】:用于重线性化(密钥交换),在乘法后用于降低密文维数。
-
伽罗瓦密钥(Galois Keys)【可公开】:用于批处理密文的旋转。批处理向量的旋转的应用是密文求和****。
默认情况下,会自动执行重线性化后和重缩放。
二、
论文解读
摘要
机器学习算法已经取得了显著的效果,并被广泛应用于各个领域。这些算法通常依赖于敏感和私有数据,如医疗和财务记录。因此,进一步关注隐私威胁和应用于机器学习模型的相应防御技术至关重要。在本文中,我们介绍了TenSEAL,这是一个使用同态加密保护隐私数据的机器学习开源库,可以轻松地集成到流行的机器学习框架中。我们使用MNIST数据集对我们的实现进行了benchmark测试,结果显示加密的卷积神经网络可以在不到一秒钟的时间内进行计算,通信量不到0.5MB。
1、介绍
近年来,机器学习狂奔发展。在典型场景中,用户需要将数据发送给服务提供商,服务提供商将对数据执行一些计算并返回结果。这种方法有两个关键问题。首先,出于隐私考虑,用户可能不想将其数据发送给服务提供商。其次,如果用户不向服务提供商发送数据,那服务提供商就无法向用户提供模型。使用同态加密,可以解决该问题,用户的数据将始终加密,服务提供商将看不到输入和输出,并且仍然可以对这些加密数据进行计算。然而,在机器学习中采用同态加密的速度很慢。原因之一,虽然目前可用的密码库为密码学家提供了一个优秀的API,但对于数据科学家来说,使用它们可能具有挑战性。另一个原因,是计算成本,包括通信和计算成本。
贡献
-
我们提出了一个灵活的开源库,使用同态加密进行密文的张量计算。该库可以直接将张量从当前流行的机器学习框架(如 PyTorch 或 Tensorflow)转换为加密版本。
-
我们在不到一秒的时间内在加密数据上评估卷积神经网络,推理过程中的通信时间不到0.5MB。
论文的其余部分,我们在第2节中描述了库的架构。在第 3 节中详细介绍在加密空间中计算卷积神经网络所需的算法。在第 5 节中,我们对我们的库进行了实验性测试,并在第 6 节中总结了我们工作的一些局限性。
2、架构
TenSEAL 是一个将经典机器学习框架与同态加密功能联系起来的库。它管理着在加密数据进行张量运算的所有复杂性。TenSEAL 依赖于 Microsoft SEAL 中 CKKS方案的实施。客户端可以使用一种受支持的前端语言(C++ 或 Python)处理明文张量或密文张量。在客户端 - 服务器方案中,消息交换是使用协议缓冲区完成的。核心 API 围绕三个主要组件构建:环境(context)、明文张量和密文张量。
环境 context
TenSEAL的context是库的核心组件。它生成并存储加密计算所需的必要密钥。context生成用于加密的公钥、用于解密的私钥、用于旋转的伽罗瓦密钥以及用于密文重新线性化的重新线性化密钥。
这个context对象还将处理 thread-pool,它控制在执行可并行化操作时应并行运行多少个 job。同时context还可以配置为在计算期间执行自动进行密文重新线性化(relinearization)和重新缩放(rescaling)。
明文张量
明文张量(PlainTensor)是一个将未加密张量与加密实现相连接的类。下图描述了张量的转换过程。
张量(Tensor):
是深度学习中广泛使用的数据结构,本质上就是一个高维的矩阵,甚至将其理解为NumPy中array,Pandas中的DataFrame。
单个元素叫标量(scalar),一个序列叫向量(vector),多个序列组成的平面叫矩阵(matrix),多个平面组成的立方体叫张量(tensor)。在深度学习的范畴内,标量、向量和矩阵都统称为张量。
密文张量
EncryptedTensor 接口提供了一个 API,需要由库公开的每个张量实现。接口有一个 TenSEALContext 对象,这是进行任何同态加密操作所必需的。派生类公开了不同的张量风格,例如:
-
CKKSVector 派生 EncryptedVector 接口,并且可以通过将实数向量加密为单个密文。
-
CKKSTensor 将实数的 N 维张量加密为密文的 N 维张量。但是,它可以批处理轴以及每个密文中可用的槽,因此只需要 (N-1) 维的密文张量。
3、方法
在同态加密方案上构建张量时,需要解决两个重要问题: 1,如何在加密之前对张量进行编码? 2、使用特定编码时可以执行哪些操作?
CKKS 方案的批处理功能允许将一个 矩阵加密为 N 个密文,每行或每列为一个密文。另一种可能性是将整个张量加密为单个密文。根据我们将明文张量放入密文的方式,我们可以执行不同的操作,具有不同的复杂度。目标是使用最少数量的密文,并在最小运行时间内具有最大深度,从而优化内存和计算。为了寻求这个理想目标,我们发现我们可以使用单个密文对输入图像进行加密,并在卷积神经网络上对其进行计算。这需要在客户端进行预处理步骤,将图像编码为矩阵,由卷积窗口作为行组成,然后通过垂直扫描将其展平为向量。在 TenSEAL 中,所有这些功能都是围绕 CKKSVector 实现的。一个CKKSVector 包含 个实数值,其中 N 是多项式模数的次数。我们可以与其他加密或明文向量执行逐元素操作(加法、减法和乘法)。我们有一种方法用于计算加密向量的幂(逐元素),该方法使用最优电路,从而使用最小乘法深度。此外,因为我们需要不同激活函数的多项式近似,所以我们构建了一种方法,用于以密文向量作为变量求值多项式,确保使用最小电路。除了逐元素操作外,我们还需要矩阵操作来执行机器学习任务。我们实现了 Halevi 和 Shoup(2014)提出的密文向量与明文矩阵乘法的变体,该变体可以使用多个线程以更快地运行。
A.2
可以查看附录中的表3,以获取库的密文张量支持的操作列表。
点积(dot)
TenSEAL为点积提供了与 Halevi & Shoup(2014)类似的计算方法,但支持的向量大小不是2的幂,或者未填满密文的所有插槽。先前方法中的这一限制是由于右旋转期望最后一个元素为第一个元素,而对于我们处理的情况并非如此。如果向量大小不是 2 的幂,我们的方法在点积数量上受到特定限制。然而,通常不会达到此限制,因为该方案允许的乘法数量可能更低。我们通过将输入向量尽可能多次复制到密文插槽中,并在计算期间仅进行左密文旋转来实现。我们的方法与 Halevi & Shoup(2014)具有相同的算法复杂度。我们使用 CKKS实现了它,用于加密向量与明文矩阵之间的点积运算。因此,它可以扩展为支持加密矩阵与明文矩阵之间的点积(矩阵乘法)。
A.3
附录中的图 3 展示了如何在密文向量与明文矩阵之间执行点积运算:
卷积(conv2d)
TenSEAL还支持计算卷积,即提供当前流行的机器学习框架(例如PyTorch)计算卷积的类似实现。我们使用了Image Block to Columns (im2col)技术,该技术将卷积层转换为单个矩阵乘法运算。这种技术需要密文矩阵乘明文向量,我们通过对矩阵转置与复制的明文向量进行逐元素乘法来实现。最后,将结果旋转并累加到单个密文向量中。
此操作仅使用一个乘法运算和log2(N)个旋转和加法,其中N表示矩阵中的行数。下面解释如何将"图像块-》列"算法应用于加密输入。需要注意的是,转换发生在明文数据中,转换后的输入图像进行编码和加密为单个密文。这直接意味着堆叠两个卷积是不可能的,因为重新组织密文的插槽并非易事。j
A.4
可以使用单个矩阵乘法来执行二维卷积,而不是在每个窗口上重复乘法。这种方法称为图像块到列的卷积( image block to column),或图像到列的卷积(image to column)。下图显示了如何使用此方法执行卷积。它首先将输入矩阵重新组织成表示卷积窗口的行,然后用扁平化的卷积核执行点积,如图4所描述。
将此技术应用于加密矩阵(加密为一个密文)并不是一件小事,因为重新组织slot并不那么简单。我们需要在加密之前将矩阵重新组织为预处理步骤,以便为卷积做好准备。
密文矩阵(输入图像)和 明文向量(kernel)的计算可以通过逐元素乘法和一系列旋转和累加来执行。图5、图6显示了执行此操作的步骤。第一步显示了密文矩阵(彩色)是如何编码并与明文向量(kernel)相乘的。第二步是对向左旋转不同的不同版本的输出求和。
第4小节:相关工作、第5小节:实验性测试、第6小节:总结 ---- 略