代理重加密原理與實踐

warm3snow發表於2024-04-15

目錄
  • 主頁
  • 引言
  • 代理重加密定義
  • 代理重加密原理
    • 基於公鑰演算法的PRE方案
      • 原理解析
    • 基於對稱演算法的PRE方案
      • 原理解析
  • 實踐&應用
  • 總結
  • 參考資料

主頁

  • 個人微信公眾號:密碼應用技術實戰
  • 個人部落格園首頁:https://www.cnblogs.com/informatics/

引言

2022年12月,人工智慧迎來了一件大事,OpenAI的ChatGPT橫空誕生,成為了現象級產品。如果說算力是人工智慧的發動機,那麼資料則是人工智慧的Gasoline

網際網路平臺的封閉導致了資訊孤島, 從而降低了資料公開流通,和資料要素價值,資料流通是實現資料社會化利用和實現資料資源價值的必然路徑。隨著國內[資料二十條][資料二十條]政策落地,支援依法依規在場內場外採取開放、共享、交換、交易等方式流通資料,為資料共享提供了法律和政策指導,推動了資料開放、流通和共享的發展。

資料二十條對資料安全提出了一定的要求:

  • 資料安全保護:在資料共享過程中,必須採取適當的安全措施,保護資料的機密性、完整性和可用性,防止未經授權的訪問、使用和洩露。
  • 資料訪問和使用許可權:資料共享應該建立明確的訪問和使用許可權,確保只有授權的使用者可以訪問和使用資料,並限制資料的濫用和不當使用。
  • 資料共享協議和契約:資料共享應該建立在明確的協議和契約基礎上,明確各方的權利和責任,確保資料共享的合法性和可持續性。

本文將要介紹的技術主要針對資料安全保護,在資料共享過程中保證資料的機密性

代理重加密定義

代理重加密(Proxy Re-encryption, 簡稱PRE)方案是一種密碼系統,允許第三方(代理)修改為某一方(資料提供方)加密的密文,以便其他方(資料使用方) 能夠解密該密文。

PRE方案主要有以下特點:

  • 委託(Delegation)- 允許訊息接收者(金鑰持有者)基於他的金鑰和被委託使用者的金鑰生成一個重加密金鑰。代理將使用這個重加密金鑰作為輸入,透過重加密函式將密文轉換為被委託使用者的金鑰。非對稱代理重加密方案有雙向和單向兩種型別。
  • 傳遞性(Transitivity)- 傳遞性代理重加密方案允許對密文進行無限次的重加密。例如,一個密文可以從Bob重新加密為Charlie,然後再從Charlie重新加密為David,依此類推。非傳遞性方案只允許對給定密文進行一次(或有限次數)的重加密。大多數已知的方案都是雙向和傳遞性的。目前,唯一已知的單向傳遞性代理重加密是透過同態加密實現的。

PRE方案常用於雲環境下的資料安全共享。

無PRE資料安全共享

在下圖中,Alice為資料提供方,Bob為資料使用方,Alice和Bob分別維護自己的加密公私鑰

image

  • Alice加密資料上傳到雲端儲存
  • 當Alice需要向Bob共享資料時,需要獲取Bob的加密公鑰
  • Alice使用Bob的加密公鑰對資料進行加密,並上傳到雲端儲存,如:密文資料 for Bob
  • Bob下載密文資料,並本地解密獲取明文資料

使用PRE進行資料共享

image

  • Alice將資料加密,並將加密後的資料上傳到雲端儲存
  • 當Alice需要向Bob共享資料時,需要獲取Bob的加密公鑰
  • Alice生成重加密金鑰,併傳送給代理重加密服務(Proxy Re-encryption Service)
  • 代理重加密服務基於重加密金鑰和步驟1中的加密資料,生成重加密密文資料
  • Bob下載密文資料,並使用本地私鑰進行解密,獲取明文
對比 \ 資料共享 不使用PRE 使用PRE
效能 低,需要資料提供者進行本地加密,
效能依賴於本地算力
高,代理重加密服務部署在雲端,
可以藉助雲端計算能力
易用性 中,對於資料提供者和資料使用者來說,
難度與不適用PRE相差不大
複雜度 低,基於基礎密碼演算法,
複雜度相對較低
依賴於PRE方案和Proxy服務,
流程較為複雜,有一定的實現和運維難度
安全性 較高,雲廠商和資料使用方存在合謀風險,但攻擊有限

代理重加密原理

基於公鑰演算法的PRE方案

代理重加密方案涉及五元組<KeyGen, Encrypt, ReGenKey, ReEncrypt, Decrypt>

  • KeyGen:本地金鑰生成函式
  • Encrypt: 資料加密函式
  • ReGenKey:重加密金鑰生成函式
  • ReEncrypt:資料重加密函式
  • Decrypt:資料解密函式

image

  • 資料提供方Alice和資料使用方Bob使用KeyGen函式,分別生成本地公私鑰
  • Alice使用Encrypt函式對明文資訊M進行加密,並將密文資料C上傳到代理重加密服務Proxy
  • 資料使用方提供加密公鑰,併傳送給Alice
  • Alice使用ReGenKey函式,生成針對Bob的重加密金鑰,併傳送給Proxy
  • Proxy使用ReEncrypt,並基於密文資料C和重加密金鑰,生成新的密文資料:重加密密文資料
  • Bob獲取重加密密文資料,並使用本地私鑰進行解密

原理解析

  1. 初始化步驟(金鑰生成&準備待共享資料)

    • Alice生成本地公私鑰: \((pk_A, sk_A), pk_A = g^{sk_A}\)

    • 待共享資料 \(M\)

    • Bob公私鑰: \((pk_B, sk_B), pk_B = g^{sk_B}\)

  2. Alice加密資料

    • 選取隨機數\(r\)
    • 計算密文二元組:\(C = (C_1, C_2) = (g^r, M.{pk_A}^r)\)
    • \((pk_A, C)\)傳送給Proxy
  3. Alice生成重加密金鑰

    • 獲取Bob公鑰\(pk_B\)
    • 生成重加密金鑰:$rk = \frac{sk_A}{H({pk_B}^{sk_A})} $
    • \(rk\)傳送給Proxy
  4. Proxy代理重加密

    • 從Alice收到的資料有\((pk_A, C, rk)\)
      • Alice公鑰\(pk_A\)
      • 密文資料:\(C\)
      • 重加密金鑰\(rk\)
    • 計算密文二元組:$C^{'} = (C{_1}^{'}, C{_2}^{'}) = (C{_1}^{rk}, C2) $
  5. Bob解密資料:

    • Bob從Proxy接收到密文資料:\(C^{'}\)
    • 計算明文:\(M^{'} = \frac{C{_2}^{'}}{({C{_1}^{'}})^{H({pk_A}^{sk_B})}}\)
    • 這裡的\(M' = M\)即為待共享資料
    • 正確性驗證:
      • 計算\(M'\): \(M^{'} = \frac{C{_2}^{'}}{({C{_1}^{'}})^{H({pk_A}^{sk_B})}} = \frac{C_2}{C1^{rk.H({pk_A}^{sk_B})}} =\frac{C_2}{C1^{sk_A}} = \frac{M.{pk_A}^r}{g^{r.sk_A}} = \frac{M.{g^{{sk_A}.r}}}{g^{r.sk_A}}\)
      • 分子分母存在公約數: \(g^{{sk_A}.r} = g^{r.sk_A}\)
      • 約去公約數後,得到:\(M' = M\)

基於對稱演算法的PRE方案

基於對稱演算法的PRE方案結合了對稱演算法和非對稱演算法兩種加密體制的優點。使用對稱演算法對共享明文資料加密,保證加密效能;使用非對稱演算法對對稱金鑰進行保護,保證金鑰協商。

基於對稱演算法的PRE方案涉及8元組如下:

<SymKeyGen, SymEncrypt, SymDecrypt, KeyGen, Encrypt, ReGenKey, ReEncrypt, Decrypt>

  • KeyGen, Encrypt, ReGenKey, ReEncrypt, Decrypt與前文同,不再贅述
  • SymKeyGen:對稱演算法金鑰生成函式
  • SymEncrypt:對稱加密函式
  • SymDecrypt:對稱機密函式

image

最佳化版代理重加密關鍵流程如下:

  • 資料提供方和資料使用方使用KeyGen函式,分別生成本地公私鑰。同時Alice生成對稱金鑰(隨機數)
  • Alice使用Encrypt函式對明文資訊M進行加密,並將密文資料C上傳到代理重加密服務Proxy
  • 資料使用方提供加密公鑰,併傳送給Alice
  • Alice使用ReGenKey函式,生成針對Bob的重加密金鑰,併傳送給Proxy
  • Proxy使用ReEncrypt,並基於密文資料C和重加密金鑰,生成新的密文資料:重加密密文資料
  • Bob獲取重加密密文資料,並使用本地私鑰進行解密

原理解析

  1. 初始化步驟(金鑰生成&準備待共享資料)

    • Alice生成本地公私鑰 \((pk_A, sk_A), pk_A = g^{sk_A}\)

    • 待共享資料 \(M\)

    • Bob公私鑰: \((pk_B, sk_B), pk_B = g^{sk_B}\)

  2. Alice加密資料

    • 選取隨機數\((e,u,r)\), \(E = g^e, U = g^u\)
    • 計算s,\(s = u + r.H(E||V)\) ,這裡的\(||\)為位元組陣列拼接
    • 生成對稱金鑰:\(K = F({pk_A}^{e+u})\), 其中\(F\)為轉換函式,可以將橢圓曲線的點對映為固定長度的位元組資料(如SM4金鑰長度為16)
    • 使用對稱演算法加密資料: \(C = SymEncrypt(M, K)\)
    • \(C\), ${C_K}=({E, U, s}) $傳送給Proxy
  3. Alice生成重加密金鑰

    • 生成隨機數\(b, B = g^b\) 並獲取Bob公開的公鑰\(pk_B\)
    • 計算d,$d = Hash(B || pk_B || {pk_B}^{sk_A}) $
    • 生成重加密金鑰:\(rk = {sk_A}.{d^{-1}}\)
    • \(({rk, B})\)傳送給Proxy
  4. Proxy代理重加密

    • 從Alice收到的資料有\({C, C_K,rk}, Proxy重加密只需要\)
    • 計算\(E', V'\), \(E' = E^{rk}, V' = V^{rk}\)
    • 生成\(C{_K}^{} = (E', V', s)\)
    • \((B, C{_K}^{}, C)\) 傳送給Bob(或由Bob下載)
  5. Bob解密資料:

    • 計算d:\(d = Hash(B || pk_B || {pk_A}^{sk_B})\)
    • 透過計算獲取對稱金鑰K, $ K = F(E'.V')^d$
    • 解密獲取M,\(M = SymDecrypt(C, K)\)

實踐&應用

下面我們以基於對稱演算法的PRE方案為例進行程式碼介紹,程式碼採用golang語言,其中非對稱演算法使用了國密sm2, 雜湊演算法為sm3.

  1. 下載PRE密碼包
# 下載practical-crypto
➜  wkdir git clone https://github.com/warm3snow/practical-crypto.git
正克隆到 'practical-crypto'...
remote: Enumerating objects: 873, done.
remote: Counting objects: 100% (383/383), done.
remote: Compressing objects: 100% (262/262), done.
接收物件中: 100% (873/873), 8.31 MiB | 28.00 KiB/s, 完成.
處理 delta 中: 100% (382/382), 完成.

關鍵函式定義如下:

func KeyGen() (*sm2.PrivateKey, *sm2.PublicKey, error) {}
func Encrypt(r *big.Int, pk *sm2.PublicKey, m []byte) ([]byte, error) {}
func ReGenKey(r *big.Int, pkA, pkB *sm2.PublicKey, alpha []byte) *big.Int {}
func ReEncrypt(cipher []byte, skAB *big.Int) ([]byte, error) {
func Decrypt(cipher []byte, skB *sm2.PrivateKey, alpha []byte) ([]byte, error) {}
  1. 執行PRE程式
# 切換到PRE程式碼目錄
➜  wkdir cd practical-crypto/advanced_crypto/pre

# 執行測試程式碼
➜  pre git:(master) go test -v -test.run=TestPre
=== RUN   TestPre
    pre_test.go:21: Test PRE
    pre_test.go:22: 待共享資料明文 M: hello PRE!
    pre_test.go:37: Alice加密資料: 2cbfa60e52a5b53dd34aa21baba69f51
    pre_test.go:38: Alice加密資料 Capsule: 7b2245223a7b224375727665223a6e756c6c2c2258223a31363331383730353633373430343430363339353132303230343032383735373534393136353032363536373030343138343330373938333439363839353738313232373530303832323635352c2259223a37363931333331323931363136373736303938383735343938343033323532303238353837333639333739383636323832363535333239303230363235373833333230353334343239383335397d2c2256223a7b224375727665223a6e756c6c2c2258223a31373738393037343035363836313239373636373536393633383530323732373833313735343633353131333032333033343635303631383136393231333338393233313131383531363238332c2259223a35393434353333323435363535353536393231363934353637393130373738353236353332343932333734383834373337363436323737383237383232333435303831373833353436323933337d2c2253223a3231333636373534353236393537303931373634303236363339363735363830353833343830313132383633373134343633363732313539343330383734393139353734363737313737343132363136303433333231333634353933343630323438393639383830333633383530323935373536303935393632343832333534353031303933393637363937333034343030393735303339353133363436353430363834353334313836303236337d
ReGenKey d: 86776578942220434879492507132922592428947784438620508923301187582598416130155
ReGenKey dInv: 97733987058783820900214716828113790131983940598302895601690744252191835809539
    pre_test.go:47: Proxy重加密資料 Capsule': 7b2245223a7b224375727665223a6e756c6c2c2258223a3131343930313439353438343139353332343539323435393339303933313231353934383630343730313733333139333739303433343931343933323030313938353232373037353130393132302c2259223a3131333437343133373131303233373930363930363935353431303432313535333833303930353332353239383139313338363139313830373638393039383231343530373536333632313733357d2c2256223a7b224375727665223a6e756c6c2c2258223a32343633323734373333313336363735313335393535353138303334373838303032343637333239323431393532393430373037303431303030303237303934393635323439313438363638302c2259223a37393935323734323930383737373433303930383232343331383730323931353234303038363038343130343131373039393937353331363034303532393638373234363332303336363835347d2c2253223a3231333636373534353236393537303931373634303236363339363735363830353833343830313132383633373134343633363732313539343330383734393139353734363737313737343132363136303433333231333634353933343630323438393639383830333633383530323935373536303935393632343832333534353031303933393637363937333034343030393735303339353133363436353430363834353334313836303236337d
Decrypt d: 86776578942220434879492507132922592428947784438620508923301187582598416130155
    pre_test.go:53: Bob解密資料 M: 492997048111525925111073
    pre_test.go:54: 明文Msg: 492997048111525925111073
    pre_test.go:58: Bob解密資料 M: hello PRE!
--- PASS: TestPre (0.01s)
PASS
ok  	github.com/warm3snow/practical-crypto/advanced_crypto/pre	0.403s

總結

本文從整體上介紹了代理重加密PRE的基本定義、方案原理、並在最後透過golang程式碼實現了代理重加密方案(非最佳化版),希望讀著對代理重加密有個初步的認識。

宣告:文中提到的程式碼實現僅用於技術交流和基本演示,不推薦在生產環境中使用,如使用請自擔風險!!!

參考資料

  • Proxy Re-encryption: https://en.wikipedia.org/wiki/Proxy_re-encryption
  • Improved Proxy Re-encryption Schemes with Applications to Secure Distributed Storage
  • How proxy re-encryption works - layman perspective

相關文章