祕密共享原理與實現

畢業設計裏用到了一些密碼學的知識,在博客做個記錄。

祕密共享

祕密共享(Secret Sharing),如其名,是一種用來共享祕密的技術。理解這個技術,首先需要把意義搞清楚,然後瞭解技術實現原理,最後用工具實現一個demo。

共享的意義

一個祕密信息,必然有其最初的持有者,也即發佈者。發佈者具有祕密的使用權和共享權,即他有權利將祕密分享給別人。但這裏存在一個問題:如何保證這個共享過程是安全的?
傳統的方法,是加密。如對稱加密,雙方用約定的密鑰進行加密解密通信——但也有一個問題:如何安全傳遞密鑰?總是需要有一個最初“絕對安全”的信道。非對稱加密解決了這個矛盾,發佈方自己生成公私鑰對,通過公開公鑰,用私鑰加密、公鑰解密,無需事先約定。
非對稱加密解決了絕大部分加密的問題,目前廣泛應用的RSA就是明證。但其實它依賴了一個潛在假設(雖然這個假設很接近現實):公開環境是一個誠實信道,它不會篡改發佈的共享信息。否則,中間人攻擊就會破獲祕密。
假設這樣一個場景:發佈者A與接受者B之間存在N條獨立信道,在不清楚各信道信任度和穩定度的情況下,A如何將信息發送給B?祕密共享應運而生。它通過某種方法將祕密拆分,從N個信道同時發送,即使有信道存在惡意者,也無法恢復祕密。
在實際應用中,祕密共享常用於密鑰的分佈式存儲,將一個密鑰拆分後多地存儲,分散風險,等到需要用的時候再聚合到一起。

共享原理

形式化定義如下:
S(s,t,n)s0,s1,...,snS(s,t,n)\rightarrow{\langle s_0\rangle,\langle s_1\rangle,...,\langle s_n\rangle}
其中s表示需要拆分的祕密,t表示恢復門限,n爲拆分數目。
存在恢複函數RR,對於任意mtm\ge tR(s0,s1,...,sm)sR(\langle s_0\rangle,\langle s_1\rangle,...,\langle s_m\rangle)\rightarrow s

shamir算法

shamir是一種祕密共享的實現1,利用了拉格朗日插值公式2。詳細原理見參考文獻。
下面補充一個shamir算法的有用的性質:加同態。
已知已有兩個用於祕密共享的多項式f(x)=a0+a1x+..+anxnf(x)=a_0+a_1x+..+a_nx^ng(x)=b0+b1x+..+bnxng(x)=b_0+b_1x+..+b_nx^n以及素數pp。通過祕密共享分享的分片形式是(x,f(x)mod p)(x, f(x)mod\ p)(x,g(x)mod p)(x, g(x)mod\ p)
將分片中的多項式結果求和,得到(x,f(x)+g(x)mod   p)(x, f(x)+g(x)\mod\ p)
根據shamir算法中的定義,a0a_0 b0b_0是原祕密。因此通過恢復算法對求和後的分片進行恢復,將會得到a0+b0a_0+b_0。這就實現了祕密求和。在雙方求和的情況下,沒有意義,但在參與者數目大於等於3時,就會有用。
下面的demo將會演示這個過程。

實現應用

github上有對shamir算法的實現3,這裏直接借用實現一個拆分求和後恢復的過程。

from secretsharing import secret_int_to_points, points_to_secret_int
from secretsharing import primes
p = primes.get_large_enough_prime([100000])

n_frac = 3
n_rcvr = 2

// 拆分
def ss(n):
	return secret_int_to_points(n, n_rcvr, n_frac, p)

// 恢復
def recover(s):
	return points_to_secret_int(s, p)

// 對祕密求和
def secret_sum(s1, s2):
	return [(i+1, (s1[i][1]+s2[i][1])%p) for i in range(3)]



>>> sh = seret_sum(ss(123),ss(234))
>>> recover(sh)
357

後記

本來寫了一堆原理,結果沒保存點了發佈,發現已經掉線,全沒了,心累。算了,參考文獻裏寫的也很詳細了。


  1. shamir算法介紹 ↩︎

  2. 拉格朗日插值法 ↩︎

  3. https://github.com/blockstack/secret-sharing ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章