我是靠谱客的博主 不安玫瑰,最近开发中收集的这篇文章主要介绍【密码学】Shamir秘密分享python实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Shamir原理参见

分析

1.随机生成最高m - 1次的多项式
2.获取f(x)的值
3.随机生成n份shares
4.根据m份shares重构出secret(拉格朗日插值)
5.测试函数

source code

import random
from math import ceil
from decimal import Decimal

FIELD_SIZE = 10 ** 5


def coeff(t, secret):
    """
    生成最高次为t - 1次的多项式,其中常数项是secret
    """
    # 保证第一项不为0
    coeff = [random.randrange(1, FIELD_SIZE)]
    # 后面t - 2系数项可为0
    if t > 3:
        coeff += [random.randrange(0, FIELD_SIZE) for _ in range(t - 2)]
    # 加入常数项
    coeff.append(secret)
    return coeff


def polynom(x, coefficients):
    """
    获取f(x)的值
    """
    point = 0
    # coeff从左到右是高次到低次的(使用enumerate表示指数)
    for coefficient_index, coefficient_value in enumerate(coefficients[::-1]):
        point += x ** coefficient_index * coefficient_value
    return point


def generate_shares(n, m, secret):
    """
    将秘密分成n份,只需要m份就可以复原(也就是阈值,函数的最高次数 + 1)
    """
    coefficient = coeff(m, secret)
    shares = []
    
    for i in range(1, n + 1):
        x = random.randrange(1, FIELD_SIZE)
        shares.append((x, polynom(x, coefficient)))
    
    return shares


def reconstruct_secret(shares):
    """
    利用拉格朗日插值法(已知m个秘密)还原并得到secret(f(0))
    """
    sums = 0
    
    for j, share_j in enumerate(shares):
        xj, yj = share_j
        prod = Decimal(1)
        
        for i, share_i in enumerate(shares):
            xi, _ = share_i
            if i != j:
                prod *= Decimal(Decimal(xi) / (xi - xj))
        
        prod *= yj
        sums += Decimal(prod)
    
    return int(round(Decimal(sums), 0))
# Driver code
if __name__ == '__main__':
 
    # (3,5) sharing scheme
    t, n = 3, 5
    secret = 1234
    print(f'Original Secret: {secret}')
 
    # Phase I: Generation of shares
    shares = generate_shares(n, t, secret)
    print(f'Shares: {", ".join(str(share) for share in shares)}')
 
    # Phase II: Secret Reconstruction
    # Picking t shares randomly for
    # reconstruction
    pool = random.sample(shares, t)
    print(f'Combining shares: {", ".join(str(share) for share in pool)}')
    print(f'Reconstructed secret: {reconstruct_secret(pool)}')

最终结果

在这里插入图片描述

总结

这是门限(n,t)Shamir秘密分享
用了多项式理论
在区块链的多方签名有所应用

20221003 bug修复

  • 由于filed_size过大可能存在超大数溢出的可能,后面可以取MOD进行解决,由于涉及除法,因此需考虑到逆元
  • x的取值需要保证不同
  • 下面修改filed_size为100,可以在一定概率上支持t = 50的情况
import random
from math import ceil
from decimal import Decimal

FIELD_SIZE = 10 ** 2
MOD = 9999999987


def coeff(t, secret):
    """
    生成最高次为t - 1次的多项式,其中常数项是secret
    """
    # 保证第一项不为0
    coeff = [random.randrange(1, FIELD_SIZE)]
    # 后面t - 2系数项可为0
    if t > 3:
        coeff += [random.randrange(0, FIELD_SIZE) for _ in range(t - 2)]
    # 加入常数项
    coeff.append(secret)
    return coeff


def polynom(x, coefficients):
    """
    获取f(x)的值
    """
    point = 0
    # coeff从左到右是高次到低次的(使用enumerate表示指数)
    for coefficient_index, coefficient_value in enumerate(coefficients[::-1]):
        point += x ** coefficient_index * coefficient_value
    return point


def generate_shares(n, m, secret):
    """
    将秘密分成n份,只需要m份就可以复原(也就是阈值,函数的最高次数 + 1)
    """
    coefficient = coeff(m, secret)
    shares = []
    xs = random.sample(range(0, FIELD_SIZE), n)

    for i in range(1, n + 1):
        x = xs[i - 1]
        shares.append((x, polynom(x, coefficient)))

    return shares


def reconstruct_secret(shares):
    """
    利用拉格朗日插值法(已知m个秘密)还原并得到secret(f(0))
    """
    sums = 0

    for j, share_j in enumerate(shares):
        xj, yj = share_j
        prod = Decimal(1)

        for i, share_i in enumerate(shares):
            xi, _ = share_i
            if i != j:
                #print(Decimal(Decimal(xi) / (xi - xj)))
                prod *= Decimal(Decimal(xi) / (xi - xj))
        #print(yj)
        prod *= yj
        sums += Decimal(prod)
    print(sums)

    return int(round(Decimal(sums), 0))


# Driver code
if __name__ == '__main__':
    # (3,5) sharing scheme
    t, n = 50, 100
    secret = 1234
    print(f'Original Secret: {secret}')

    # Phase I: Generation of shares
    shares = generate_shares(n, t, secret)
    print(f'Shares: {", ".join(str(share) for share in shares)}')

    # Phase II: Secret Reconstruction
    # Picking t shares randomly for
    # reconstruction
    pool = random.sample(shares, t)
    print(f'Combining shares: {", ".join(str(share) for share in pool)}')
    print(f'Reconstructed secret: {reconstruct_secret(pool)}')

最后

以上就是不安玫瑰为你收集整理的【密码学】Shamir秘密分享python实现的全部内容,希望文章能够帮你解决【密码学】Shamir秘密分享python实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部