基于TEE的数据合作实现方案
一、数据合作基本场景
让我们从一个最基本的数据合作场景开始,这个场景中存在两类主体:数据分析方(Data Analyzer,简称DA)是具有使用数据需求的企业,例如如数据研究机构、数据驱动决策的公司;而数据提供方(DataProvider,简称DP)则是自身具有大量数据的企业机构。
当DA需要DP的数据来进行分析或者其他用途时,两者产生了交互,这也是最基本的数据合作场景。
一个最为直观的流程:DP直接将原始数据发给DA。然而,这样做的问题在于不能防止DA将收到的宝贵数据进行二次贩卖。这实际上造成了隐私的泄露,也是目前数据合作行业的主要痛点之一。
最为简单的数据合作流程
注意到我们这个场景里面,DA需要的只是数据的分析结果而不一定需要完整的数据,故解决这个问题的一个思路就是,DA将他指定的分析程序提供给DP,然后让DP在“数据不出域”的情况下完成分析程序。最后,DP只将分析结果发给DA,则此次数据合作完成。
数据“不出域”的数据合作模式
这个方法的好处是,相比于暴露全部数据,DP只给出数据分析结果,而这个结果通常也是定制化的,不会泄露太多敏感信息。这意味着DP可以重复进行类似的数据合作,保证了原始数据的价值。在很多地方,这种解决方案被称为“数据可用不可见”。
然而,引入这个数据不出域的方案又会带来新的关于“可信”的问题,这也是所谓“隐私计算”的研究重点。具体而言,有下面几个亟待解决:
1.如何保证DP给出的原始数据的正确性。
2.保证分析程序被DP正确执行,即DP没有篡改代码。
3.保证分析结果的正确性:DP最后发给DA的分析结果确实是分析程序返回的结果。
接下来我们将从这三个问题出发,提出基于可信执行环境(TEE)的解决方案。
二、SGX基本介绍
1.什么是SGX?
SGX(software guard extensions),是Intel推出的基于硬件的可信执行环境(TEE)。本质上来说,SGX可以认为是一个特殊的CPU,拥有专属的内存空间,寄存器,运算器,指令集等。当然,TEE这种技术也有很多其他厂家在做,比如AMD的叫SEV,ARM的叫Trust Zone。
2.SGX如何保护隐私?
一般程序在运行时,其大部分信息(包括程序代码,中间变量的值)都需要放到内存里。而传统的内存是有办法被扫描并修改的:例如各种游戏修改器。因为程序代码也是要放到内存里的,所以甚至代码也可以被更改。
SGX对可信环境的贡献主要在于两点:它能保护运行在它之中的程序无法被篡改,以及能保证中间变量的值无法被获取。
其大致工作原理如下:SGX划分了一块专属内存区域,只有运行在SGX内部的程序能访问此段内存。其方法是在CPU这一层加了一个判断:如果外部访问的内存地址属于SGX的保护范围,则会返回无法访问。其整个判断过程都是写死在CPU电路里的,可以认为难以被篡改。
Intel的说明书定义任何在sgx之外的环境都是不可信环境,其内存、寄存器等都会被做任意更改。而sgx之内的环境为可信环境,受其保护的内存等无法被扫描或修改。其安全性的前提为Intel硬件的可信程度。然而,对SGX的漏洞和进攻方式一直是学术界和工业界都关注的研究热点,每年都有相关论文发表在顶级会议上。
注:SGX内部的代码本身还是可以通过静态分析获取(尽管很复杂),故代码本身不应包含任何隐私信息。
3.哪些CPU支持SGX?
Intel大部分CPU,如酷睿系列都支持SGX,只是平时我们极少用到。AMD等其他公司的CPU也提出过类似可信环境功能,但目前Intel的SGX的使用范围最为广泛。
三、SGX的使用
执行在SGX中的一段程序叫做enclave(中文名飞地),实际上是一个动态库。所谓的动态库是由程序的各个方法(函数)构成,不包含main函数。以下我们仍称作程序。同一平台下(同一个CPU)可以存在多个enclave。
SGX简单原理,Figure 1
注:图片来源https://blog.quarkslab.com/overview-of-Intel-sgx-part-1-sgx-internals.html
如果你想在你的电脑上进行enclave的开发/使用,需要经过下面的步骤:
1. 作为enclave的开发者,你首先需要生成一组RSA3072公私钥对,私钥自己保存好用于后面对enclave程序的签名。公钥提交给Intel官方申请加入一个白名单。之后,开发者拿出设计好的程序代码,用RSA3072私钥对源代码hash,配置文件(包括产品ID,序列号等)进行签名,再将签名、RSA3072公钥和上述源代码,配置文件等打包到一起,这样就得到了一个enclave文件。注意enclave支持的程序功能有限,如不支持I/O。用户在设计程序代码时应当参考Intel官方说明书以确定范围。
2. 此时的enclave文件不能直接被加载,还需要一个授权文件:开发者向Intel提交白名单申请一段时间后会收到一个授权文件,该文件是和开发者的RSA3072公钥绑定的。之后,开发者将签过名的enclave文件连同授权文件以及其他相关东西打包到一起,统称为安装包。安装包可以发给任何用户,并可以任何一台装有SGX的电脑上加载enclave文件。
3. 作为一个enclave的用户,只要获得完整的安装包(主要包括enclave文件以及授权文件)后就可以开始加载enclave。首先,程序源代码会被加载到SGX受保护的内存里面,但不做任何执行。然后SGX判断程序的hash值是否与enclave文件里附带的hash值匹配,用公钥验证签名是否合法,以及验证授权文件是否合法。其整个判断过程都是写死在CPU电路里的,可以认为难以被篡改。一旦验证通过则enclave程序加载完毕,无法再作修改。即使对于拥有私钥的开发者而言,一旦部署完毕后想要修改SGX代码,也只有重新签名并初始化一个新的enclave。
四、SGX里的交互
现在我们已知SGX的内存只有enclave内部方法能够访问,那么我们该如何使用这些方法来实现SGX内部和外部的交互呢?这依赖于两种特殊的方法类型,ecall和ocall。
一个enclave内部方法类型为ecall,如果它能够被enclave外部程序(即不可信环境)调用。换言之,ecall方法为enclave外部访问enclave内部的唯一通道,但其执行过程是受可信环境保护的。所有未声明为ecall的方法都无法在enclave外部进行调用。
用户在事先构建动态库时可以任意指定哪些方法为ecall。同时用户在这一步应当确保ecall函数的返回值不会造成任何隐私泄露。
ocall是enclave内部调用enclave外部方法的类型。由于所调用ocall方法是运行在不可信的环境中,用户要特别小心其中存在窃取信息的可能。Intel推荐尽可能少的声明ocall方法。
不难发现,两个enclave之间可以通过外部内存来进行交互:通过调用第一个enclave的ecall方法将欲发送的信息写入外部内存,然后第二个enclave调用ocall方法将外部内存对应位置的信息写入enclave里面。然而此次交互涉及到了不可信环境(外部内存),可能会造成信息被篡改。
Intel提供了一套直接让同一平台中两个enclave进行数据交互的手段,称作local attestation。其包含认证交互双方身份(均属于enclave)的过程,交换数据的过程,同时能获取交互双方enclave的hash值。该过程能可以保证全程交互数据外部不可见,且不依赖于外部内存的安全性(事实上,其原理用到了密码学中的ECDH秘钥交换,具有更高级别的安全性)。
更进一步的,Intel提供跨平台的enclave间数据交互,称作remote attestation。该过程也能达到和local attestation同样的目的,但每次进行remote attestation要求和Intel官方服务器进行一次交互,即每次交互都依赖于联网以及Intel官方服务器的可信性。
五、场景实现
有了上述工具,我们可以准备开始实现数据合作的场景了。回到本文最初提出的三个问题,我们逐一解决。
对于第一个问题,我们需要DP的原始数据存在一段公开可见的描述,如全部数据的hash值。DA在设计分析程序的时候,需加入一段判断传入的输入数据是否与公开的hash值相匹配的代码。如果不匹配则认为原始数据不合法。当然,如何保证公开的原始数据hash值也是正确的不在本文讨论范围之内。通常这需要DP的历史信用(如历史交易成功次数等)来背书。
对于第二个问题,就到了我们的SGX发挥作用的时候了。首先,我们需要有一个RSA3072公钥位于Intel白名单的可信第三方来扮演开发者的角色,并获得Intel官方提供的授权文件。之后,可信第三方将授权文件交给DA,并为DA部署一个特殊的enclave:该enclave用可信第三方的RSA3072私钥对DA传入的数据分析程序进行签名,且不会暴露RSA3072私钥的任何信息!(实现这个部署需要用到remote attestation以及seal操作)。这相当于开发者在不泄露私钥的情况下将开发权限“授权”给了DA。
之后,DA只需要将数据分析程序传给这个enclave获得其RSA3072签名,然后连同授权文件一起打包成安装包发给送DP即可。DP接收到安装包之后就可以在本地装有SGX的电脑上加载这个包含数据分析程序的enclave,并传入原始数据开始执行数据分析任务。在之后的执行过程中,程序会通过remoteattestation进行可信身份验证,包括验证执行环境确实是enclave,以及程序的hash值正确等,以确保DP篡改程序代码的话验证无法通过。
对于第三个问题,也是最后的一个关键问题,如何保证DP给出的执行结果是真实的呢?
这里同样需要用到一些密码学手段:DA生成一对非对称加密公私钥,称作验证钥匙。然后DA在数据分析程序最后加上一段对分析结果用验证私钥进行签名的代码。如果DP没有执行程序或者给出的不是正确的执行结果,那么DP无法获得这个结果的签名,最终将无法被DA所接受。
那么接下来的问题是,如何在将验证私钥不暴露给DP的情况下完成上面过程呢(若DP获得了验证私钥,则他可以获得任何签名)?注意,我们前面说过,不能将私钥作为常量写在分析程序代码里,会被静态分析而暴露(即常量作为代码的一部分会被看到,但程序执行过程中变量值是不可见的)。
这时就需要用到我们介绍过的remote attestation:DA将验证私钥传到他本地的一个enclave里,然后这个enclave和DP已经部署好的包含数据分析程序的enclave做一次remote attestation,其交换的数据就是这个验证私钥。这样包含数据分析程序的enclave就能用接收到的验证私钥对分析结果进行签名,且因remoteattestation是能保证交换数据的私密性的,DP仍然无法获取验证私钥。同时,remote attestation能顺便进行上面提到的可信身份验证(包括验证DP的执行程序确实是enclave,以及该enclave的hash值与DA提供的相匹配)。
基于TEE的数据合作实现
至此,我们已经介绍完毕如何通过SGX来做数据合作。然而上述方案仍然存在一定的缺陷,例如每次交易都需要联网和Intel服务器交互(remote attestation需求),以及DA和DP存在合谋的可能。
我们将在后续文章介绍如何通过区块链来消除上述弊端。