多方安全计算———姚氏百万富翁问题(附代码)
姚氏经典百万富翁问题
1.张三和李四各有i,j财富
2.李四选取一个大整数x并加密得到K,并用K减去财富j得到c,把c发送给张三
3.张三把计算 c+1、c+2...c+o并解密,随后用这10个数模除一个适当的整数p得到
d....dio(要保证d, = x mod p)
4.张三对前i 企.d不动,从第i+1个后每个加1,发送给李四
5.李四计算x mod p 与d,比较,如果相等说明d;,属于前i个数,可以知道i>=j,如果不相
等说明dj,属于i后面的数,则i>j.
完整源代码可以关注公众号回复百万富翁问题代码即可
# SimpleRSA.py # 简单的RSA生成公私钥的算法 # -*- coding: utf-8 -*- import random from collections import namedtuple # 返回范围内的一个素数列表(start, stop) def get_primes(start, stop): if start >= stop: return [] primes = [2] for n in range(3, stop + 1, 2): for p in primes: if n % p == 0: break else: primes.append(n) while primes and primes[0] < start: del primes[0] return primes # 判断是否为相对质数 def are_relatively_prime(a, b): """ 如果“a”和“b”是两个相对质数,则返回“True”。 如果两个数没有公因数,它们就是质数。 """ for n in range(2, min(a, b) + 1): if a % n == b % n == 0: return False return True # 获取私钥和公钥 def make_key_pair(length): if length < 4: raise ValueError('cannot generate a key of length less than 4 (got {!r})'.format(length)) n_min = 1 << (length - 1) n_max = (1 << length) - 1 start = 1 << (length // 2 - 1) stop = 1 << (length // 2 + 1) primes = get_primes(start, stop) while primes: p = random.choice(primes) primes.remove(p) q_candidates = [q for q in primes if n_min <= p * q <= n_max] if q_candidates: q = random.choice(q_candidates) break else: raise AssertionError("cannot find 'p' and 'q' for a key of length={!r}".format(length)) stop = (p - 1) * (q - 1) for e in range(3, stop, 2): if are_relatively_prime(e, stop): break else: raise AssertionError("cannot find 'e' with p={!r} and q={!r}".format(p, q)) for d in range(3, stop, 2): if d * e % stop == 1: break else: raise AssertionError("cannot find 'd' with p={!r}, q={!r} and e={!r}".format(p, q, e)) pkey = PublicKey(p * q, e) skey = PrivateKey(p * q, d) return pkey, skey # 加密 class PublicKey(namedtuple('PublicKey', 'n e')): __slots__ = () def encrypt(self, x): return pow(x, self.e, self.n) # 解密 class PrivateKey(namedtuple('PrivateKey', 'n d')): __slots__ = () def decrypt(self, x): return pow(x, self.d, self.n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # Billion.py # 百万富翁问题 主程序 # -*- coding: utf-8 -*- from SimpleRSA import * import random public_key, private_key = make_key_pair( 12 ) # safe for n<100 A = random.randint( 1 , 9 ) B = random.randint( 1 , 9 ) def safeCmpAleB(a, b): print ( "\n假设张三有 i={} 亿,李四有 j={} 亿" . format (a, b)) print ( "\n张三生成一对RSA公私钥:" ) print ( "公钥(n,e): {}" . format (public_key)) print ( "私钥(n,d): {}\n" . format (private_key)) x = random.randint( 1000 , 2000 ) print ( "Step 1:李四随机选取一个大整数:{} " . format (x)) K = public_key.encrypt(x) print ( "\t\t李四利用张三公开的公钥对大整数进行加密得到密文K: " . format (K)) print ( "\t\t然后李四将 c=K-j({}-{}={}) 发送给张三\n" . format (K, b, K - b)) c = K - b p = 29 d = [] for i in range (c + 1 , c + 11 ): d.append((private_key.decrypt(i) % p)) print ( "Step 2:张三用自己的私钥对 c+1至c+10 进行加密:" ) print ( "\t\t{}" . format (d)) for i in range (a, 10 ): d[i] = d[i] + 1 print ( "\t\t对c+i+1至c+10执行+1操作,得到:" ) print ( "\t\t{}" . format (d)) print ( "Step 3:计算 x mod p 是否等于 d[j]. \n\t\t如果是, i>=j,即张三比李四富裕\n\t\t否则,i<j,即李四比张三富裕\n" ) print ( "\t\t计算:d[j] = {}, x mod p = {}" . format (d[b - 1 ], x % p)) if x % p = = d[b - 1 ]: return print ( "\t\t此次结果:i>=j,张三比李四富裕" ) else : return print ( "\t\t此次结果:i<j,李四比张三富裕" ) if __name__ = = '__main__' : safeCmpAleB(A, B) |
举个例子:
假设张三有 i=5 亿,李四有 j=7 亿
张三生成一对RSA公私钥:
公钥(n,e): PublicKey(n=3589, e=5)
私钥(n,d): PrivateKey(n=3589, d=2765)
Step 1:李四随机选取一个大整数:1688
李四利用张三公开的公钥对大整数进行加密得到密文K:
然后李四将 c=K-j(1007-7=1000) 发送给张三
Step 2:张三用自己的私钥对 c+1至c+10 进行加密:
[23, 26, 0, 18, 14, 14, 6, 17, 26, 26]
对c+i+1至c+10执行+1操作,得到:
[23, 26, 0, 18, 14, 15, 7, 18, 27, 27]
Step 3:计算 x mod p 是否等于 d[j].
如果是, i>=j,即张三比李四富裕
否则,i<j,即李四比张三富裕
计算:d[j] = 7, x mod p = 6
此次结果:i<j,李四比张三富裕
用一个前辈的化学解释:先在一不透光试管中加入未知量的水
A女士量取她年龄那么多毫升的1mol/L的HCl 加入试管
B女士量取她年龄那么多毫升的1mol/L的NaOH 加入试管
然后用Ph试纸就可判断谁的年龄大了
量取之后可以用水稀释至相同体积(比如40mL)这样就不怕泄露了
举个类似的多方安全计算问题的生活例子
比如说a,b,,c,d四人在同一家公司打工,他们互相不知道对方工资也不想让别人知道他们自己的工资,如果他们想知道四人的平均工资的话,就得需要通过多方安全计算来解决问题。
当然上述的基础是建立在所有人都诚实的加上自己的工资情况下才能成立。
本功法来自三千大道(博客园),由小仙:{Hndreamer}创作,本文章均采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可,转载请注明源功法及作者链接:https://www.cnblogs.com/Hndreamer/p/16917544.html