密码学实验 | shamir门限秘密共享算法(python)

一、实验原理

(t,n)门限秘密共享方案,该方案是Shamir和Blakley在1979年各自独立地提出。

(t,n)门限方案是基于(t.n)门限访问结构上的秘密共享方案,而(t,n)门限访问结构包括所有t个或t个以上的参与者子集所构成的集合。

1. Shamir (t,n)门限方案是通过构造一个t-1次多项式,并将需共享的秘密作为该多项式的常数项,将秘密分成n部分分别给n个参与者,使t个参与者联合可恢复秘密,但少于t个参与者联合不能得到共享秘密的任何信息。Blakley独立地提出的另一个(t,n)门限方案,它的基本思想是利用多维空间中的点来建立门限方案,将共享的秘密看成t维空间中的一个点,每个子秘密为包含这个点的t-1维超平面的方程,任意t个t- 1维超平面的交点刚好确定共享的秘密,而t-1个子秘密(即t-1个t-1维超平面)仅能确定其交线,因而得不到共享秘密的任何信息。

2. Blakley方案比Shamir方案信息率低,但它有一个特殊的性质:任意t个子秘密除确定交点以外,它们相互之间是无关的,而Shamir方案却与此不同,任意t个子秘密能够确定整个多项式,并能计算出其余参与者的子秘密。

二、实验代码

# -*- coding:utf-8 -*- 
import random
import math


"""
This program generates a Shamir (t,n)-Threshold Scheme, with the desired
settings - as set by the user. The scheme can be initiated by running this
python script through the command line, or run directly via the python shell.

For specifications, the program requires the following 4 parameters:
-Prime field, over which all calculations will be conducted
-Desired secret, in the form of some number less than the prime field
-Number of total participants
-Size of threshold
"""

# 输入q, n, t, k 
def initiateScheme(predefinedVars):
    kField = []
    n = 0
    t = 0
    #*Allows scheme to be run multiple times with different secret
    if not predefinedVars:
        Elements = input("Enter prime field (q)\n")

        q = int(Elements)
        q = testPrimality(q)
        
        Field = createField(q)
        print("\nField created:")
        print("q:", Field)

        kField = Field
        
        n = input("Enter number of participants n (less than field order)\n")
        t = input("Enter access structure length t (less than participant number)\n")
        
        predefinedVars = [n, t, q, Field]
        
        if(n >= t):
            print("Creating new (" + t + ", " + n + ")-Threshold Scheme")
        
        else:
            print("Access structure length must be less than number of participants")
            initiateScheme()
    else:
        kField = predefinedVars[3]
        q = predefinedVars[2]
        t = predefinedVars[1]
        n = predefinedVars[0]
    
    secretInd = input("\nEnter index of desired secret (k) in field (0 to (q-1))\n")
    secret_k = kField[int(secretInd)]
    print("k:", secret_k)

    recovered_k = runScheme(t, n, secret_k, q, Field)
    
    return predefinedVars, recovered_k

# 检查是不是素数
def testPrimality(q):
    i = q
    q = math.sqrt(q)
    q = int(q)
    for p in range(2, (q+1)):
        f = i / p
        if(f.is_integer()):
            #print(f)
            #print(i)
            #print(p)
            newQ = input("Enter prime number")
            newQ = int(newQ)
            newQ = testPrimality(newQ)
            i = newQ
            break
    return i

# 创建有限域 GF(q)
def createField(q):
    ModuloK = []
    for i in range(0, q):
        ModuloK.append(i) 
    
    return ModuloK
    
# 运行算法
def runScheme(t_str, n_str, k, q, Field):
    x_subi = [0]
    a_subj = [0]
    pShares = [0]
    pShares_regex = [0]
    
    t = int(t_str)
    n = int(n_str)
    
    for i in range(1, n+1):
        #print("ran")
        x = getDistinctX(x_subi, Field)
        x_subi.append(x)

    print("x 所有取值:", x_subi)
    
    for j in range(1, t):
        ind = random.randint(0, q)
        a_subj.append(Field[ind])
    # 根据需要加减a_i的值
    print("a_1的值:", a_subj[1], "a_2的值:", a_subj[2])
    print("a_3的值:", a_subj[3], "a_4的值:", a_subj[4])    

    
    for i in range(1, n+1):
        x = x_subi[i]
        # print("x_i的值:",x)
        polynomialSum = k
        #print(k)
        for j in range(1, t):
            a = a_subj[j]
            # print("a:", a)
            exponent = math.pow(x, j)
            # print("exponent:", exponent)
            polynomialSum += a * exponent
            # print("polynomialSum:", polynomialSum)
        
        regEx = polynomialSum % q
        print("(%d, %d)" %(x, regEx))
        pShares_regex.append(regEx)
        # print("all f(x) :", pShares_regex)
        
        pShares.append(polynomialSum)

    # 根据你需要的多项式,手动修改
    # print("f(x) = %d + %d x +%d x^2  mod %d" %(k, a_subj[1], a_subj[2], q))
    print("f(x) = %d + %d x +%d x^2 +%d x^3 + %d x^4 mod %d" %(k, a_subj[1], a_subj[2], a_subj[3], a_subj[4] ,q))
    print("Shares generated")
    displayShares_i(pShares_regex)


    generatedK = tryAccessStructure(k, pShares, x_subi, t_str, q)
    
    return generatedK


def reduce(integer, F):
    F.sort(reverse=True)
    print(F)
    binary = []
    regEx = []
    for i, f in enumerate(F):
        if(integer >= f):
            integer -= f

            binary.append(1)
            regEx.append(f)
        else:
            binary.append(0)

    return binary, regEx


def tryAccessStructure(k, pShares, x_subi, t_str, q):
    P_Subset = getSubset()

    generatedK = generateK(pShares, x_subi, P_Subset, q)
    if(generatedK != k):
        print("Incorrect secret; access structure must be of length: " + t_str)
    else:
        print("Secret recovered")
    r = input("Try different access structure (Y or N)\n")
    if(r.upper() == "Y"):
        generatedK = tryAccessStructure(k, pShares, x_subi, t_str, q)

    return generatedK

# 生成x的值,x = 1~5
def getDistinctX(x_subi, F): 
    #x_subi = []
    ind = random.randint(1, 5)
    # ind = range(0, (len(F)-1))
    x = F[ind]
    if not x in x_subi:
        return x
    else:
        x = getDistinctX(x_subi, F)
        return x

    

def displayShares_i(pShares):
    P_ID_str = input("Enter participant number to see share (number from 1 - n)\n")
    P_ID = int(P_ID_str)
    try:
        Share = pShares[P_ID]
        Share = int(Share)
        print("Share for participant #" + P_ID_str + ": " + str(Share))
        Repeat = input("Display another share (Y, or N)\n")
        if(Repeat.upper() == "Y"):
            displayShares_i(pShares)
    except:
        print("Index out of range: \nEnter number between 1 and access structure length.")
        displayShares_i(pShares)
    
    return 

# 获取子密钥
def getSubset():
    Subset_RAWstr = input("\nEnter list of participants who wish to recover the secret\nEnter in form 'ID#1 ID#2 ... ID#T' where ID#i is the number of\nparticipant i \n")
    Subset_str = Subset_RAWstr.split()
    Subset = [0]
    Subset_mm = input("Enter list of Participant i secrets\n")
    for ID in Subset_str:
        try:
            ID = int(ID)
            Subset.append(ID)
        except:
            print("Error in list entered, try again")
            Subset = getSubset()
            #ADD RECURSIVE FUNCTION
        
    return Subset

# 恢复秘密k 
def generateK(pShares, x_subi, Subset, q):
    y_subset = []
    x_subset = []
    
    Subset.sort()
    for ID in Subset:
        y_i = pShares[ID]
        x_i = x_subi[ID]
        y_subset.append(y_i)
        x_subset.append(x_i)
    
    recoveredK = 0
    for j in range(1, (len(x_subset))):
        x_j = x_subset[j]
        b_j = 1
        for L in range(1, len(x_subset)):
            if(L != j):
                x_L = x_subset[L]
                newCoeff = float(x_L)/(x_L - x_j)
                b_j = b_j * newCoeff
        recoveredK += y_subset[j] * (b_j)

    recoveredK_int = int(round(recoveredK))
    print("恢复出的秘密值k:", recoveredK_int)
    
    return recoveredK_int


def runPackage(predefinedVars, recoveredKs):
    predefinedVars, returnK = initiateScheme(predefinedVars)
    # print("predefinedVars:", predefinedVars, "returnK:", returnK)
    if returnK in predefinedVars:
        print("New secret found:" + str(returnK))
        recoveredKs.append(returnK)
        print(recoveredKs)
    else:
        print("Invalid access structure")

    response = input("Run process again for different k in field (Y or N).\n")
    if(response.upper() == "Y"):
        runPackage(predefinedVars, recoveredKs)
    
# initiateScheme()

runPackage([], [])

三、实验结果

解密正确:

在这里插入图片描述

解密错误:
在这里插入图片描述

四、实验总结

在这次实验中,使用的是python编写shamir门限算法,通过构造初始化函数、创建有限域 GF(q)、运行算法等函数组合编写成该门限共享方案。
通过这次实验,可以知道秘密共享算法是一种非常安全的算法,将共享的秘密分成若干份分别给予若干参与者保管,并规定哪些参与者联合起来可重构秘密,哪些参与者联合起来并不能得到任何信息,就像示例3所示,当参与者个数少于最少重构秘密个数时,则不能得到任何信息。

  • 22
    点赞
  • 158
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
Shamir秘密共享算法是一种通过将秘密信息分割成多个部分,分发给不同的参与者,使得只有集齐足够数量的部分才能恢复出原始秘密信息的算法。下面将介绍一个Shamir秘密共享算法实验设计。 实验目标:验证Shamir秘密共享算法的可行性和正确性。 实验步骤: 1. 确定参与者数量和秘密信息的长度,假设有k个参与者分别称为P1, P2, ..., Pk,并且秘密信息由一个整数表示。 2. 生成一个(k-1)次的多项式函数,其中常数项为秘密信息,其它项为随机生成的系数。将该函数表示为f(x) = a0 + a1*x + a2*x^2 + ... + a(k-1)*x^(k-1)。 3. 将多项式函数f(x)代入不同的x坐标(对应参与者),计算出对应的y坐标(对应分发给参与者的部分秘密信息)。 4. 将生成的坐标对(x, y)分发给相应的参与者,每个参与者只收到一个坐标对。 5. 只有集齐至少k个参与者的坐标对,秘密信息才能被恢复。 6. 验证恢复出的秘密信息是否正确,并与原始秘密信息进行对比。 实验要点: 1. 多项式函数的生成需要保证随机性,可以使用随机数生成器来产生系数。 2. 参与者之间必须保持沟通,以便在恢复秘密信息时,能够及时共享各自持有的部分信息。 3. 实验中的参与者数量k和多项式次数(k-1)需要事先确定,并满足k的选择与算法要求的阈值条件。 通过这样的实验设计,可以验证Shamir秘密共享算法的正确性和可行性。并且,这个实验可以帮助理解Shamir秘密共享算法的原理和应用场景,帮助学习者更好地掌握该算法
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值