基于中国剩余定理的(t, n)门限秘密共享方案

基于中国剩余定理的(t, n)门限秘密共享方案

  • 目录
    • 实验目的
      • 实验环境
      • 实现目标
    • 方案设计
      • 背景
      • 实验原理
      • 算法步骤
    • 方案实现
      • 流程图
      • 主要函数介绍
      • 主要代码
    • 数据分析
      • 数据1
      • 数据1运行结果
      • 数据2
      • 数据2运行结果
  • 完整代码

目录

实验目的

实验环境

python3.8.8

实现目标

  1. 实现(t, n)秘密共享方案,具体t和n的值需要测试数据的时候输入,而不是在代码中设定好t=3,n=5;
  2. 需要验证少于等于t-1个子秘密,不能正确恢复出秘密,也需与原秘密最对比
  3. 子秘密的选取也是在测试数据的时候输入,不是指定的
  4. 原秘密的长度大约500位,需要如何设置di的值,也需要思考

方案设计

背景

在中国剩余定理的基础上,提出了秘密共享的设计方案。将秘密k分成n个子秘密k1,k2,…,kn,利用中国剩余定理,使得如果已知任意t个ki的值,则很容易恢复出k,如果已知任意t-1个或者更少的ki值,则不能够恢复出k,以此来达到(t,n)门限秘密共享的方案。

实验原理

基于中国剩余定理的(t, n)门限秘密共享方案_第1张图片
基于中国剩余定理的(t, n)门限秘密共享方案_第2张图片
基于中国剩余定理的(t, n)门限秘密共享方案_第3张图片

算法步骤

1、从键盘获取参数t,n
2、从文件中读入500位的秘密k
3、所以生成n个d值并保证它们两两互素
4、将其放入列表d[],并输出
5、计算N,M的值并输出
6、计算n位ki的值
7、任选t组子秘密,用中国剩余定理恢复秘密k并输出
8、将恢复的秘密与原k值比较
9、任选t-1组子秘密,尝试用中国剩余定理恢复秘密k并输出
10、将恢复的秘密与原k值比较

方案实现

流程图

基于中国剩余定理的(t, n)门限秘密共享方案_第4张图片

主要函数介绍

def moni(a, b):  # 计算a对b的模逆
def ChineseRemainderTheorem(kj, dj):  # 中国剩余定理,参数为t个或指定个数的子秘密

主要代码

def moni(a, b):  # 用扩展的欧几里得算法计算模逆
    f = 0  # 判断a是否大于b的标志位
    if a < b:
        f = 1
        t = a
        a = b
        b = t
    x1, x2, x3 = 1, 0, a
    y1, y2, y3 = 0, 1, b
    while y3 != 0:
        q = x3 // y3
        t1 = x1 - q * y1
        t2 = x2 - q * y2
        t3 = x3 - q * y3
        x1, x2, x3 = y1, y2, y3
        y1, y2, y3 = t1, t2, t3
    if f != 1:
        return x1
    else:
        return x2
def ChineseRemainderTheorem(kj, dj):  # 中国剩余定理,参数为任选的t个或其他个数的子秘密
    l = len(kj) # 计算子秘密的个数
    M = 1
    for i in range(l):
        M *= dj[i]
    Mi = []
    for i in range(l):
        Mi.append(M // dj[i])
    Mini = []
    for i in range(l):
        Mini.append(moni(Mi[i], dj[i]))
    sum = 0
    for i in range(l):
        sum += kj[i] * Mi[i] * Mini[i]
    return sum % M
# 生成n个d值放入列表
d = []
temp = random.randint(pow(10, (math.floor(math.log(k, 10)) + 1) // t + 1),
                      pow(10, (math.floor(math.log(k, 10)) + 1) // (t - 1)))
d.append(temp)
while len(d) < n:
    temp = random.randint(pow(10, (math.floor(math.log(k, 10)) + 1) // t + 1),
                          pow(10, (math.floor(math.log(k, 10)) + 1) // (t - 1)))
    if len(d) == 1:
        if math.gcd(d[0], temp) == 1:
            d.append(temp)
    else:
        d.append(temp)
        flag = 1  # 检查各d值是否两两互素的标志
        for i in range(len(d) - 1):
            for j in range(i + 1, len(d)):
                if math.gcd(d[i], d[j]) != 1:
                    flag = 0    # 不满足两两互素,将temp从列表中删去
                    d.pop()
                    break
            if flag == 0:
                break
# 任选t组子秘密来恢复秘密k
kn = random.sample(range(n), t)  # 从n位任选t位,把下标存入kn列表
k1 = []
d1 = []
for i in range(t):
    k1.append(ki[kn[i]])
    d1.append(d[kn[i]])
recoverk = ChineseRemainderTheorem(k1, d1)
print("用t个子秘密恢复的秘密为:")
print(recoverk)
if recoverk == k:
    print("用t个子秘密恢复的秘密与原秘密相同,恢复正确!")
else:
    print("用t个子秘密恢复的秘密与原秘密不同,恢复错误!")

数据分析

数据1

34513712707371090043400509009985458207561435293144665050156734850970676055150464106635392035854544862922520495601217956585479796115422265889272312112460676286676002639176428018428110501603858423653391913799566813168343496159580747338826480697660522927181825310390154470363345038219192650075737129895819591216748784152267758174110791876279446873375543750375483617833468974263170064305100280485303368221268987883665789183494148190239289344532645805573919693262044556121484486211305720303265273494061665

数据1运行结果

基于中国剩余定理的(t, n)门限秘密共享方案_第5张图片

数据2

17478026666831342165607225368616063321718469751086098129424513844183358424079116995431214409628223777290633100657385400167527602481955811267190102034135644678975332538402411252204599772483146656099060144969961437110041474027934832041351813583159652034964431257857287075228427404692047523442305548984024079911564277739000132521183888591292001268001699186206357791036971642713788106200272066299890847864165018226431988593865501936053961710499420525798158420768632815038342235167689001130965331812773662

数据2运行结果

基于中国剩余定理的(t, n)门限秘密共享方案_第6张图片

完整代码

import random
import math


def moni(a, b):  # 用扩展的欧几里得算法计算模逆
    f = 0  # 判断a是否大于b的标志位
    if a < b:
        f = 1
        t = a
        a = b
        b = t
    x1, x2, x3 = 1, 0, a
    y1, y2, y3 = 0, 1, b
    while y3 != 0:
        q = x3 // y3
        t1 = x1 - q * y1
        t2 = x2 - q * y2
        t3 = x3 - q * y3
        x1, x2, x3 = y1, y2, y3
        y1, y2, y3 = t1, t2, t3
    if f != 1:
        return x1
    else:
        return x2


def ChineseRemainderTheorem(kj, dj):  # 中国剩余定理,参数为任选的t个或其他个数的子秘密
    l = len(kj) # 计算子秘密的个数
    M = 1
    for i in range(l):
        M *= dj[i]
    Mi = []
    for i in range(l):
        Mi.append(M // dj[i])
    Mini = []
    for i in range(l):
        Mini.append(moni(Mi[i], dj[i]))
    sum = 0
    for i in range(l):
        sum += kj[i] * Mi[i] * Mini[i]
    return sum % M


t = int(input("请输入参数t:"))
n = int(input("请输入参数n:"))
with open("D:\secret2.txt") as file:
    data = file.readline()
k = int(data)
print("从文件中读取的秘密k的值为:")
print(k)

# 生成n位d值放入列表
d = []
temp = random.randint(pow(10, (math.floor(math.log(k, 10)) + 1) // t + 1),
                      pow(10, (math.floor(math.log(k, 10)) + 1) // (t - 1)))
d.append(temp)
while len(d) < n:
    temp = random.randint(pow(10, (math.floor(math.log(k, 10)) + 1) // t + 1),
                          pow(10, (math.floor(math.log(k, 10)) + 1) // (t - 1)))
    if len(d) == 1:
        if math.gcd(d[0], temp) == 1:
            d.append(temp)
    else:
        d.append(temp)
        flag = 1  # 检查各d值是否两两互素的标志
        for i in range(len(d) - 1):
            for j in range(i + 1, len(d)):
                if math.gcd(d[i], d[j]) != 1:
                    flag = 0    # 不满足两两互素,将temp从列表中删去
                    d.pop()
                    break
            if flag == 0:
                break

print(n, "个d值分别为:", sep='')
for i in range(n):
    print(d[i])
N = 1
M = 1
for i in range(t):
    N = N * d[i]
for i in range(n - t + 1, n):
    M = M * d[i]
print("N值为:", N)
print("M值为:", M)
ki = []
for i in range(n):
    ki.append(k % d[i])

# 任选t组子秘密来恢复秘密k
kn = random.sample(range(n), t)  # 从n位任选t位,把下标存入kn列表
k1 = []
d1 = []
for i in range(t):
    k1.append(ki[kn[i]])
    d1.append(d[kn[i]])
recoverk = ChineseRemainderTheorem(k1, d1)
print("用t个子秘密恢复的秘密为:")
print(recoverk)
if recoverk == k:
    print("用t个子秘密恢复的秘密与原秘密相同,恢复正确!")
else:
    print("用t个子秘密恢复的秘密与原秘密不同,恢复错误!")

# 任选t-1组子秘密来恢复秘密
kn2 = random.sample(range(n), t - 1)  # 从n位任选t-1位,把下标存入kn2列表
k2 = []
d2 = []
for i in range(t - 1):
    k2.append(ki[kn2[i]])
    d2.append(d[kn2[i]])
recoverk = ChineseRemainderTheorem(k2, d2)
print("用t-1个子秘密恢复的秘密为:")
print(recoverk)
if recoverk == k:
    print("用t-1个子秘密恢复的秘密与原秘密相同,恢复正确!")
else:
    print("用t-1个子秘密恢复的秘密与原秘密不同,恢复错误!")

你可能感兴趣的:(算法,python)