2022-7月-日报

什么是同态加密

同态加密是一种加密形式,但是与我们理解的加密方法不同的是,它允许人们对密文进行特定形式的代数运算得到仍然是加密的结果,然后对结果进行解密得到的明文与直接对明文进行相同的代数运算的结果一样。如下图所示:

在这里插入图片描述

换言之,这项技术令人们可以对加密的数据进行处理,得出正确的结果,而在整个处理过程中无需对数据进行解密,直接在加密之后的明文上进行处理即可。

如果一种同态加密算法支持对密文进行任意形式的计算,则称其为全同态加密(Fully Homomorphic Encryption, FHE);如果支持对密文进行部分形式的计算,例如仅支持加法、仅支持乘法或支持有限次加法和乘法,则称其为半同态加密或部分同态加密,英文简称为SWHE(Somewhat Homomorphic Encryption)或PHE(Partially Homomorphic Encryption)。一般而言,由于任意计算均可通过加法和乘法构造,若加密算法同时满足加法同态性和乘法同态性,则可称其满足全同态性。

目前,同态加密算法主要分为半同态加密和全同态加密两大类。半同态加密主要包括以RSA算法和ElGamal算法为代表的乘法同态加密、以Paillier算法为代表的加法同态加密以及以Boneh-Goh-Nissim方案为代表的有限次数全同态加密;全同态加密算法主要包括以Gentry方案为代表的第一代方案、以BGV方案和BFV方案为代表的第二代方案、以GSW方案为代表的第三代方案以及支持浮点数近似计算的CKKS方案等等。

同态加密的组成部分

同态加密算法一般包含以下四个部分:

  1. KeyGen:密钥生成算法,产生公钥和私钥
  2. Encryption:加密算法
  3. Decryption:解密算法
  4. Homomorphic Property:同态加密计算部分

同态加密的分类

为了更好地理解与运用同态加密算法,我们按照将同态加密算法支持的运算类型和数量,将其分成3类:部分同态加密、层次同态加密、和全同态加密。

  1. **部分同态加密(Partial HE,简称PHE)指同态加密算法只对加法或乘法(其中一种)有同态的性质。**例如:RSA加密是最早应用的公钥加密算法框架,同时RSA算法也是一种PHE算法,其对乘法有同态的性质。PHE的研究成果出现比较早,并且加法同态加密算法(Additive HE)比 乘法同态加密算法要多一些。PHE的优点是原理简单、易实现,缺点是仅支持一种运算(加法或乘法)。
  2. **层次同态加密算法(LHE,Leveled HE 或 SWHE ,SomeWhat HE)一般支持有限次数的加法和乘法运算。**层次同态加密的研究主要分为两个阶段,第一个阶段是在2009年Gentry提出第一个FHE框架以前,比较著名的例子有:BGN算法、姚氏混淆电路等;第二个阶段在Gentry FHE框架之后,主要针对FHE效率低的问题。LHE的优点是同时支持加法和乘法,并且因为出现时间比PHE晚,所以技术更加成熟、一般效率比FHE要高很多、和PHE效率接近或高于PHE,缺点是支持的计算次数有限。
  3. 全同态加密算法(Fully HE,简称FHE)支持在密文上进行无限次数的、任意类型的计算。从使用的技术上分,FHE有以下类别:基于理想格的FHE方案、基于LWE/RLWE的FHE方案等等。FHE的优点是支持的算子多并且运算次数没有限制,缺点是效率很低,目前还无法支撑大规模的计算。

同态加密在联邦学习中的运用

在联邦学习中,各个参与方分享梯度到服务服务器上以聚合全局模型,但是已有研究证明通过几个梯度信息就可以推断出原数据信息,所以如果直接发送明文的结果可能会有隐私泄露风险。隐私风险可能来自于中间人攻击,又或者参与方认为服务器方都是不可信的。在这种场景下,同态加密就可以发挥很重要的作用。

多方直接将梯度信息采用同态加密算法进行加密,然后交给服务器进行聚合运算,此时因为数据是被加密的,服务器也只能进行聚合运算,但是不能获取到任何梯度信息,避免了隐私泄露。

这种情况下,联邦学习中的有三类参与者,一类是加入训练的参与者,一类是server,在一类是CA机构。由CA机构生成同态加密的密钥对交给参与者对梯度进行加密,然后加密梯度交给server,server计算完成之后交给CA机构进行解密,然后再由CA将聚合后的结果分发给参与者。

Paiilier库

Paiilier是一种同态加密算法,满足加法同态。其支持的运算如下:

  1. [ [ x 1 ] ] p k ∗ [ [ x 2 ] ] p k = [ [ x 1 + x 2 ] ] p k [[x_1]]_{pk}*[[x_2]]_{pk} = [[x_1 + x_2]]_{pk} [[x1]]pk[[x2]]pk=[[x1+x2]]pk,由这个可以看出,即使是加密之后的密文,也支持加法运算,这也就是Paiilier是加法同态的原因
  2. [ [ x 1 ] ] p k r = [ [ r ∗ x 1 ] ] p k [[x_1]]^r_{pk} = [[r*x_1]]_{pk} [[x1]]pkr=[[rx1]]pk,其中 r r r是任意常数。由次可以看出,虽然Paiilier不支持密文之间的乘法,但是支持密文与常量之间的乘法。
  3. [ [ x 1 ] ] p k + r = [ [ x 1 + r ] ] p k [[x_1]]_{pk}+r = [[x_1+r]]_{pk} [[x1]]pk+r=[[x1+r]]pk,由此可以看出Paiilier不仅支持密文与常量的乘法,还支持密文与常量的加减法。

总结起来就是,Paiilier支持密文之间的加减法,支持密文与明文之间的乘除法。

Paiilier库实现了半同态加密Paiilier算法,可以简单实现同态加密。

项目官方地址:https://github.com/data61/python-paillier

安装

去PyPI单独看一下phe的安装说明:phe(插一句,PyPI真的是个非常好用的和python相关的各种包的安装集合地)

直接进行安装:

pip install phe

在安装phe之前它推荐安装gmpy2,虽然不是必须的,但gmpy2做大数计算和精确计算以及提高计算效率都很有帮助。

同样到pypi中查看安装帮助:https://pypi.org/project/gmpy2/#files

我们也可以直接安装:

pip install gmpy2

测试

from phe import paillier
import gmpy2 as gy

public_key, private_key = paillier.generate_paillier_keypair()


def test_mul(encrypt_x, encrypt_y, origin_x, origin_y):
    # [[x]]*[[y]] = [[x+y]]
    encrypt_res = paillier.EncryptedNumber(public_key, encrypt_x.ciphertext() * encrypt_y.ciphertext())
    res = origin_x + origin_y
    assert res == private_key.decrypt(encrypt_res)


def test_exponent(encrypt_x, x, r):
    # [[x]]^r = [[x*r]]
    encrypt_res = paillier.EncryptedNumber(public_key, encrypt_x.ciphertext() ** r)
    res = x * r
    assert res == private_key.decrypt(encrypt_res)


secret_number_list = [3, 4, 5]
encrypted_number_list = [public_key.encrypt(x) for x in secret_number_list]

test_mul(encrypted_number_list[0], encrypted_number_list[1], secret_number_list[0], secret_number_list[1])
test_exponent(encrypted_number_list[0], secret_number_list[0], 3)

encrypt_res = encrypted_number_list[0] + encrypted_number_list[1]
assert 7 == private_key.decrypt(encrypt_res)

encrypt_res = encrypted_number_list[0] + 4
assert 7 == private_key.decrypt(encrypt_res)

再通过计算测试一下同态性,可以发现phe中的paillier支持同态相加以及密文与明文的加法和乘法计算,同时也验证了paillier的性质不支持乘法同态:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0jMlnOFt-1657808057956)(assets/6.同态加密/20200323182838143.png)]

安全多方计算

安全多方计算可形式化描述为,n个计算参与方分别持有数据x1,x2,…,xn,协议的目的是各方利用自己和的它方的秘密数据计算一个预先达成的共识函数y1,y2,…yn=f(x1,x2,…,xn),此时任意一方可以得到对应的自己想要的结果yi,但无法获得其他任何信息,无法得到其他人的密码信息。如下图:
在这里插入图片描述
在传统分布式计算模型下,传统的分布式计算由中心节点协调各用户的计算进程,收集各参与方的明文输入信息,各参与方的原始数据对第三方来说毫无秘密可言,很容易造成数据泄露。在MPC计算模式下,不需要可信第三方收集所有参与节点的原始明文数据,只需要各参与节点之间相互交换数据即可,而且交换的是处理后(如同态加密、秘密共享等处理方法)的数据,保证其他参与节点拿到数据后,也无法反推原始明文数据,确保了各参与方数据的私密性。

多方安全计算的特点:

  1. 两方或者多方参与基于他们各自隐私或秘密数据输入的计算。

  2. 参与一方都不愿意让其他任何第三方知道自己的输入信息。

MPC方案主要可分为基于混淆电路(Garbled Circuit,GC)和基于秘密共享两种。
根据参与方的个数,可分为两方安全计算(two party computation,简称2PC)和多方安全计算(multiparty computation)

秘密共享

传统的对称加密就可以视为一种密码共享,例如: C = E n c k e y ( M ) C = Enc_{key}(M) C=Enckey(M)。其中的M是明文,C是密文,key是密钥。也就是说,明文被分解成了密文和密钥,分发给多方就实现了秘密共享。

谈及秘密分享时,一般取的是它狭义的定义,即数据的裂片被一组参与方分别拥有。这些参与方一般是对等的角色,且其中的分享或者说分裂和还原均不涉及加解密。秘密分享的优势正在于此,数据的分裂和还原运算一般来说成本极低,如加性秘密分享(Additive Secret Sharing),分裂和还原只是加减法,除此之外,就是对分裂点的选择需要做一次随机数生成,这些运算成本远低于一般的加解密运算。

如果仅限于分裂和还原,秘密分享就没有什么价值,它的真正价值在于处于分裂态可以运算,而运算的结果在多方参与的情况下可以还原。这正是隐私计算中所追求的可用而不可见的性质,因此秘密分享成为隐私计算中最重要的框架之一的多方安全计算的基石。

算数秘密共享

算术秘密分享( Arithmetic Secret Sharing ) 是一种低成本的秘密分享,它的主要思想是将一个数 x x x随机的分裂为两个或多个数,如加性秘密分享中,分裂为 x 1 x_1 x1 x 2 x_2 x2 ,使得 x = x 1 + x 2 x = x_1+x_2 x=x1+x2,分裂后的数分属不同的计算方,谓之分享,各计算方即可根据这些分享的数据展开隐私保护下的算术计算。

Additive Secret Sharing 加法秘密共享

假设现在有两个参与方A和B,他们各自有数据 x a x_a xa x b x_b xb,现在C想知道两数的和,但是A和B不想告诉C x a x_a xa x b x_b xb的值。那么双方利用算术秘密共享可以有:A: x a = x a 1 + x a 2 x_a = x_{a1}+x_{a2} xa=xa1+xa2,B: x b = x b 1 + x b 2 x_b = x_{b1}+x_{b2} xb=xb1+xb2
A此时将 x a 1 x_{a1} xa1发送给Server1,将 x a 2 x_{a2} xa2发送给Server2,B同理。

这时候C想知道和,C向各个Server请求和计算算子,Server1计算 z 1 = x a 1 + x b 1 z_1 = x_{a1} + x_{b1} z1=xa1+xb1,Server2计算 z 2 = x a 2 + x b 2 z_2 = x_{a2} + x_{b2} z2=xa2+xb2,最终C计算 z 1 + z 2 z_1+z_2 z1+z2既得到两个数的和。
从而完成了加法运算。双方都没有泄露自己的数字。但是前提是,Server之间没有进行共谋攻击,如果两个Server联手,秘密就泄露了。

布尔秘密分享(GMW)

布尔共享与算数秘密共享类似,只是替换了运算。

XOR秘密共享

假设一个秘密值为 s s s,此时要将s分解成n份,那么就选择n-1个同bit长度的随机数。 r 1 , r 2 , … , r n − 1 r_1,r_2,\dots,r_{n-1} r1,r2,,rn1,计算:
r n = s ⊕ r 1 ⊕ r 2 ⊕ ⋯ ⊕ r n − 1 r_n = s \oplus r_1 \oplus r_2 \oplus \dots \oplus r_{n-1} rn=sr1r2rn1
最终s就被拆分成了 r 1 , r 2 , … , r n r_1,r_2,\dots,r_{n} r1,r2,,rn,既秘密的分享。恢复秘密只需要计算:
s = r 1 ⊕ r 2 ⊕ ⋯ ⊕ r n s= r_1 \oplus r_2 \oplus \dots \oplus r_{n} s=r1r2rn

举例

我们假设现在有秘密值 s = 10 s = 10 s=10,需要拆分成两份,既n=2。然后我们选择一个随机数15。
计算得到 r 1 = 15 , r 2 = 5 r_1 = 15, r_2 = 5 r1=15,r2=5。然后将 r 1 , r 2 r_1,r_2 r1r2分享给 P 1 , P 2 P_1, P_2 P1,P2
P 1 P_1 P1做运算: r 1 ⊕ 3 = 12 r_1 \oplus 3 = 12 r13=12 P 2 P_2 P2做运算: r 2 ⊕ 4 = 1 r_2 \oplus 4 = 1 r24=1。然后 P 1 P_1 P1 P 2 P_2 P2将运算结果还给我们。我们再进行解密: s = 12 ⊕ 1 = 13 s = 12 \oplus 1 = 13 s=121=13,就等价于 s ⊕ 3 ⊕ 4 = 13 s \oplus 3 \oplus 4 = 13 s34=13
这样 P 1 P_1 P1 P 2 P_2 P2既进行了运算,但是又不能得到秘密值。

xor秘密共享共享出去的秘密仅支持xor运算,既对xor是同态的。

Shamir秘密共享

Beaver Triples 三元组

Beaver三元组:主要用于安全多方计算协议中的乘法计算。应用范围为加法和乘法均为线性的秘密分享机制。
我们用用 [ ∗ ] [∗] []表示秘密被分享之后的状态,如 [ 𝑎 ] [𝑎] [a]表示秘密𝑎已经通过秘密分享函数被分享给了参与者,如果有n个参与者,则 [ 𝑎 ] = 𝑎 1 , 𝑎 2 , … , 𝑎 𝑛 [𝑎] = {𝑎_1,𝑎_2,…,𝑎_𝑛} [a]=a1,a2,,an。假设秘密共享函数为𝑓(𝑥),𝑥为待共享的秘密,参与者为 𝑃 1 , 𝑃 2 , … , 𝑃 𝑛 𝑃_1,𝑃_2,…,𝑃_𝑛 P1,P2,,Pn,参与者 𝑃 𝑖 𝑃_𝑖 Pi拿到的 𝑥 𝑥 x的子秘密记为 𝑥 𝑖 𝑥_𝑖 xi

假设需要分享的秘密为 𝑎 𝑎 a 𝑏 𝑏 b,参与者 𝑃 𝑖 𝑃_𝑖 Pi获得的 𝑎 𝑎 a 𝑏 𝑏 b的子秘密为 𝑎 𝑖 𝑎_𝑖 ai 𝑏 𝑖 𝑏_𝑖 bi
加法秘密分享机制为线性的意思为:存在一组常数 λ 1 , λ 2 , … , λ 𝑛 \lambda_1,\lambda_2,\dots,\lambda_𝑛 λ1,λ2,,λn,使得:
𝑎 + 𝑏 = λ 1 ∗ ( 𝑎 1 + 𝑏 1 ) + λ 2 ∗ ( 𝑎 2 + 𝑏 2 ) + ⋯ + λ n ∗ ( 𝑎 n + 𝑏 n ) 𝑎+𝑏 = \lambda_1* (𝑎_1+𝑏_1) + \lambda_2*(𝑎_2 + 𝑏_2) + ⋯+ \lambda_n*(𝑎_n+𝑏_n) a+b=λ1(a1+b1)+λ2(a2+b2)++λn(an+bn)
将其抽象简记为: [ 𝑎 + 𝑏 ] = [ 𝑎 ] + [ 𝑏 ] [𝑎 + 𝑏] = [𝑎] + [𝑏] [a+b]=[a]+[b]
乘法秘密分享机制为线性的意思为:存在一组常数 λ 1 , λ 2 , … , λ 𝑛 \lambda_1,\lambda_2,\dots,\lambda_𝑛 λ1,λ2,,λn使得:
𝑎 ∗ 𝑏 = λ 1 ∗ 𝑎 1 ∗ 𝑏 1 + λ 2 ∗ 𝑎 2 ∗ 𝑏 2 + ⋯ + λ n ∗ 𝑎 n ∗ 𝑏 n 𝑎*𝑏 = \lambda_1*𝑎_1*𝑏_1+ \lambda_2*𝑎_2*𝑏_2+ \dots+\lambda_n*𝑎_n*𝑏_n ab=λ1a1b1+λ2a2b2++λnanbn
将其抽象简记为: [ 𝑎 ∗ 𝑏 ] = [ 𝑎 ] ∗ [ 𝑏 ] [𝑎 * 𝑏] = [𝑎] * [𝑏] [ab]=[a][b]

现在我们的需求是,要求各个参与方协同计算 a ∗ b a*b ab,显然,如果参与方之间互相交换自己得到的子秘密 a i a_i ai,就能得到 a ∗ b a*b ab。但是这样参与者就能通过秘密重构函数得到原始的秘密 a , b a,b a,b。所以参与方之间不能直接进行交换,但是还要实现乘法,这就要利用到乘法三元组。
在协议开始之前预先产生一个随机三元组: [ x ] , [ y ] , [ 𝑐 ] [x], [y], [𝑐] [x],[y],[c],其中 x x x y y y对所有参与者保密, c c c满足 c = x ∗ y c=x*y c=xy。假设秘密 a a a b b b已经被分享,现在需要计算 a ∗ b a*b ab
步骤如下:

  1. 所有参与者公开自己计算的 [ α ] [\alpha] [α],其在本地计算方式为: [ α ] = [ a ] − [ x ] [\alpha]=[a]−[x] [α]=[a][x]
  2. 所有参与者公开自己计算的 [ β ] [\beta] [β],其在本地计算方式为: [ β ] = [ b ] − [ y ] [\beta] = [b]−[y] [β]=[b][y]
  3. 所有参与者计算 [ 𝑧 ] = [ c ] + [ α ] ∗ [ y ] + [ β ] ∗ [ x ] + [ α ] ∗ [ β ] [𝑧]=[c]+[\alpha]*[y]+[\beta]*[x]+[\alpha]*[\beta] [z]=[c]+[α][y]+[β][x]+[α][β]
  4. 最终 [ a ] ∗ [ b ] = [ z ] [a]*[b] = [z] [a][b]=[z] ,又因为 a a a b b b是加法分享值,所以最终所有参与者能重构出 a ∗ b a*b ab

因为 [ α ] [\alpha] [α] [ β ] [\beta] [β]已公开,因此所有参与者都可以通过秘密重构函数独立计算出 α \alpha α β \beta β。又因为:
[ 𝑧 ] = ( [ α ] + [ x ] ) × ( [ β ] + [ y ] ) = [ α ] ∗ [ β ] + [ α ] ∗ [ y ] + [ x ] ∗ [ β ] + [ x ] ∗ [ y ] = [ c ] + [ α ] ∗ [ y ] + [ β ] ∗ [ x ] + [ α ] ∗ [ β ] = [ c ] + ( [ a ] − [ x ] ) ∗ [ y ] + ( [ b ] − [ y ] ) ∗ [ x ] + ( [ a ] − [ x ] ) ∗ ( [ b ] − [ y ] ) = [ c ] + [ a ] ∗ [ y ] − [ x ] ∗ [ y ] + [ b ] ∗ [ x ] − [ y ] ∗ [ x ] + [ a ] ∗ [ b ] + [ x ] ∗ [ y ] − [ y ] ∗ [ a ] − [ x ] ∗ [ b ] = [ a ] ∗ [ b ] + [ c ] \begin{align} [𝑧] & = ([\alpha]+[x]) \times ([\beta]+[y]) \\ & = [\alpha]*[\beta] + [\alpha]*[y] + [x]*[\beta] + [x]*[y] \\ & =[c]+[\alpha]*[y]+[\beta]*[x]+[\alpha]*[\beta] \\ &= [c]+ ([a] − [x]) * [y] + ([b] − [y]) * [x] + ([a] − [x]) * ([b] − [y]) \\ &= [c]+ [a] * [y] − [x] * [y] + [b] * [x] − [y] * [x] + [a] * [b] + [x] * [y] − [y] * [a] − [x] * [b] \\ &= [a] * [b] + [c] \end{align} [z]=([α]+[x])×([β]+[y])=[α][β]+[α][y]+[x][β]+[x][y]=[c]+[α][y]+[β][x]+[α][β]=[c]+([a][x])[y]+([b][y])[x]+([a][x])([b][y])=[c]+[a][y][x][y]+[b][x][y][x]+[a][b]+[x][y][y][a][x][b]=[a][b]+[c]
所有参与者成功计算得到 a ∗ b a*b ab

安全多方计算线性回归实例

Two-server Model

假设现在有一个用户,它有很多数据,需要训练一个模型,但是它自己没有能力训练,需要大公司的帮助,但是它又不想把数据直接给某一个大公司,因为这样导致自己的隐私泄露,这时候就可以利用Two-server model。用户将自己的数据分成两个分享值,将分享值发送给两个服务器。单个服务器得到的是数据的分片,不能还原出完整的信息(假设两个服务器之间不会进行共谋攻击)
然后两个服务器在基于分片的基础上进行两方的安全计算,最终得到机器学习模型。
在这里插入图片描述

Linear Regression

假设我们现在的回归函数为: y = w x y = \mathbf{w}\mathbf{x} y=wx.
在这里插入图片描述
所以有模型更新: w = w − α ( x i w − y i ) x i \mathbf{w} = \mathbf{w} - \alpha(\mathbf{x}_i\mathbf{w} - y_i)\mathbf{x}_i w=wα(xiwyi)xi
用户对x和y进行加法的秘密分享。
在这里插入图片描述
与此同时,一个Server也随机初始化一个初始化参数,然后使用加法的秘密分享分享到两端:
在这里插入图片描述
这样双方就共同有了 x , y , w \mathbf{x},y,\mathbf{w} xyw的秘密分享值。那么两端在进行前向和反向传播的过程中,是没办法直接在本地计算。因为双方现在拥有的 x , y , w \mathbf{x},y,\mathbf{w} xyw都是处于分享态的,我们不能hi姐将分享态的 < x > 1 <x>_1 <x>1 < w > 1 <w>_1 <w>1进行计算。如果直接在分享态进行运算,然后再将结果结果进行相加,我们通过简单的式子就知道这是错误的。但是两方也不允许将自己的秘密分享值分享出去,这是MPC的前提。
那么问题来了,如何在本地实现前向传播和反向传播呢?既如何实现在分享态的情况下,双方也能正确计算得到 x w xw xw呢?
这就需要借助其他东西了,也就是Beaver triples(乘法三元组),利用乘法三元组去实现加法秘密分享的乘法运算。
根据乘法三元组,生成两个随机数 U , V , Z = U × V U,V,Z = U \times V UVZ=U×V,这个三元组就可以用于 x ∗ w \mathbf{x}*\mathbf{w} xw的计算。
在这里插入图片描述
通过这种方式计算之后,双方就各自拥有了 x w xw xw的密钥分享,也就是S1有了 < x w > 1 <xw>_1 <xw>1,S2有了 < x w > 2 <xw>_2 <xw>2

然后还有 ( x ∗ w − y ) × x (\mathbf{x}*\mathbf{w}-y)\times \mathbf{x} (xwy)×x,也需要一次乘法运算,所以我们还需要一个三元组 U , V ′ , Z ′ = U × V ′ U,V',Z' = U \times V' UVZ=U×V(因为第二个乘法的乘数还是原来的X,所以U可以不变,重新生成一个新的V即可)
最终双方都更新了自己的模型分享值,将双方的模型分享值相加,就得到了最终的模型。

那么在训练过程中,两端就要进行下面三种在线的重构:
在这里插入图片描述
这三个重构,也就是线性回归中主要的通信开销。这个通信开销主要是由beaver triples乘法运算所引发的。
上面模型更新中的减法,因为是加法秘密分享,所以各方直接在本地计算自己秘密分享值得减法即可。

被分享的十进制数上的算数操作

前人工作的不高效主要来源于在共享/加密的十进制数上的计算,之前的解决方案主要有两种:
1、把共享的十进制数看成整数,比如保留8位小数,就将原来的浮点数乘 1 0 8 10^8 108,转换为整数。做乘法后在很大的有限域上完全保留下所有的精度。缺点是只能支持一定数量的乘法,因为结果的范围会随着乘法的数量指数级增长。《Applying neural networks to encrypted data with high throughput and accuracy》
2、在十进制数上利用安全两方计算的布尔电路来做定点或者浮点乘法。这带来了大量的负载,因为计算两个l-比特长的数的乘法就需要O(l^2)个门,在2PC(例如姚氏混淆电路中),这样的电路需要为每个乘法进都算一次。《Secure linear regression on vertically partitioned datasets.》

本文提出了一种简单但有效的支持有限域上的十进制数的解决方案。将十进制数转换为定点数,考虑对两个小数部分最多有lD比特的两个十进制数x y的定点乘法,首先把通过 x ′ = 2 l D × x , y ′ = 2 l D × y x' = 2^{l_D}×x,y' = 2^{l_D}×y x=2lD×x,y=2lD×y,把数字转化成整数,然后把他们相乘得到 z = x ′ × y ′ z = x'×y' z=x×y,注意到 z z z最多有 2 l D 2^{l_D} 2lD表示积的小数部分,所以我们简单粗暴地将最后 z z z的最后 l D l_D lD比特砍掉,这样它最多有 l D l_D lD比特来表示小数部分。
z z z也可以被秘密分享,可以证明,两个服务器分别砍去自己的最后 l D l_D lD位比特,和想要的 z z z其实最多相差一个最不重要的比特位,这对最后结果的影响可以说是微乎其微。换句话说,相较于标准的定点乘,我们只是缺少了小数部分最不重要的一个比特位。

secret_sharing.py

import random
from collections.abc import Iterable

import numpy as np


class AdditiveSecretSharing:

    def __init__(self, data, n):
        # 分成几个秘密分享值
        self.n = n
        self.origin_data = data
        self.sharing_values = self.split(data)

    def get_sharing_value(self, index):
        return self.sharing_values[index]

    def split(self, data):
        if isinstance(data, Iterable) or type(data) == np.ndarray:
            res = {}
            for index, d in enumerate(data):
                res["sharing_{}".format(index)] = self.__split(d)
            return res
        return self.__split(data)

    def sum(self):
        if isinstance(self.sharing_values, dict):
            res = {}
            for k, v in self.sharing_values:
                res[k] = np.sum(v).item()
        return sum(self.sharing_values)

    def __split(self, data):
        # count = self.n
        res_list = [data]
        while True:
            if len(res_list) * 2 > self.n:
                break
            res = []
            for data in res_list:
                res.extend(self.__two_split(data))
            res_list = res
        random.shuffle(res_list)
        re_split_list = res_list[0:self.n - len(res_list)]
        res_list = res_list[self.n - len(res_list):]
        for data in re_split_list:
            res_list.extend(self.__two_split(data))
        return np.array(res_list)

    def __two_split(self, data):
        # random_num = round(random.random(), 2)
        random_num = 0.5
        value = round(data * random_num, 4)
        return [data - value, value]

    def __str__(self):
        return str(self.sharing_values)


class BeaverTriple:

    @staticmethod
    def multi(u: AdditiveSecretSharing, v: AdditiveSecretSharing, z: AdditiveSecretSharing,
              data_0: AdditiveSecretSharing,
              data_1: AdditiveSecretSharing):
        alpha = data_0.sum() - u.sum()
        beta = data_1.sum() - v.sum()

        res = 0
        for index in range(len(v.sharing_values)):
            res += z.sharing_values[index] + alpha * v.sharing_values[index] + beta * \
                   u.sharing_values[index]
        res += alpha * beta
        return res


if __name__ == '__main__':
    num_participants = 2
    x = AdditiveSecretSharing(1320, num_participants)
    w = AdditiveSecretSharing(12320, num_participants)
    print(x, w)

    u = AdditiveSecretSharing(1, num_participants)
    v = AdditiveSecretSharing(1, num_participants)
    z = AdditiveSecretSharing(u.sum() * v.sum(), num_participants)

    print(u, v)

    multi = BeaverTriple.multi(u, v, z, x, w)
    print(multi)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 博图WinCC是西门子公司开发的一款工业自动化监控软件,支持数据采集、实时监控、报警管理等功能。日年报表是基于历史数据生成的报表形式,用于分析和展示某个时间段内的数据变化趋势,以下是使用博图WinCC制作日年报表的步骤: 1. 配置数据采集:首先需要设置数据采集项,选择需要监控和记录的变量,如温度、压力、流量等。设置采样周期和存储时间间隔,确保数据被准确采集和存储。 2. 设计报表模板:在博图WinCC界面上选择“报表”功能,打开报表设计器。根据需要设计报表模板,包括表头、行列信息、数据格式等。可以插入变量、公式和条件语句,定制化不同类型的报表。 3. 历史数据查询:使用博图WinCC提供的历史数据查询功能,选择要生成报表的时间段,选择相应的数据采集点和变量。导出数据为Excel或其他格式,方便后续处理和分析。 4. 数据处理和分析:将导出的历史数据进行处理和分析,计算出报表所需的各项指标和数据统计结果。可以使用Excel等工具进行数据处理和图表绘制,展示数据的变化趋势和统计结果。 5. 生成报表:将数据处理和分析的结果填入报表模板中,生成最终的日、、年报表。可以将报表保存为PDF、Word等格式,方便查阅和共享。 总之,使用博图WinCC制作日年报表需要配置数据采集、设计报表模板、导出历史数据、数据处理和分析,最后生成报表。这样可以方便地记录和分析历史数据,了解系统运行情况和数据变化趋势。 ### 回答2: 博图WinCC可以通过以下步骤来制作日年报表: 1. 配置数据源:首先,需要在WinCC中配置数据源,可以选择使用历史数据存储(如SQL Server)。在WinCC的配置界面中,选择“数据源”选项,点击“添加”按钮,然后输入数据源的名称和连接信息。配置完毕后,保存并退出配置界面。 2. 创建报表模板:在WinCC的报表设计器界面中,选择“新建”按钮,然后选择报表类型为“日报表”,“报表”或“年报表”,根据需求选择相应的报表类型。接下来,可以选择报表的布局和样式,添加标题、表头、表格等内容,并设置数据源为前面配置好的数据源。 3. 设计报表数据源:在报表设计器界面中,选择“数据源”选项,并选择前面配置好的数据源。然后,选择数据源中的表格或查询,将需要的数据字段添加到报表中。 4. 填充数据:在报表设计器界面中,选择“数据”选项,点击“填充数据”按钮。根据报表类型和需求,选择填充的时间范围(日、、年),然后点击“确定”按钮,WinCC将从数据源中获取相应时间范围内的数据,并填充到报表中。 5. 预览和导出报表:在报表设计器界面中,选择“预览”选项,可以查看报表的效果。如果满意,可以选择“导出”选项,将报表导出为Word、Excel或PDF等格式,保存到指定的路径。 通过以上步骤,就可以在博图WinCC中制作日年报表了。需要注意的是,具体的操作步骤可能因WinCC的版本和设置而有所不同,可以参考WinCC的使用手册或在线帮助进行操作。 ### 回答3: 博图WinCC是一款先进的过程数据管理和监控系统,可以帮助用户对工业过程进行实时监测与控制。要创建日//年报表,需要按照以下步骤操作: 1. 打开博图WinCC软件,在项目中选择相应的控制模块。 2. 在项目中创建报表数据源。通过点击“添加报表数据源”按钮,在弹出的对话框中选择需要监测的变量。可以按照需求选择单个或多个变量。 3. 定义报表的参数。在报表数据源配置界面,可以设置报表的名称、时间段、时间间隔等参数。 4. 设计报表模板。在报表模板设计界面,可以选择所需的报表格式、布局、字体样式等。 5. 定义报表内容。在报表设计界面,可以添加标题、页眉、页脚等,并通过拖拽变量数据到报表中,将需要监测的变量数据添加到报表。 6. 配置报表生成规则。在报表生成规则界面,可以设置报表生成的触发条件,如按照每天、每、每年等时间周期自动生成报表。 7. 保存报表设计和配置。完成报表设计后,需要保存报表设计和配置。 8. 生成报表。在WinCC监控界面,可以选择“生成报表”功能,根据设定的触发条件,自动或手动生成报表。 9. 查看和导出报表。生成的报表可以在WinCC中直接查看,也可以导出为PDF、Excel等格式进行保存和共享。 通过以上步骤,就可以在博图WinCC中实现日//年报表的设计和生成。这些报表可以帮助用户了解工业过程的运行情况、分析数据趋势,并支持决策和优化生产过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值