隱私數據在隱私AI框架中的安全流動

2020-11-03     AI科技大本營

原標題:隱私數據在隱私AI框架中的安全流動

作者 | Rosetta技術團隊

責編 | 晉兆雨

出品 | AI科技大本營

本文中,我們將介紹為了保護用戶的隱私數據,在隱私 AI 框架的計算任務全流程中,數據是如何以密文形式流動,同時仍正確完成加法、乘法等計算步驟的。

隱私 AI 系統存在的目的就是賦能 AI,使得各種 AI場景下對用戶隱私數據的使用都是安全的。那麼,這樣的系統就需要提供充分的保障,從理論到工程實現的每一個階段都應該是經得起推敲、抵抗得住各種 攻擊的。不能簡單的認為只需要各方先在本地自己的數據上計算出一個模型,然後將模型結果交換一下 計算下其模型參數的平均值,就不會泄露各方的隱私數據了。現代密碼學 (Cryptography)是建立在嚴格的數學定義、計算複雜度假設和證明基礎之上的,其中 MPC (Multi-Party Computation)方向是專門研究多個參與方如何正確、安全的進行聯合計算的子領域,Rosetta、TFEncrypted等隱私 AI框架都採用了 MPC技術以提供可靠的安全性。下面我們就結合具體案例看的看下在 Rosetta中隱私數據是如何得到安全保護的。

案例

Alice,Bob和 Charley三人最近需要在他們的 AI系統中引入對數據的隱私保護能力。他們很重視安全性,所以他們想通過一個簡單的例子 —— 乘法(multiply),來驗證下隱私 AI 框架是否真正做到了隱私安全。

他們約定:Alice的輸入為 1.2345;Bob 的輸入為 5.4321;而 Charley拿到相乘的結果。他們按照 Rosetta 提供的教程,快速編寫了如下代碼(腳本名為 rosetta-mul.py):

#!/usr/bin/env python3

importlatticex.rosetta asrtt

importtensorflow astf

rtt.activate( "SecureNN")

x = tf.Variable(rtt.private_console_input( 0, shape=( 1,))) # Alice's input y = tf.Variable(rtt.private_console_input(1, shape=(1,))) # Bob's input

z = tf.multiply(x, y) # z = x * y

withtf.Session assess:

sess.run(tf.global_variables_initializer)

res = sess.run(rtt.SecureReveal(z, receive_party= 4)) # 'b0100' means Charley

print( 'z:', res)

rtt.deactivate

接著,他們各自打開一個終端,分別進行如下操作:

Alice ( P0) 在終端敲下如下命令行,並根據提示輸入自己的私有數據:

$ python ./rosetta-mul.py --party_id= 0

please input the privatedata ( floatorinteger): 1.2345

Bob ( P1) 執行同樣的操作,輸入的也是只有自己才知曉的私有數據:

$ python ./rosetta-mul.py --party_id= 1

please input the privatedata ( floatorinteger): 5.4321

Charley ( P2) 在終端敲下如下命令行,等一會兒就可以得到所期望的計算結果:

$ python ./rosetta-mul.py --party_id= 2z: [ b'6.705910']

註:

對於 Charley來說,由於沒有數據,故不會提示輸入。

Alice和 Bob的本地輸出都會是 z:[b'0.000000'], 而不會拿到正確的結果。

可以看出,Charley 拿到的最終結果與邏輯上明文結果(6.70592745)相比,誤差(0.00001745)可以忽略不計。系統的正確性得到了驗證。

如果想讓誤差更小,可以通過配置提升精度,或使用128-bit 的數據類型。

上面短短的幾行代碼,雖然結果是正確的,但是他們三人對於系統安全性方面仍有一些困惑:

  • Alice、Bob的私有輸入會不會被另外兩方知道?

  • Charley拿到的結果會不會被 Alice、 Bob知道?

  • 整個程序運行過程中,有沒有其他數據的泄漏?

  • 如果前幾問的回答都是否定的,那 Charley 又是如何得到明文?

在回答這些問題之前,為簡化描述、突出本質,我們需要簡單介紹一下MPC實際落地中常用的安全假設。

假定系統中有 3 個節點, P0/P1/P2,其中成P0/P1為數據參與方,而P2是輔助節點,用於隨機數生成。

  • 只考慮半誠實( Semi-Honest )安全模型,即三方都會遵守協議執行的流程,並且其中誠實者占多數( Honest-Majority),也就是說三個節點中只會有一個「壞人」。更為複雜的惡意( Malicious)模型等安全場景可參考其他相關論文。

  • 內部數據類型為64位無符號整型,即uint64_t

下面我們就按照 輸入--計算--輸出的順序,詳細介紹 Rosetta 中數據的表示與流動,以及所用到相關技術與算法在工程上的優化實現。

隱私數據的輸入

隱私計算問題,首先要解決的是隱私數據的輸入。

在上述案例中,是通過如下兩行代碼來完成私有數據的安全輸入的:

x = tf.Variable(rtt.private_console_input(0, shape=(1,))) # Alice's input

y = tf.Variable(rtt.private_console_input(1, shape=(1,))) # Bob's input

如代碼所示, rtt.private_console_input是 Rosetta 眾多 API 之一,Rosetta還提供了rtt.private_input,等 API,用來處理隱私數據的輸入。

這裡發生了什麼?x,y 的值會是什麼?

在進入剖析之前,先來了解一個重要的概念 —— 秘密分享。

秘密分享

什麼是 秘密分享(Secret Sharing)[1]?先來看一種簡單的兩方additive 的構造:

給定一個數 x,定義 share(x)= (x0, x1) = (x − r, r),其中r是隨機數,並且與x獨立。可以看到, x = x0 + x1 = x -r + r。原始數據x的秘密分享值(x0,x1)將會由兩個數據參與方 (P0,P1) 各自保存。

在秘密分享的方案中,所有的數據,包括中間數值都會分享在兩個參與方之間。直觀的看,參與的兩方不會得到任何的明文信息。理論上,只需要在環上支持加法和乘法,就可以進一步通過組合來支持上層各種更複雜的函數。下文我們會看到關於乘法的詳細解析,讀者可以回過頭來再看 這段話。

那工程上是如何處理的呢?假設P0有一個私有數據x,三方之間可以簡單交互一下實現:

方案1:生成一個隨機數 r,發送給 P0/P1。然後本地設置 x0 = x - r, P1 本地設置 x1 = r。此時 share(x) = (x0, x1) = (x - r, r),與上面的定義一致。

這是方案之一,後文基於這個方案進行講解。在本文最後,我們會提一下實際落地時的進一步優化方案。

回到主線,結合 方案1,我們以Alice 的輸入值x = 1.2345為例看下具體過程。

第一步,浮點數轉定點數。

對於有數據輸入的一方,需要先將真實的浮點數轉成定點數。

浮點數轉定點數:即浮點數乘以一個固定的縮放因子(scale,一般為2^k)使其變成定點數(取其整數部分,捨棄小數部分)。當最後需要還原真實的原始浮點數時,用定點數除以縮放因子即可。

我們先選定一個縮放因子,這裡取scale= 2^(18)。

經過縮放後,得到 x = 1.2345 * (1<<18) = 323616.768,取整數部分即 323616,用於後續計算。

這裡是有精度損失的,但在精度允許的範圍內,不會影響後面的計算。

第二步,生成隨機數 r。也叫掩碼( Maskingvalue),用來隱藏真實值。

p2生成一個隨機數 r,是一個 64-bit 空間的無符號整數。(如,r = fdad72ecbfbefeb9。這裡用十六進位表示,下同)

p2將r發送給P0,P1。此時,P0,P1都擁有一個相同的隨機數r了。

第三步,設置秘密分享值。

按秘密分享 方案1的定義, P0 本地設置 x0 = x - r, P1 本地設置 x1 = r。所以有:

P0:x0= 4f020-fdad72ecbfbefeb9 = 2528d134045f167

P1:x1= fdad72ecbfbefeb9

4f020是 323616 的十六進位表示。

如果計算結果大於 64 bit 的空間範圍,需要對結果取模(64 位空間)。下同。

至此,我們獲得了關於x的分享值,share(x)=(x0,x1)=(x-r,r)=(2528d134045f167,fdad72ecbfbefeb9)

感興趣的讀者朋友可以驗證一下(x0+x1)mod 。

同理,我們對Bob的輸入值進行一樣的處理。

上面三步,其實就是 private_console_input 的工作機制與過程。經過處理後,各方本地都存儲著如下值:

P0 P1 P2
X0

X1

fdad72ecbfbefeb9

X2

0

Y0

Y1

f271e642f5c29328

Y2

0

我們用 Xi,Yi 表示 X,Y 在 Pi的分享值。(下同)

P2 為何是0呢?在本方案中 P2 作為一個輔助節點,不參與真正的邏輯計算。

我們可以看到,在處理隱私數據輸入的整個過程中, P0無法知道 Y 值, P1 無法知道 X 值, P2 無法知道 X 或 Y 值。

最後,我們總結一下這三個主要階段:

密文上的協同計算

這是計算的核心。

上一步,我們 保證了輸入的安全,沒有信息的泄漏,各方無法單獨拿到其他節點的私有輸入。接下來,看一下計算的代碼,只有一行:

z = tf.multiply(x, y) # z = x * y

在這個計算的過程中發生了什麼?下面結合乘法 (Multiply)運算元原理進行實例講解。

Multiply 運算元原理

乘法相對較為複雜,我們結合經典的 Beaver Triple方法[2]加以介紹。該方法是由密碼學家 Donald Beaver在 1991 年提出,主要思想是通過乘法。協議基本原理如下:

輸入:P0 擁有 X,Y的秘密分享值 X0,Y0;P1擁有X,Y的秘密分享值 X1,Y1。

這裡有 share(X) = (X0, X1),share(Y) = (Y0, Y1)。在此案例中,這裡的輸入,就對接上一節所述的"隱私輸入"的輸出結果。

計算步驟:1.P2 本地生成一組隨機數A,B,C,且滿足 C = A*B。 A,B,C 的生成步驟: P2 隨機生成 A0,A1,B0,B1,C0,令 A = A0 + A1,B = B0 + B1,得到C= A*B, C1 = C - C0。 其中AI,BI,CI 是 A,B,C 的分享值。 這些都是在 P2 本地完成的。這也就是 P2 做為輔助節點的作用(用於隨機數生成)。

這裡 A,B,C 一般被稱為三元組(Beaver'sTriple)。

比如,某次生成的隨機數如下:

A0

2373edde1a0e5dcd

A1

ad483b77e4e5db41

B0

d81a4646be1c0cb8

B1

78222aff7dcc1ae8

C0

62a175e20f9a1542

C1

483498026c6ab57e

感興趣的讀者朋友可以驗證一下。如 A = A0 + A1 =2373eddela0e5dcd + ad483b77e4e5db41 = d0bc2955fef4390e。這個 A 是個隨機數。

2.將上一步生成的隨機數的秘密分享值分別發送給P0,P1。

即將A0,B0,C0發送給P0;將A1,B1,C1發送給P1。

此時, P0,P1擁有如下值:

P0

P1

A0

2373edde1a0e5dcd

A1

ad483b77e4e5db41

B0

d81a4646be1c0cb8

B1

78222aff7dcc1ae8

C0

62a175e20f9a1542

C1

483498026c6ab57e

3.P0 計算 E0 和 F0;P1 計算 E1 和 F1。並交換 Ei,Fi。

P0 本地計算 E0 = X0 - A0, F0 = Y0 - B0。

P1 本地計算 E1= X1 - A1, F1 = Y1 - B1。

此時, P0,P1擁有如下值:

P0

P1

E0

dede9f352637939a

E1

50653774dad92378

F0

3573d3764c371a98

F1

7a4fbb4377f67840

交 換 Ei,Fi。

P0將E0,F0發送給P1;P1將E1,F1發送給P0。此時,P0,P1都擁有E0,F0,E1,F1。

4.本地計算 得到 E和 F。

P0,P1 各自本地計算 E = E0 + E1, F= F0 + F1。

P0

P1

E

2f43d6aa0110b712

E

2f43d6aa0110b712

F

afc38eb9c42d92d8

F

afc38eb9c42d92d8

5.本地計算 Z0;P1本地計算 Z1。

現在, P0 已經擁有 A0,B0,C0,E,F;P1已經擁有 A1,B1,C1,E,F。有了這些就可以計算出 Z= X*Y 的秘密分享值 Z0,Z1了。即:

P0 本地計算 Z0 = E * B0 + A0 * F+ C0;

P1 本地計算 Z1 = E * B1 + A1 * F+ C1 + E * F。

P0

P1

Z0

1db35d14c12a

Z1

ffffe24ca30611b0

正確性可以通過以下恆等式加以驗證:

輸出:P0,P1 分別持有 Z = X * Y的秘密分享值 Z0,Z1。

我們可以看到, 從輸入到計算再到輸出,整個過程中,沒有泄漏任何隱私數據。

整個運算元計算結束時,P0 單獨擁有X0,Y0,A0,B0,C0,E0,F0,E1,F1,E,F,Z0,P1 單獨擁有X1,Y1,A1,B1,C1,E0,F0,E1,F1,E,F,Z1,P2 單獨擁有 A0,B0,C0,A1,B1,C1,三方都無法單獨得到 X 或 Y 或 Z。

最後,我們總結一下(1~5 對應著上面的步驟):

獲取明文結果

輸入到計算再到輸出,各節點只能看到本地所單獨擁有的秘密分享值(一些毫無規律的64位隨機 數),從上文也可以看到,節點是無法獨自得到任何隱私數據的。那麼,當計算結束後,如果想得到結果的明文,怎麼獲取呢?

Rosetta 提供了一個恢復明文的接口,使用很簡單。

res = sess.run(rtt.SecureReveal(z, receive_party=4)) # 'b0100' means Charley

print('z:', res)

那這個 rtt.SecureReveal 是如何工作的呢?

其實非常簡單:如果本方想要知道明文,只需要對方把他的秘密分享值發給我,然後本地相加即可。

比如,上一節結尾處,我們知道了各方(P0/P1/P2)的分享值如下:

P0 P1 P2

Z0

1db35d14c12a

Z1

ffffe24ca30611b0

Z2

0

結合實例,Charley(P2)想要獲取結果明文,那麼,P0,P1將各自的分享值Z0,Z1發給P2,然後P2本地相加即可。即: 1db35d14c12a + ffffe24ca30611b0 = 1ad2da(1757914)。我們將此值進一步再轉換為浮點數,就可以得到我們想要的用戶態的明文值了:1757914 / (1 << 18)=6.7059097

效率優化

上面介紹的 秘密分享 與 multiply 運算元 都是基於最基本的算法原理,在時間上和通信上的開銷還是比較大的,在實際工程實現中,還可以進一步進行優化以提升性能。在介紹優化方案之前,先了解一下什麼是 PRF[3]?

PRF[3],Pseudo-Random Function。簡單來說,即給定一個隨機種子 key,一個計數器 counter, 執行 PRF(key, counter) ,會得到一個相同的隨機數。

補充說明一下。例如, P0,P1 執行 PRF(key01,counter01),會產生一個相同的隨機數。這裡的 key01, counter01 對於的 P0,P1 來說是一致的。程序會維護這兩個值,對使用者來說是透明

關於秘密分享

來看看優化版本(假設:P0有一個私有數據x)。

方案2(優化版):P0,P1 使用 PRF(Key01,counter) 本地同時生成一個相同的隨機數r。然後P0本地設置x0=x-r,P1本地設置x1=r。此時 share(x) = (x0,x1)x=(x = r.r),與定義一致。此版本無需 P2 的參與。沒有通信開銷。

目前 Rosetta 開源版本中使用的正是此方案。

方案3(優化版):P0 設置 x0 = x-r, P1 設置 X1 = 0 即可。此時 share(x) = (x, 0)。此版本無需 P2 的參與。沒有通信開銷,也沒有計算開銷。

上述各個版本(包括方案1),都是可行且安全的。可以看到P1/P2並不知道 P0 的原始輸入值。

關於 Multiply 運算元

Multiply 運算元中輸入,輸出部分沒有變化,主要是計算步驟中的第1步與第2步有些許變化,以 減少通信量。這裡也只描述這兩步,其餘與前文相同。

在上文的描述中,我們知道 P2 生成三元組後,需要將其分享值發送給P0,P1。當我們有了 PRF 後,可以這麼做:

  1. P0,P2 使用PRF(Key02,counter02) 同時生成 A0,B0,C0;P0,P1使用 RF(Key12,counter12) 同時生成 A1,B1。
  2. 然後,P2令A=A0+A1,B=B0+B1,得到C=A*B,C1=C-C0。P2將發送給P1。P2的任務完成。

目前 Rosetta 開源版本中使用的是此方案。

相比於原始版本,優化版本只需要發送 C1,不用再發送 A0,A1,B0,B1,C0。

在 Rosetta中,我們還針對具體的各個不同的運算元進行了一系列的算法、工程優化,歡迎感興趣的讀者來進一步了解。

小結

安全性是隱私 AI框架的根本,在本篇文章中,我們結合隱私數據輸入的處理和密文上乘法的實現,介紹了「隨機數」 形式的密文是如何在多方之間流動,同時「神奇」的仍能保證計算邏輯的正確性的。我們這裡對於安全性的說明是直觀上的描述,而實際上,這些算法的安全性都是有嚴格數學證明的。感興趣的讀 者可以進一步去探索相關的論文。

Rosetta 將持續集成安全可靠的密碼學算法協議作為「隱私計算引擎」到框架後端中,也歡迎廣大開發者參與到隱私AI 的生態建設中來。

作者簡介:

Rosetta技術團隊,⼀群專注於技術、玩轉算法、追求⾼效的⼯程師。Rosetta是⼀款基於主流深度學習框架TensorFlow 的隱私AI框架,作為矩陣元公司⼤規模商業落地的重要引擎,它承載和結合了隱私計算、區塊鏈和AI三種典型技術。我們專門為AI從業者撰寫了隱私計算+AI從技術到實戰的全教程,力圖讓相關行業從業者0難度一鍵掌握隱私計算技術的用法

參考文獻

[1] 秘密共享,

https://en.wikipedia.org/wiki/Secret_sharing

[2] Beaver,Donald."Efficientmultipartyprotocolsusingcircuitrandomization."Annual InternationalCryptologyConference.Springer,Berlin,Heidelberg,1991.

[3] PRF的一個簡單介紹

https://crypto.stanford.edu/pbc/notes/crypto/prf.html

文章來源: https://twgreatdaily.com/zh-cn/t5dTknUB2uKmW_kOd2v9.html










CSDN湘苗培優

2020-12-24