同態加密與 Paillier/RSA


白話同態加密

雖然同態加密即使現在聽起來也很陌生,但是其實這個概念來自 1978 年,由 RSA 算法的發明者的 R 和 A 以及 Dertouzos 提出。具體的定義如下:

A way to delegate processing of your data, without giving away access to it.

翻譯成人話就是傳統的加密方法和數據處理方法是互斥的,比如我需要計算兩個數字的和(1 和 2),如果加密了之后,就無法對密文進行計算;如果想要進行計算,就必須知道這兩個數字是 1 和 2。如果數據擁有方和計算方是同一方,那么知道 1 和 2 沒啥問題;但如果數據擁有方和計算方並非同一方,並且數據擁有方還不想讓計算方知道這兩個數字是 1 和 2,這個時候就是同態加密發揮作用的時候了。

同態加密將數據的處理和數據本身解耦了:計算方拿到的是加密之后的數字,但是依然可以相加,相加之后把結果告訴數據擁有方,最終數據擁有方解密就可以知道最終的計算結果。

同態加密的這個特點使得雲服務廠商非常在意,因為這一舉解決了用戶擔心雲服務廠商竊取數據的擔心(因為加密了除了計算沒法做其他事情),並且因為加密計算本身耗費更多計算資源,還可以變相提高營收。

總結一下:同態加密使得數據可以在加密的狀態下進行計算,至於支持什么計算,如何進行計算,我們接下來繼續講。

定義同態加密

先假設一個場景:我想要處理一大批數據,如果在本地用明文要 100 個小時,這個時間太長了,所以我需要借助雲計算的力量。但是因為這批數據很敏感,包括了我從小到大每一分每一秒的心情和各類身體指標,我不希望雲計算平台能夠直接獲取到,這樣我就感覺自己沒有隱私了,所以我需要使用同態加密,讓雲計算平台在加密的情況下計算(假設只需要 1 個小時),我拿到加密計算的結果再解密得到真實結果。那么問題來了,這個過程需要幾步?

  1. 我在本地生成用來加密數據的 Key
  2. 我用 Key 和 Encrypt 算法加密本地的數據,記為 EncData = Encrypt(Key, Data)
  3. 我告訴雲平台需要如何計算數據,記為函數 F()
  4. 雲平台進行計算 Evaluate,即 Evaluate(F(), EncData) = Encrypt(Key, F(Data)),記為 ProEncData
  5. 雲平台將 ProEncData 發回給我
  6. 我用密鑰進行解密 Decrypt,得到 F(Data) = Decrypt(Key, ProEncData),也就是最終結果

在以上六個步驟中,至少有四個函數是必須的:

  1. 生成密鑰的函數:本地執行,生成密鑰
  2. Encrypt 函數:本地執行,加密數據,加密之后的數據不會暴露源數據的信息
  3. Evaluate 函數:用來執行用戶給定的計算函數 F(),是唯一由雲平台運行的函數
  4. Decrypt 函數:本地執行,解密數據

根據支持的 F() 的不同,同態加密分成了兩類:

  1. Fully Homomorphic Encryption, FHE:這種方式下,任何 F() 都可以,只要這個算法能夠被計算機實現即可。不過這個計算開銷非常大,目前暫無實際應用。注:Gentry 在 2009 年給出過一個實現
  2. Somewhat Homomorphic Encryption, SWHE:這種方式下,只支持某些特定的F()(比如只支持加法/乘法,並且只能執行有限次數)。這個方案有比較大的限制,但也因此計算開銷較小,已經可以在實際中使用
    1. 乘法:RSA, Elgamal
    2. 加法:Paillier

接下來我們會詳細看看 Paillier 算法和 RSA 算法,對加法同態和乘法同態有更加深入的理解。

Paillier 算法

因為有了前面的分析,我們知道一個同態加密算法需要四個函數:密鑰生成、加密、解密、同態運算,針對 Paillier 算法,我們一項一項來看一下。

這里我們也准備了不同語言版本的實例:

  1. Python 版
  2. Golang 版

注:實際實現的過程中,一般不會直接實現 gcd 和 lcm 函數,而是采用一些替代的計算,具體參考上面鏈接中的源碼。

密鑰生成

總共有如下幾個步驟:

  1. 隨機選擇兩個質數 p 和 q 滿足 \(|p|=|q|=\tau\),這個條件保證了 p 和 q 的長度相等。
  2. 計算 \(N=pq\)\(\lambda=lcm(p-1,q-1)\),注:lcm 表示最小公倍數
  3. 隨機選擇 \(g\in Z_{N^2}^*\),滿足 \(gcd(L(g^\lambda mod N^2),N)=1\),注:gcd 表示最大公約數;Z 表示整數,下標表示該整數集合里有多少個元素;\(L(x)=\frac{x-1}{N}\)
  4. 公鑰為 \((N,g)\)
  5. 私鑰為 \(\lambda\)

加密

對於任意整數 \(m\in Z_N\),任意選擇隨機數 \(r\in Z_N^*\),密文 \(C=E(m)=g^mr^NmodN^2\)

解密

對於密文 \(C\in Z_{N^2}^*\),解密得到明文 m 的計算如下:

加法同態

對於任意明文 \(m_1, m_2\in Z_N\),假設 \(E(m_1)=g^{m_1}r_1^NmodN^2\)\(E(m_2)=g^{m_2}r_2^NmodN^2\),有

\[E(m_1)E(m_2)=g^{m_1+m_2}(r_1r_2)^NmodN^2=E(m_1+m_2modN) \]

這個性質表明 Paillier 加密方案具有加法同態性。

RSA 算法

RSA 算法作為最為知名的非對稱加密算法,想必大家都有一定的了解,這里我們仍然以針對密鑰生成、加密、解密、同態運算四個步驟,一項一項來看一下。同樣可以參考下面的代碼實例:

  1. Python 版

密鑰生成

  1. 隨機找兩個質數 P 和 Q,越大越安全,並計算乘積 \(n=P*Q\)。P 和 Q 的乘積的二進制位數代表 RSA 加密的位數,一般來說都要有 1024 或 2048 位。
  2. 計算 n 的歐拉函數 \(\phi(n)\),表示在小於等於 n 的正整數中,與 n 構成互質關系的數的個數。比如 1~8 中,和 8 互質的有 1,3,5,7,所以 \(\phi(8)=4\),如果 p 和 q 為質數,那么他們的乘積的歐拉函數有一個特殊的性質,公式為 \(\phi(n)=\phi(P*Q)=\phi(P-1)\phi(Q-1)=(P-1)(Q-1)\)
  3. 選取 e,要大於 1 小於 \(\phi(n)\),並且 e 與 \(\phi(n)\) 要互質
  4. 計算出一個整數 d,使得 \((ed-1)\ \%\ \phi(n)=0\),即 \(e*d\) 除以 \(\phi(n)\) 的余數為 1,實際上轉化為找到二元一次方程 \(ed+k\phi(n)=1\) 的一組解(求 d 和 k),具體使用的是擴展歐幾里得算法

於是我們可以得到:

  • 公鑰 (n, e)
  • 私鑰 (n, d)

在這樣的條件下,如果想要根據 n 和 e 算出 d,就只能暴力破解,位數越長,玻璃破解時間越長。

加密

我們現在有個這么幾個關鍵的數值:n, e, d。要使用公鑰 (n, e) 加密,首先要求被加密的數字必須是整數且小於 n(如果是字符串,可以逐個取 ascii 碼或 unicode 值,並且中間用非數字和字母分割即可)。假設我們需要加密的數字是 A,則加密之后的 B 為(為了區別使用大寫):

如果沒有 d,那么是很難從 B 中恢復 A 的。

解密

如果我們擁有私鑰 (n, d),那么對於 B,就可以通過下面的公式計算出 A:

乘法同態

相對 Paillier 來說還要更加簡單一些,我們只要把兩個加密后的數字相乘即可,代碼片段如下:

print('接下來加密計算 2 x 20')
print('加密 2')
enc1 = rsa.core.encrypt_int(2, public_key.e, public_key.n)
print(enc1)
print('加密 20') # 40471062776583530669631608186743860028386032505372124150562694293213549812024
enc2 = rsa.core.encrypt_int(20, public_key.e, public_key.n)
print(enc2) # 16915103439566807805446086181091224947678993169521653470724152014464992293178

print('相乘')
result = enc1 * enc2
print(result) # 684572213175112282577113686759405066981454950839007710126450052851088805616753069318980764721622690261112227625923822693220128510206043466290770597572272

print('解密結果')
decrypt_result = rsa.core.decrypt_int(result, private_key.d, public_key.n)
print(decrypt_result) # 40

復制

寫在最后

這一講我們結合實際的例子熟悉了同態加密,接下來我們會繼續介紹聯邦學習相關的底層技術,讓大家知其然更知其所以然。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM