秘密共享原理与实现

毕业设计里用到了一些密码学的知识,在博客做个记录。

秘密共享

秘密共享(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 ↩︎

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