Web 前端密码加密是否有意义?www.zhihu.com
在这个温柔问题下看到了
@w2014
的一些密码学有趣的定理,感觉很有意思,例如零知识证明、盲签名、百万富翁问题,进而看到了知道了这个方法,两个人不需要裁判就能玩暗军棋daily.zhihu.com
这篇文章里关于百万富翁问题姚期智院士所给出的解法
本者刨根问底的好奇心,本人自己将该过程实现了一遍代码如下:
#!/usr/bin/env python
# coding -*- utf:8 -*-
import math
import random
'''
百万富翁问题实现
自己生成公钥私钥并解密加密
算法无安全性
'''
# 获取小于等于指定数的素数数组
def get_prime_arr(max):
prime_array = []
for i in range(2, max):
if is_prime(i):
prime_array.append(i)
return prime_array
# 判断是否为素数
def is_prime(num):
if num == 1:
raise Exception('1既不是素数也不是合数')
for i in range(2, math.floor(math.sqrt(num)) + 1):
if num % i == 0:
# print("当前数%s为非素数,其有因子%s" % (str(num), str(i)))
return False
return True
# 找出一个指定范围内与n互质的整数e
def find_pub_key(n, max_num):
while True:
# 这里是随机获取保证随机性
e = random.randint(1, max_num)
if gcd(e, n) == 1:
break
return e
# 求两个数的最大公约数
def gcd(a, b):
if b == 0:
return a
else:
return gcd(b, a % b)
# 根据e*d mod s = 1,找出d
def find_pri_key(e, s):
for d in range(100000000): # 随机太难找,就按顺序找到d,range里的数字随意
x = (e * d) % s
if x == 1:
return d
# 生成公钥和私钥
def build_key():
prime_arr = get_prime_arr(100)
p = random.choice(prime_arr)
# 保证p和q不为同一个数
while True:
q = random.choice(prime_arr)
if p != q:
break
print("随机生成两个素数p和q. p=", p, " q=", q)
n = p * q
s = (p - 1) * (q - 1)
e = find_pub_key(s, 100)
print("根据e和(p-1)*(q-1))互质得到: e=", e)
d = find_pri_key(e, s)
print("根据(e*d) 模 ((p-1)*(q-1)) 等于 1 得到 d=", d)
print("公钥: n=", n, " e=", e)
print("私钥: n=", n, " d=", d)
return n, e, d
# 加密
def rsa_encrypt(content, ned):
# 密文B = 明文A的e次方 模 n, ned为公钥
# content就是明文A,ned【1】是e, ned【0】是n
B = pow(content, ned[1]) % ned[0]
return B
# 解密
def rsa_decrypt(encrypt_result, ned):
# 明文C = 密文B的d次方 模 n, ned为私钥匙
# encrypt_result就是密文, ned【1】是d, ned【0】是n
C = pow(encrypt_result, ned[1]) % ned[0]
return C
if __name__ == '__main__':
pbvk = build_key()
pbk = (pbvk[0], pbvk[1]) # 公钥
pvk = (pbvk[0], pbvk[2]) # 私钥
# 生成两个亿万富翁
i = random.randint(1, 9)
j = random.randint(1, 9)
print("王有%s亿,李有%s亿" % (i, j))
x = random.randint(1, 100)
print("随机选取的大整数x: %s" % (x))
K = rsa_encrypt(x, pbk)
print("大整数加密后得密文K: %s" % (K))
c = K - j
print("王收到数字c: %s" % (c))
c_list = []
for k in range(1, 11):
t = rsa_decrypt(c + k, pvk)
c_list.append(t)
print("对c+1到c+10进行解密: %s" % c_list)
# 选取合适大小的p,这里根据感觉写了100以内的随机数,生成的序列的值也要求小于100
# 这个p是该算法的精华,在实际中选取p的策略要考虑到安全性和性能的因素
d_list = []
p = 0
while True:
# 每次选取p重置列表
d_list = []
p = random.randint(1, 100)
for k in range(0, 10):
if c_list[k] % p <= 100:
d_list.append(c_list[k] % p)
else:
break
if len(d_list) >= 10:
break
print("p的值为: %s" % p)
print("除以p后的余数为: %s" % d_list)
for k in range(i, 10):
d_list[k] = d_list[k] + 1
print("前i位不动后面数字+1后: %s" % d_list)
print("第j个数字为: %s" % d_list[j - 1])
print("x mod p为: %s" % (x % p))
if d_list[j - 1] == x % p:
print("i>=j,即王比李有钱或一样有钱")
if i - j >= 0:
print("验证成功")
else:
print("代码存在错误")
else:
print("i
代码是基于Python3的,有兴趣的朋友可以直接在本地跑一下,希望结合代码能让感兴趣的朋友了解的更透彻。
完。