/AZFT-MPC

Primary LanguagePython

MPC可信硬件说明文档

Secure multi-party computation (MPC) enable a group to jointly perform a computation without disclosing any participant’s private inputs. The partic�ipants agree on a function to compute, and then can use an MPC protocol to jointly compute the output of that function on their secret inputs without revealing them.

MPC(Secure multi-party computation) 可以用于解决一组互不信任的参与方之间保护隐私的协同计算问题,SMPC 要确保输入的独立性,计算的正确性,同时不泄露各输入值给参与计算的其他成员。本项目实现了可信硬件下的安全多方计算通用框架。

项目优势

目前的MPC框架存在大量的问题

  • 计算效率低下。
  • 无法保证可证明安全或安全性较低

尽管近年来研究者努力进行实用化技术的研究,并取得一些成果,但是离真正的大规模产业化应用还有一段距离。

使用可信硬件的MPC

将可信硬件用于安全多方计算是一种有效提高计算速度的方法,并且在安全性假设下,其相较于传统交互式的MPC具有更高的安全性优势。但目前主流的可信硬件大多采用SGX,但由于英特尔的信任源问题,无法保证数据安全。本系统开发了通用的可信硬件支持框架,可以嵌入任何可信硬件。

与同类产品的比较

本项目设计开发了基于可信软硬件的通用安全多方计算平台。符合以下特点:

  • 异构性:该安全多方计算平台可以采用TPM、smartcard、TrustZone等各种实现,并非依赖于Intel SGX
  • 高效性:该框架可支持全部通用安全多方计算任务,性能(通信量与运行时间)超过目前最先进的非可信软硬件的通用安全多方计算系统2~3个数量级。
  • 强鲁棒性以及高安全性:在任意n-1计算方恶意攻击的情况下,仍然保证输出计算结果的正确性。该框架超过现有已和安全多方计算方案的安全水平。该框架可以做到mobile下的malicious安全。

可证明安全下的异构

logical

逻辑结构和物理结构对比

不同的公司采用各自的底层可信硬件平台参与计算,信任源由单一的SGX到多信任源。在逻辑上可以规约到所有计算方直接与可信第三方交互。

同类型安全性比较

本框架与同类型相比在安全性上有较大优势,做到了mobile下的malicious安全,远远超过了目前市面上的主流框架。

table

与同类型框架安全性比较

协议说明

协议流程分为运行指令编译,秘钥交换,数据交换,以及进行多方计算四个流程。

  • 运行指令编译
    运行指令编译是将需要运行的代码转换为二进制流,并进行密码学签名的过程。目的是保证用户无法使用其他指令来进行作弊操作,具有协议生成权限的用户,持有协议签名密钥ζ,当该用户要生成协议时,向可信硬件发起签署请求,按指令运行流程,输入指令块,可信硬件对指令块依次进行对称秘钥签名生成MAC,返回使用非对称秘钥对中用于加密的私钥对对称秘钥进行加密,并将该密文和MAC数据一起返回给用户。用户向MPC网络广播该密文。所有用户只有持有该密文才能进行下一步的计算。除了代码块本身的MAC,由于出于对指令运行顺序的保护(如下代码段,修改指令运行顺序会造成巨大的安全漏洞),为此采用hash链的方式来确保运行时指令的顺序。
block1:d = 1
...
blocki:d = a + d
...
blockj:b = b ^ d
#修改顺序后不断调用
block1:d = 1
block2:b = b ^ d
#可以进行选择明文攻击

如上所示,若不能保证指令执行的顺序,攻击者可以通过重新组合代码顺序(如上,得到b和~b的密文)进行有效的选择密文攻击。为此保证可信硬件对执行代码的有效性验证时有必要的。(这里,读者可能会觉得在代码前加执行顺序,如1,2,3的序列,将序列添加到MAC中,可信硬件累计序列来确保依次执行。但考虑跳转逻辑,这无疑是存在安全性问题的,如添加跳转后,程序会多次调用b = b ^ d语句,每次的不同仅仅体现在序列不同上。而为了保证指令运行,该序列对用户是可见的)。

为此采用如下的hash链的方式来进行MAC检查。

指令与nonce连接通过hash函数生成新的nonce,与下一条指令继续进行连接hash操作,这样形成了链式的hash结构,最后,输出的nonce作为可信硬件检测指令完整性的凭据,输入到可信硬件中,可信硬件在计算指令时重新构建hash链验证一致后输出运输结果。

Hash

hash链结构

读者可以发现这是完全固定指令执行顺序的方式,若采用交互式执行指令(更灵活的指令执行方式)可以采用Merkle‘Tree的方式来重组这个执行顺序,这在之前的代码版本中实现。

解决密文跳转逻辑

众所周知,普通MPC协议是无法解决密文跳转逻辑的。因为一旦发生跳转,密文将直接被泄露。为此分支MPC协议的求解是个复杂的的问题。

if a + b > c goto label1
	d = i1 + i2
	d = d * i3
label1:
	d = i1 - i2
	d = d / i3
~~~~~~~~~~~~~~~~~~~~~~~~~~
	w = a + b > c 
	d = (1 - w)(i1 + i2) + w * b
	d = (1 - w)(d * i3 ) + w * b
label1:
	d = w * (i1 - i2) + (1 - w) * b
	d = w * (d / i3) + (1 - w) * b

对分支MPC的一般处理如上,需要对分支进行消除。消除所有的分支后进行多方计算。但由于复杂分支的存在,给这类方法提供了巨大的挑战。本系统在之前的版本采用该方法,并对分支进行了递归的消除。但某些分支情况无法被处理,并且代码的复杂度大大提升。

在之后的代码块处理方法中,提供了更简单的方法。在本质上本系统未在本质上解决密文跳转的问题,而是将密文跳转问题转变成代码块的跨块跳转问题。所有的密文跳转逻辑不能跳出块本身。这是将代码流结构改成代码块结构带来的直接好处。而可以证明所有复杂跳转结构可以转换成尽可能小的分块块内跳转逻辑。这个转化过程将在后续工作中实现。

  • 秘钥交换
    密钥交互的过程为构建可信信道的过程,可信硬件初始化时,TEE产生公钥对,此时TEE创建了两对公钥对,为了构建密码学下的P2P网络,TEE会向全网络广播对应的两个公钥,这使得全网络所有的节点都清楚其他所有节点的公钥对,为确保所有公钥对与所有节点对号入座,所有节点维持一个节点的序列值,按节点的序列值填入收到的公钥对,由此构成了公钥板。与此同时,为了确保收到的公钥对的确是对应节点发送的,TEE需要使用其Root key对公钥信息进行确认,对此全网络交换公钥对后,TEE对公钥板(包涵自己公钥)进行签名(使用root key:第二对公钥对中的私钥),签名后发送到P2P网络上,TEE收到对应整个网络的公钥板签名后,检查所有签名是否满足阈值要求。对应的广播信息结构如下,下图为为第一次告知全网络TEE自己的公钥对时的结构,前半部分为公钥对1,后半部分为公钥对2,其中收到的TEE会根据接受方硬编码的IP地址得到对于的TEE序号,感觉序号生成签署公钥对数据包,如下图前半部分为签名信息,后半部分为签名时公钥板上的公钥序列,后半部分可以缺省,缺省时为默认自然数序列的公钥顺序。

image-20200520192508483

公钥对结构

image-20200520192601773

签署公钥对数据包结构
  • 数据交换
    与指令交换类似的,需要进行数据交换来确保用户运行的指令中的数据的正确性。可信硬件同样使用非对称秘钥对中用于加密的私钥对对称秘钥进行加密,然后使用对称秘钥对数据进行加密,最后使用该秘钥对数据和指令中使用的标签整合内容进行MAC计算。用户广播并监听。 具体实现为使用AE(Authenticated encryption)系统进行数据的加密和数据和label的对映。先使用对称密钥对数据进行加密得到密文,再对密文和label进行连接,使用Hmac计算MAC数据,将这几个字段以及使用公钥加密的对称密钥密文数据一起打包成数据报发布到P2P网络上。如下图

    image-20200520193138528

    数据交换报文

    可信硬件进行计算时检查AE的正确来确保数据的可靠。流程图如下

protocol_0

秘钥、数据交换过程
  • 计算
    用户需要进行计算时将标签、数据密文,指令,以及标签-数据密文的MAC、指令的MAC输入到可信硬件,可信硬件返回输出标签对应的密文结果和标签-密文MAC。

项目实现

系统流程设计

struct

系统实现
  • 代码编译成电路指令模块 在该模块,实现了对用户输入的java代码转换为电路指令的功能,使用算法消除了代码的数据相关性(牺牲一定的运算时间)。最后将转换的指令流读入内存供主程序查询。
  • 网络层模块设计 网络实现了数据的接受和发送,以及对数据的序列化和对象化,主程序将数据对象交付给该模块后,该模块转换为二进制流发送到网络;该模块将在网络上监听到的二进制数据流转换为数据对象供主程序查询。

protocol_1

协议运行
  • 应用层模块设计 在该模块实现了整个程序的调度逻辑,包括密钥交换,签名,指令流的提交和轮询,控制整个用户程序的业务流程,按上图协议运行流程运行。而在该模块的具体实现中为了降低代码的耦合度,将继续划分成多个功能模块和主模块。

  • 可信硬件程序设计 在可信硬件程序的设计中,先根据用户交互设计固定了抽象类的所有接口,然后根据不同的平台开发相同接口的可信硬件程序。具体实现了

    • 所有的逻辑运算操作、数值计算操作,并返回操作结果的密文形式。
    • 公钥对,对称密钥对生产和对应的查询公钥接口。
    • 数据的加密查询接口。
    • 对不同流程中签名的检查逻辑,并返回对应的数据流。

    protocol_2

协议运行优化
  • 相关优化 对协议进行了优化,如数据交互中的数据流压缩,指令签名交互过程中对指令 MAC的重新设计等, 如上图对计算流程的优化,去除了输出结果前的签名交互流程,减少了网络开销。

代码块和深度学习算法支持

code_block

代码块实现

由于深度学习算法,存在大量的矩阵乘法操作等,使得使用原来的构架(每次运行一次指令进行一次加解密的操作)大量的时间用于密码学加解密操作。同时由于采用原来的接口(支持三元组操作符),不支持多参数输入,使得矩阵乘法需要分解为大量的基础运算指令,列如,

两个100*100 的矩阵乘法需要分解成10000 + 5000 + 2500 + ... + 13 + 7 + 4 + 2 + 1 = 20000个三元指令。而一次卷积操作需要矩阵乘法至少需要2000个类似的卷积操作。

针对这一问题本系统采用代码块的方式,用户向trusted hardware输入的不再是单独的指令,而是指令集(代码块),与之前的指令密码学保护方式类似的采用hash链的方式来保护可信硬件的输入指令和数据的对应关系。hardware检查数据、输入的权重和指令集完整性,在hardware内部运行指令集,指令分析代码块,依次调用内部的运算模块,计算结果,运行完成后向用户输出密文数据。

项目结构

  • compiler
    • mixedProtocolsAnalysis
    • Protocols_Analysis
  • sootOutput
  • HW
    • crypto
    • crypto_pend
    • ...
  • src
    • main
    • network
    • protocol
      • ...
  • include
  • test

HW hardware 中是模拟可信硬件的类文件。其中主要的两个文件:crypto为模拟可信硬件API函数,crypto_pend为添加了机器学习支持的crypto子类函数,调用crypto_pend即可。在之后的版本中修改为TEE cap版本,使用TEE.h 和 TEE.cpp代替上述两个类结构。

compiler 负责将java code 编译成电路语句,输出到sootOutput文件夹,其中mixedProtocolsAnalysis是编译程序的编译运行文件,Protocols_Analysis是源文件。

protocol 程序负责读入电路语句,对电路语句进行展开、去除数据依赖,与HW交互对指令进行MAC操作等。

network 程序负责整个网络的通信,对数据进行序列化,提供缓冲区,储存交互的数据等。

main 程序中运行了整个程序的业务流程,包括多次的数据交互,秘钥交换,指令的运行等。

test 编写了一些测试用例。

其他文件 包括了编译安装的脚本,一些中间函数等。

Java code编译成电路语句

将java code 编译成电路语句,涉及到代码块的拼接,代码参数、宏定义的展开等。使用Protocols_Analysis程序对java文件进行编译得到电路程序,输出在sootOutput文件中。使用file_deal函数对该文件进行裁剪获取运行有效部分。

电路语句展开实现[在代码块版本删除]

由于需要对指令进行数据有效性检查,需要添加MAC,在系统对指令进行签名时,需要对指令变量进行展开(针对数组变量等),此时要对程序段进行预运行,该预运行(展开)包括了

  1. 对分支语句进行展开,以确保得到的指令可以添加计数器。
  2. 对不合法指令进行检查,密文不能出现在分支语句中、密文不能出现在数组索引中等。
  3. 对数组元素进行改写,如arr[i11], 先确保i11是明文数据,不然返回报错,在用密文改写数组,如i11在运行到此指令时value为100,则得到arr_100。
  4. 对代码进行预展开能确保程序是数据独立的,只有通过了预展开,才能证明代码段在输入密文数据前数据流已经确定了。

运行

运行结构

持有协议签名密钥ζ的节点,生成协议并共享到所有参加运算的节点。所有的节点运行MPC程序,两两发送持有的数据密文,进行数据交换。最后各自向本地的可信硬件输入之前得到的协议。可信硬件运行协议,检查到输出语句向客户端输出明文数据。TEE在内部维持数据存储。若数据栈满,客户端需要向TEE查询数据。此时TEE会返回使用AE加密的密文数据。在下一轮计算是客户端需要提供这些数据。

截屏2020-05-20 下午8.01.38

运行结构

可以看到,在两方计算下,两个计算节点同时起到了数据提供方的作用。但这并不是必须的,所有的节点都拥有数据提供、参与计算、协议生成的功能(只要具有对应的密钥和数据),可以指定某方进行计算,某方提供数据,某方生成协议。

本系统支持linux运行或使用docker容器运行。

Linux

运行:

cd install_tool
#检查环境,或手动安装jsoncpp
bash ./install.sh
#编译java code 文件 bash ./compile.sh java_code项目路径  如
bash ./compile.sh ./java_code_demo/mexp
#编译
cmake -DCMAKE_BUILD_TYPE=Release
make
#运行程序
./main
dockerfile
docker bulid -t azft_mpc_demo 
#运行docker
docker run -it --net azft_mpc_hw 
#使用code_gen编译协议,编译前代码储存在./protocol_file文件夹下
./code_gen ./protocol_file
#运行
./main
#input listen port
#输入监听端口,列如6000
#input connect host
#输入链接host和端口,如10.111.45.46:6001, 如果在本地则直接输入端口号,如6001,
#程序会提示下一步指令,按要求输入来继续下一步。
#进行运算前先使用1选项向网络发送数据,然后选择2运行协议。
#系统会自动读取label_data.data和data_data.data来读入标签和对应的数据,同理协议文件将保存成code_data.code文件被自动读取。

Release

  • Jan 2, 2020
    实现了基本逻辑,可以运行大部分指令,目前已经实现了array的所有功能,但java code累计从命令行输入变量到数组中的代码,编译成电路语句时由于需要用户交互输入,而框架设计为non-interactive,无法支持此类代码,需要在下一步进行改写。
  • Jan 6, 2020
    修改了移位操作时计算错误的BUG,修改了验证指令完整性MAC的逻辑,改为使用链式计算MAC的方法,记录累计MAC值,进行指令MAC发送时只发送结束MAC,可信硬件只有在检查到结束MAC时才进行明文输出,该方案减少了网络通信量。
  • March 1, 2020
    添加了对神经网络的支持,实现了在Hardware内进行神经网络卷积,池化等操作的支持。
    设计了代码块指令,用户可以使用代码块作为输入指令向Hardware进行命令输入。
  • March 20, 2020
    实现了resnet模型,在该框架下实现了resnet预测模型。
  • May 20,2020
    将框架应用到TEE cap上。

性能测试

相较前人的协议,本系统性能上有较大的提升。

添加代码块后性能比较

在单核cpu下,针对简单算法(gcd)和复杂算法(resnet50),对系统运行的两种模式进行了测试。分别记录两种模式下cpu运行时间、测试时间(加上网络传输数据延迟)、网络消耗流量

运行方式 指令复杂度(行) cpu计算耗时(s) 测试耗时(s) 网络流量
non_block_gcd 65675 3.56 6.27 1051.5 KB
non_block_res 1017685 221.55 226.71 8080.9 KB
block_gcd 75 0.0021 0.05 0.332 KB
block_res 152 27.36 4.09 602.1KB

与前人系统性能比较

前人的系统提供的性能报告运行在24核cpu下,本系统采用的为16核cpu,给出以下的对应的运行resnet101的性能比较。

运行方式 网络延时 cpu计算耗时(s) 测试耗时(s) 网络流量
proposed_protocol_16核 0.03ms 6.01 6.88 602.1KB
secureNN_24核 0.03ms 141.5 170.404 22851.7MB
proposed_protocol_16核 100ms 6.09 7.27 602.1KB
secureNN_24核 100ms 156.49 1719.84 22851.7MB
proposed_protocol_16核 500ms 6.19 8.21 602.1KB
secureNN_24核 500ms 156.449 9694.77 22851.7MB