近期,基于TensorFlow的隱私AI框架Rosetta正式開源(https://github.com/LatticeX-Foundation/Rosetta)。借助Rosetta,AI開發(fā)者不需要了解密碼學等隱私保護技術,只需要改動幾行代碼,就能賦予自己的程序以保護數(shù)據(jù)隱私的能力。本專欄將通過多篇獨家技術稿件,深度披露Rosetta的整體框架設計、TensorFlow的定制化改造最佳實踐、將密碼學理論算法進行高效工程化落地等內容。通過本系列專題,希望能讓更多開發(fā)者了解隱私AI框架的技術挑戰(zhàn),同時為密碼協(xié)議算法工程化、AI框架深度定制等相關方向的開發(fā)者提供一些經驗參考。
數(shù)據(jù)是AI技術的“燃料”已經成為業(yè)界的共識,更多的數(shù)據(jù)往往意味著可以訓練出更準確的模型。但無論是在公司內部還是多個企業(yè)之間,為了對用戶數(shù)據(jù)負責、合法合規(guī),在數(shù)據(jù)的分享使用時,必須注意對于原始明文數(shù)據(jù)的保護。
傳統(tǒng)的面向靜態(tài)數(shù)據(jù)保護的安全手段無法解決數(shù)據(jù)的動態(tài)使用、分享中的隱私泄露問題,而正是這一實際需求催生出了隱私計算(在AI場景下,更進一步的可以稱之為隱私AI)這一新的交叉技術。隱私計算技術融合在數(shù)據(jù)的使用過程之中,保障的是計算過程本身(廣義的講,還包括計算結果)不會泄露原始明文數(shù)據(jù)本身的信息。
目前實現(xiàn)隱私計算的途徑可以分為密碼學、聯(lián)邦學習和硬件可信執(zhí)行環(huán)境(TEE)等幾大類。而其中以密碼學理論為基礎的MPC(Multi-Party Computation,安全多方計算)是最有安全保障的技術路線,其秉持的基本理念是信任計算復雜度理論、代碼,而不是信任人、硬件,而聯(lián)邦學習和TEE目前還很難講清楚安全性,經常被發(fā)現(xiàn)新的安全漏洞。并且,聯(lián)邦學習中核心部分也往往需要使用同態(tài)加密等密碼學手段進行強安全性的保障。從工程技術的角度上看,聯(lián)邦學習是分布式機器學習技術的延伸,主要的挑戰(zhàn)是訓練過程中如何進行多異構終端的同步更新等[1],很多傳統(tǒng)分布式系統(tǒng)開發(fā)經驗仍然適用。而以MPC為代表的密碼學途徑則帶來了一些全新的挑戰(zhàn)。
安全多方計算MPC(圖片來自網(wǎng)絡)
其中最核心的困難是,密碼學屬于計算機理論領域,很多概念、算法協(xié)議都需要有長期的專業(yè)知識積累才能理解,而業(yè)務落地中的典型AI方向,無論是計算機視覺、文本挖掘還是用戶行為建模等都更加面向實際場景。如何打通以密碼學為典型代表的隱私保護技術與AI技術之間的壁壘?這是開發(fā)者在實際構建一個通用的、易用的隱私計算框架時需要解決的核心問題。圍繞著這個核心問題,又有一系列具體的工程技術挑戰(zhàn):
如何實現(xiàn)系統(tǒng)的易用性?AI開發(fā)者不會愿意,也不應該為了在業(yè)務中引入數(shù)據(jù)隱私保護能力而費時耗力地學習各種復雜、抽象的密碼算法。一個好的隱私AI框架應該是易上手的,便于AI開發(fā)者使用自己熟悉的方式快速解決自己的數(shù)據(jù)隱私問題。
如何實現(xiàn)系統(tǒng)的高效執(zhí)行?這包括單機和多機兩個層面。密碼學的計算大部分都是在大隨機數(shù)的密文上進行,為此常常需要使用專用的硬件指令、SIMD(Single Instruction/Multiple Data)等技術來進行單機并行化的加速,這些優(yōu)化實現(xiàn)需要對于密碼學基礎庫有深入的了解,并往往需要根據(jù)協(xié)議算法做進一步的并行優(yōu)化。而在多機層面上,則需要考慮如何和很多AI框架自身的并行優(yōu)化技術兼容。
如何實現(xiàn)MPC多方之間的高效通信?在MPC中,多方之間需要進行大量的同步通信,而且信道上的內容大都是無規(guī)律的、不可壓縮的一次性使用的隨機數(shù),這就需要在保證安全性的同時,根據(jù)具體的計算邏輯進行很多工程優(yōu)化以減少通信量和通信次數(shù)。
如何保障隱私保護技術的可擴展性?MPC等隱私計算技術還在不斷發(fā)展之中,也是學術研究上的熱點問題,所以一個好的隱私AI框架,需要能夠支持研究者簡單快速地將新的算法協(xié)議集成進來。
針對這些問題,業(yè)界已經有一些探索,下面我們結合Rosetta來具體談一談在隱私AI框架的設計和實現(xiàn)中如何克服這些挑戰(zhàn)。篇幅所限,本文主要整體性地先介紹宏觀設計,后續(xù)系列文章會進一步剖析一些技術細節(jié)。
如同其他的隱私AI框架一樣,Rosetta仍然處于發(fā)展的早期,尚有一些不完善之處。我們在此以Rosetta為例是希望能具體化地講清楚這一領域中的細節(jié)挑戰(zhàn),也希望激發(fā)更多開發(fā)者參與到未來的隱私AI系統(tǒng)設計中來。
隱私AI框架整體設計思路
目前業(yè)界尚沒有大規(guī)模落地的、成熟完善的隱私AI框架,但是已經有一些探索性的開源隱私AI框架,比如PySyft、TF Encrypted和CrypTen。
從整體上看,這些框架都是在TensorFlow或PyTorch的前端Python層進行封裝集成的。這樣做的好處是可以直接使用這些AI框架的上層接口來實現(xiàn)隱私計算算法,而且天然的可以直接調用框架自身封裝好的一些高層次API高功能。這對于聯(lián)邦學習這種本身就源自分布式機器學習的技術來說是較為適合的,但是對于密碼學的MPC來說會有一些不足:
首先,單機性能無法得到充分的提升。用Python來實現(xiàn)各種復雜的密碼學計算、多方之間的通信無法充分利用底層操作系統(tǒng)、硬件層的并行優(yōu)化。而且更現(xiàn)實的是,大部分高性能的密碼學庫提供的是C/C++的接口,如果在AI框架的前端上層實現(xiàn)MPC等密碼技術,則很難復用這些業(yè)界長時間積累(同時也還在不斷發(fā)展中)下來的成果。
其次,密碼協(xié)議等隱私技術的實現(xiàn)和AI框架本身耦合過深,不利于擴展。由于這些AI框架本身提供的對外API接口本就是面向AI需求的,在實現(xiàn)較為復雜的MPC等密碼協(xié)議時不僅需要熟練使用這些框架的API,還往往需要大量直接使用numpy等庫來實現(xiàn)復雜的計算邏輯。這一方面破壞了對AI框架自身使用上的自洽,不再能將全部的計算邏輯完全承載在AI框架的邏輯執(zhí)行圖上,另一方面也使得每一次引入新的后端密碼協(xié)議時都需要重新基于AI框架進行實現(xiàn),這對于密碼協(xié)議開發(fā)者來說成本很高。
基于上述認識,Rosetta在現(xiàn)階段首先以TensorFlow這一流行AI框架為基礎,深度改造其前端Python入口和后端kernel實現(xiàn),并封裝可插拔的MPC算法協(xié)議作為“隱私保護引擎”來驅動整個計算過程中數(shù)據(jù)的安全流動。
Why TensorFlow?
TensorFlow和PyTorch是目前工業(yè)界最主流使用的開源AI框架。雖然很多公司在內部可能也會根據(jù)自身需求定制化改造一些組件,或者推出各具特色的新框架以在易用性、高效性、完備性等不同的維度上進行進一步突破,但是整體上看,這些框架基本的設計范式是較為相似的。大多是通過豐富的接口API讓用戶以有向無環(huán)圖DAG的形式表達上層計算邏輯,而框架本身則會在實際調度執(zhí)行這些計算任務時進行一系列的優(yōu)化。TensorFlow雖然在用戶友好性上略遜色于PyTorch,常受開發(fā)者詬病,但是其在可擴展性、高效性上、分布式部署等方面確實是更加均衡、全面(當然這也意味著TensorFlow更加復雜,對其改造會更加的具有挑戰(zhàn)性)。所以綜合考慮下來,Rosetta在當前版本中選擇TensorFlow作為基本的底層承載體,在設計開發(fā)的過程中,一方面會充分利用TensorFlow內在的計算圖并行執(zhí)行優(yōu)化等功能以提升效率,另一方面也會盡量克制,主要是利用其作為深度學習框架通用性的一些接口特性,而不會過于依賴其獨有的一些組件。
Rosetta框架核心設計思想
隱私算子(SecureOp)作為核心抽象接口連接AI框架和隱私計算技術。TensorFlow在不同的層次上提供了多樣的擴展方式,Rosetta選擇后端算子(Operation)層作為核心切入點,TensorFlow在執(zhí)行算子時會動態(tài)的綁定到具體MPC協(xié)議中的SecureOp實現(xiàn)中。通過這樣的抽象,密碼協(xié)議開發(fā)者可以不需要了解AI框架,只需要用C++實現(xiàn)滿足接口定義的各個功能函數(shù)即可,而AI開發(fā)者也不需要深入了解MPC等技術的實現(xiàn)細節(jié),而只需要在現(xiàn)有算子的基礎上進一步封裝自己想要的上層高級功能即可。
基于優(yōu)化遍(Pass)的分階段轉換。為了盡可能給AI開發(fā)者提供易用的接口,減少給線上AI程序賦予數(shù)據(jù)隱私保護能力時的改造成本,Rosetta在整體的設計中借鑒了程序編譯器領域的核心概念:Pass。Pass是編譯器中常用的技術,主要用作將源碼文件一步步轉變?yōu)闄C器碼過程中的多輪轉化和優(yōu)化。在Rosetta中,用戶使用原生TensorFlow接口編寫的DAG(有向無環(huán)圖)形式的邏輯計算圖會被分階段的轉換、替換為多方協(xié)作執(zhí)行的MPC程序,這樣可以實現(xiàn)對于用戶API層最少的改動。
具體的,在Rosetta中,有兩個階段的Pass,一個在前端Python層的全局DAG構建過程中生效的Static Pass,會將原生Tensor轉換為支持自定義密文類型的RttTensor,將原生Operation轉換為支持tf.string格式輸入輸出的RttOp,并最終在圖開始啟動時進一步的轉換為承載實際MPC操作的SecureOp。
Static Pass
另一個是在SecurOp的實際執(zhí)行時所進行的Dynamic Pass處理,會動態(tài)的根據(jù)當前用戶選擇的協(xié)議選擇對應的實際算子實現(xiàn)去執(zhí)行,同時可以在此時嵌入基于執(zhí)行上下文的優(yōu)化處理。
Dynamic Pass
融合MPC技術的分布式隱私AI架構
理清楚整體的分布式結構對于了解一個系統(tǒng)的架構大有裨益。整個隱私AI系統(tǒng)對外接口會涉及三個方面,如何指定物理部署上的網(wǎng)絡拓撲?數(shù)據(jù)在整個計算的過程中是如何安全輸入、流動、輸出的?隱私計算邏輯要如何表達?Rosetta的整體邏輯結構如下圖所示:
Rosetta多方網(wǎng)絡結構圖
多方網(wǎng)絡的建立
MPC技術本身就是要求多方(multi-party)參與的,一般稱他們?yōu)镻layer,不同的MPC算法協(xié)議會有不同個數(shù)的參與方。以Rosetta中目前實現(xiàn)的三方協(xié)議SecureNN[2]為例,系統(tǒng)中存在三個邏輯參與方,P0、P1和P2。
在v0.2.1版本中,在這一方面的用戶接口層次上,為了保障對外的靈活性,目前支持用戶通過配置文件來一次性指定多機之間的網(wǎng)絡關系,也支持調用接口動態(tài)的激活、解除多方之間的網(wǎng)絡拓撲:
#調用activate接口會根據(jù)配置參數(shù)或配置文件建立起網(wǎng)絡
rtt.activate(protocol_name="SecureNN",protocol_config_str=None)
#調用deactivate接口會釋放網(wǎng)絡鏈接等資源
rtt.deactivate()
在內部實現(xiàn)中,每一個參與方都會監(jiān)聽一個本地的server端口,而同時分別建立到另外兩方之間的client網(wǎng)絡鏈接。這樣的好處是相互之間的網(wǎng)絡鏈接關系簡單清晰,當然也需要解決隨之而來的SecureOp并發(fā)同步執(zhí)行時的一致性問題,這一點我們會在后續(xù)文章中討論。
一些注意點
*熟悉TensorFlow的讀者可能會疑惑,這種多方基于不同數(shù)據(jù)跑相同程序的模式,不就是TensorFlow分布式執(zhí)行下對數(shù)據(jù)并行進行支持的In-graph replication和Between-graph replication嗎?并不是這樣,實際上它們是不同層次的結構,這里講的是上層邏輯視角的MPC各參與方,在實際中,你甚至可以進一步的將各方內部執(zhí)行的這一task按照TensorFlow的分布式規(guī)范進行集群部署,而將集群中的"server“作為統(tǒng)一的對外邏輯代表。
*上面一直講的是“邏輯上”的三方,那么在實際的業(yè)務場景中,可能是2個、4個或以上公司之間的數(shù)據(jù)合作,是不是就不能用這些架構了嗎?其實不然,我們完全可以在上層進行一層映射,以Privacy-as-a-Service的形式提供對上層的服務,關于這一點,后續(xù)文章也會進一步介紹。
隱私數(shù)據(jù)的流動
每一個邏輯參與方都可以有自己私有的明文輸入數(shù)據(jù),也可以繼續(xù)處理上一次任務輸出的密文結果。在整個程序的運行過程中,只有開始和結束時數(shù)據(jù)才會以明文的形式存在:開始時對于私有數(shù)據(jù)的引入,以及最后可配置是否將結果以明文的形式恢復出來加以輸出。而在中間各個算子的計算過程中,數(shù)據(jù)總是以密文形式在本地的邏輯上下文、多方之間進行交互。
對外接口方面,在實際的業(yè)務中多方數(shù)據(jù)之間是需要關聯(lián)對齊的,目前Rosetta提供常見的兩種數(shù)據(jù)集處理方法,一是對應于整體上數(shù)據(jù)集是在各方之間“水平劃分”的場景,即各方擁有不同樣本id的全部特征屬性值;另一種對應于整體數(shù)據(jù)集是在各方之間“垂直劃分”的場景,即各方之間擁有相同樣本id的部分特征屬性值。這些都可以調用PrivateDataset類的load_data等接口方便的處理。而在輸出階段,提供了如下兩個接口:
#將一個密文形式的cipher_tensor恢復為明文,receive_party參數(shù)指定3方中哪幾方可以獲得明文結果
rtt.SecureReveal(cipher_tensor,receive_party=0b111)
#與原生TensorFlow中模型保存接口SaveV2具有一樣的函數(shù)原型,可通過配置文件指定哪幾方可以獲得明文模型文件
rtt.SecureSaveV2(prefix,tensor_names,shape_and_slices,tensors,name=None)
隱私集合求交PSI(Private Set Intersection)技術
在實際場景中還存在一個很現(xiàn)實的問題,就是多方之間樣本的對齊問題,比如將A方的樣本id所指向的樣本和B方此樣本id對應的屬性信息給對應起來。PSI技術可以安全的解決上述問題,目前各個開源框架中還沒有將這一功能很好的集成進來,Rosetta目前正在集成這一功能,將在近期版本中發(fā)布。
在內部實現(xiàn)中,密碼學中的很多運算是在空間較大的環(huán)(Ring)、域(Field)等抽象代數(shù)結構上的操作,而具體的在代碼中則落地到對于大整數(shù)、多項式等數(shù)據(jù)結構上的處理,所以框架設計上要在三個方面達成平衡:
盡可能的實現(xiàn)用戶對于內部密文數(shù)據(jù)結構的透明無感;
TensorFlow的DAG圖構建、自動求導等核心功能仍需要無縫的支持;
支持不同的MPC協(xié)議使用自定義的具體數(shù)據(jù)結構對象以便于擴展。
為同時實現(xiàn)這些目標,Rosetta基于tf.string這一TensorFlow原生數(shù)據(jù)結構來承載各協(xié)議自定義的密文數(shù)據(jù),然后通過對TensorFlow源碼代碼進行深度的hook改造使得DAG圖構建、自動求導等功能仍然可用。
DAG的執(zhí)行
如上述網(wǎng)絡結構圖所展示的那樣,各Player運行的是同一份基于TensorFlow編寫的AI二進制代碼,比如訓練一個簡單神經網(wǎng)絡模型的程序。用戶直接的使用TensorFlow中原生的算子API來構建邏輯計算圖DAG,Rosetta內部會在圖開始執(zhí)行時完成到隱私算子SecureOp的轉換。與其他隱私計算框架相比,這樣的切換成本是最低的。
在執(zhí)行過程中,各Player自身都是在按照這個DAG圖在運行,特殊的地方在于在各個算子的內部執(zhí)行過程中,各個Player會根據(jù)自己所屬的角色遵循MPC協(xié)議執(zhí)行不同的操作,這些操作即包括本地的在密文上的處理,也包括在多方之間進行強同步的通訊交互,傳輸大量隨機數(shù)形式的密文。
Rosetta多方協(xié)作運行圖
小結
在本篇文章里,我們結合Rosetta框架,從整體上介紹了隱私AI框架在工程落地時所需要面對的挑戰(zhàn),以及Rosetta等框架的一些設計方案。后續(xù)的文章中,我們會就核心的關鍵模塊進行進一步的介紹。