Shamir 秘密共享方案
Shamir 秘密共享方案
这是个好玩的东西。简单的讲,就是某个数字例如K=77,可以分成5个,只有3个人都选择恢复这个数字才能恢复这个数字。
这能干的事情就很多了。
至于详细地说。。。看下面:
基本原理
Shamir 秘密共享方案是一种基于多项式插值原理的密码学技术,由 Adi Shamir 在 20 世纪 70 年代提出。其核心思想是将一个秘密数据分割成多个份额,只有当足够数量的参与者(达到一个预设的阈值)将他们的份额组合在一起时,才能重建出原始秘密。
详细步骤
构造多项式
- 选择一个有限域 GF(q),其中 q 是一个素数,且要大于最大的秘密值和参与者的数量。
- 构造一个 k−1 次多项式 f(x)=a₀+a₁x+a₂x²+…+a_{k−1}x^{k−1},其中 a₀ 为秘密,a₁,a₂,…,a_{k−1} 是在有限域内随机选择的系数。
生成份额
对于每个参与者 i(1≤i≤n),计算该多项式在 x=i 处的值,即份额 s_i=f(i),然后将这些份额分发给各个参与者。
秘密恢复
当有足够的参与者(至少 k 个)提供他们的份额时,可以通过插值法(如拉格朗日插值法)来重建多项式 f(x),从而计算出 f(0),即原始秘密。
用途
安全领域
- 门限密码学
- 在加密货币钱包管理等场景中,将私钥分割成多个部分分发给不同信任方,只有达到一定数量的信任方提供份额时才能组合出私钥,防止因单点故障或恶意行为导致私钥泄露或系统崩溃。
 
- 关键基础设施保护
- 对于核电站、军事指挥中心等关键设施的操作系统密码或启动密钥等重要信息,将其分割成多个部分分发给不同授权人员,确保只有足够数量的授权人员同时提供份额时才能启动或操作关键设施。
 
分布式系统
- 数据备份与恢复
- 在分布式存储系统中,将数据加密密钥分割成多个份额存储在不同节点上,当部分节点故障或数据丢失时,只要还有足够数量的存活节点提供份额,就可以恢复出原始密钥进而恢复数据。
 
- 容错机制
- 在分布式计算任务中,将关键参数分割成多个份额分配给不同计算节点,即使部分节点出现故障或计算错误,只要还有足够数量的正确节点提供份额,就可以恢复出正确的关键参数,保证整个计算任务的正常进行。
 
示例
感谢作者pyrie的代码。
# https://www.cnblogs.com/pyrie/p/sss_py.html
import Crypto.Util.number as numb
import random
# 求逆的函数,之前的版本用python2写的,这次用的python3,只把整除符号改了一下
def oj(a, n):
    a = a % n
    s = [0, 1]
    while a != 1:
        if a == 0:
            return 0
        q = n // a
        t = n % a
        n = a
        a = t
        s += [s[-2] - q * s[-1]]
    return s[-1]
# max_length 为p的长度,同时也是秘密的最大长度
# secret_is_text =0 默认输入时文本, 非0时认为是数字
# p 默认为0, 会根据max_length 自动生成,不为0时直接使用,需要保证p为素数, 函数内没有素性检验
def create(max_length=513, secret_is_text=0, p=0):
    if not p:
        p = numb.getPrime(max_length)
    w = int(input("请输入秘密保存人数:"))
    t = int(input("请输入秘密恢复所需人数:"))
    while not (t > 0 and t <= w):
        t = int(input("请重新输入:"))
    s = input("请输入你的秘密:")
    if secret_is_text:
        s = numb.bytes_to_long(s.encode("utf-8"))
    else:
        try:
            s = int(s)
        except Exception as e:
            s = numb.bytes_to_long(s.encode("utf-8"))
    x_list = list()
    a_list = list()
    i = w
    while i > 0:
        x = random.randint(p // 2, p)  # 该范围没有特定限制,如果想让xi,yi取小一点儿的话可把范围写小点儿,但是要大于w
        if x not in x_list:
            x_list.append(x)
            i -= 1
    for a in range(t):
        a_list.append(random.randint(p // 2, p))  # 同上
    result = list()
    for x in x_list:
        y = s
        for a_n in range(t):
            a = a_list[i]
            y += a * pow(x, i + 1, p)
        result.append((x, y))
    return t, p, result
# get_text=1 默认恢复为字符串,若想得到数字填0
def restore(p, information, get_text=1):
    x_list = list()
    y_list=list()
    for x, y in information:
        x_list.append(x)
        y_list.append(y)
    s = 0
    for x_i in range(len(x_list)):
        tmp_num = y_list[x_i]
        x_i_j = 1
        for x_j in range(len(x_list)):
            if x_i != x_j:
                tmp_num = tmp_num * (0 - x_list[x_j]) % p
                x_i_j *= x_list[x_i] - x_list[x_j]
        tmp_num = tmp_num * oj(x_i_j, p) % p
        s += tmp_num
    s = s % p
    print(s)
    if get_text:
        try:
            s = numb.long_to_bytes(s)
            s = s.decode("utf-8")
        except Exception as e:
            print(e)
    return s
t, p, result = create()             #result为秘密碎片的列表
print(result)
print(restore(p, result[:t]))     #这里我取了result的前t个,实际中可以取任意t个。
我看看我是何时复制这些代码的,嗯,25-03-26。
确实好玩,但也仅限于“好玩”,实用性确实有,但目前对我没有效果。
而且“每次恢复密钥后,密钥就要改变”也挺烦的,如果能够实现同态加密,每个人用自己的那一部分解密就好了。
而且“拿到全部份额的人同时也担任着公布的责任”
啧,好玩,而且有用,但是有一定局限。
至少目前看来比某两个东西好。对,说的是零知识证明和RSA同态加密,点你们俩呢。

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号