python3.8.8
在中国剩余定理的基础上,提出了秘密共享的设计方案。将秘密k分成n个子秘密k1,k2,…,kn,利用中国剩余定理,使得如果已知任意t个ki的值,则很容易恢复出k,如果已知任意t-1个或者更少的ki值,则不能够恢复出k,以此来达到(t,n)门限秘密共享的方案。
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值比较
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个子秘密恢复的秘密与原秘密不同,恢复错误!")
34513712707371090043400509009985458207561435293144665050156734850970676055150464106635392035854544862922520495601217956585479796115422265889272312112460676286676002639176428018428110501603858423653391913799566813168343496159580747338826480697660522927181825310390154470363345038219192650075737129895819591216748784152267758174110791876279446873375543750375483617833468974263170064305100280485303368221268987883665789183494148190239289344532645805573919693262044556121484486211305720303265273494061665
17478026666831342165607225368616063321718469751086098129424513844183358424079116995431214409628223777290633100657385400167527602481955811267190102034135644678975332538402411252204599772483146656099060144969961437110041474027934832041351813583159652034964431257857287075228427404692047523442305548984024079911564277739000132521183888591292001268001699186206357791036971642713788106200272066299890847864165018226431988593865501936053961710499420525798158420768632815038342235167689001130965331812773662
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个子秘密恢复的秘密与原秘密不同,恢复错误!")