Shamir 门限秘密共享算法:原理、Python 实现及算法流程

一、实验目的

掌握车联网中的数据共享方案原理,并利用 Python 代码实现 Shamir 门限秘密共享算法。

二、实验环境

Python 3.9

三、实验内容

3.1 Shamir 门限秘密共享方案原理

Shamir(t, w) 门限密钥共享方案由 Shamir 在 1979 年提出。该方案通过构造一个 t-1 次多项式,将需要共享的主密钥 S 作为常数项,碎片密钥分成 w 部分给 w 个参与者。当碎片密钥数量大于或等于 t 时,就可以求解出这个主密钥 S。

子密钥生成:

构造多项式:

F(x) = s + a_1*x + a_2*x^2 + ... + a_{t-1}*x^{t-1} (mod p)

其中 s 为密钥,p 为素数 (s 取 w 个不相等的 x 带入 F(x) 中,得到 w 组子密钥,分发给 w 个人保管,将 p 公开,销毁子密钥生成多项式,每个人保管自己的子密钥)。

恢复密钥:

构造多项式:

F(x) = s + a_1*x + a_2*x^2 + ... + a_{t-1}*x^{t-1} (mod p)

取 x=0,代入 t 组密钥可以求解出 F(0),也就是主密钥 s。

3.2 Python 代码实现

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('还原出最初的秘密S:')
print(restore(p, result[:t], 0))

3.3 算法流程

  1. 输入秘密保存人数 w 和秘密恢复所需人数 t;
  2. 输入需要共享的主密钥 S;
  3. 生成一个素数 p,用于构造多项式;
  4. 随机生成 w 个 x 值,作为多项式的系数;
  5. 随机生成 t 个 a 值,作为多项式的常数项;
  6. 根据多项式,计算出 w 个 (x, y) 对,作为密钥碎片;
  7. 将密钥碎片分发给 w 个人保管,同时销毁多项式;
  8. 当需要恢复密钥时,收集至少 t 个密钥碎片;
  9. 利用拉格朗日插值,通过 t 个密钥碎片恢复出主密钥 S。

四、总结

Shamir 门限秘密共享算法是一种简单高效的安全数据共享方案,在实际应用中具有广泛的应用场景,例如密钥管理、数据备份等。

Shamir 门限秘密共享算法:原理、Python 实现及算法流程

原文地址: https://www.cveoy.top/t/topic/n8g4 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录