import random # miller-rabin 算法素性检测 def isprime_mr(a,b=None): if b is None: b = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97] if a == 2:return True if a%2==0 or a==1:return False for x in b: t = a - 1 while t%2 == 0: v = pow(x,t,a)# python自带函数pow就带有快速幂取模功能 if v not in [0,1,a-1]: return False else: if v in [0,a-1]: break t //= 2 return True # Pollcard Rho 质因数分解,比普通质因分解更好的一种算法,能处理更大的数字 def prime_list_rho(n,root=None): # 之所以不用 def prime_list_rho(n,root=[]): 的方式是因为这里有坑 # 作为函数对象的内部参数的临时地址多次使用会一直引用一个地址, # 所以考虑到该参数最后会作为结果返回出去,所以需要考虑初始化处理 if root is None: root = [] if not root and n<2: raise ValueError(n) if isprime_mr(n): root.append(n) return root from random import randint from math import gcd while True: x = randint(0,n-1) + 1 c = randint(0,n-1) + 1 y = x i = j = 2 while True: x = ((x**2)+c)%n z = abs(x - y) d = gcd(z,n) if d>1 and d<n: prime_list_rho(d,root) prime_list_rho(n//d,root) return root if x == y: break if i == j: y = x j <<= 1 i += 1 # 根据长度随机迭代,获取质数 def get_prime(bitlen=1024): num = (1<<(bitlen-1)) + random.randint(0,1<<(bitlen-1)) | 1 while True: num += 2 if isprime_mr(num): return num # 扩展欧几里得算法获取乘法模逆元 def ex_gcd(a,b): if b == 0: return (1,0,a) (x, y, r) = ex_gcd(b,a%b) t = x x = y y = t - a//b*y return (x,y,r) # 根据二进制数字长度需求生成rsa密钥,length需要为2的倍数 def create_rsa_key(length=1024, e=65537): if e == 2: raise KeyError('The parameter E must not be equal to 2.') if length%2 != 0: raise KeyError('bit length must be even number') # 确保公共参数n的位数,以便保证密钥长度。 while True: p = get_prime(length//2) q = get_prime(length//2) n = p * q if n.bit_length() == length and p != q: break fn = (p-1) * (q-1) a, b, r = ex_gcd(fn, e) if b == 1: return create_rsa_key(length, e) # 值得注意的是,如果模拟元 b 等于 1 时就会出现 rsa 加密失效的情况,需要非常注意 # 同时 当加密参数 e == 2 的时候模拟元基本就等于 1 所以,加密参数一定不能是 2 # 当 e 为大于 2 的素数并且 e 的值很小时会有一定几率模拟元等于 1 的情况 # 公钥n,e 私钥n,d d = b + fn if b < 0 else b return e,d,n def get_d_from_e_n(e, n): p, q = prime_list_rho(n) fn = (p-1) * (q-1) a, b, r = ex_gcd(fn, e) d = b + fn if b < 0 else b return d, p, q if __name__ == '__main__': print('============= test =============') # 测试rsa密钥生成效率 e,d,n = create_rsa_key(1024,17)#默认生成1024位的密钥 print('(rsa publicKey n,e) {} --- {}'.format(n,e)) print('(rsa PrivateKey n,d) {} --- {}'.format(n,d)) print('============= test =============') # 测试rsa密钥加密解密 # rsa可以加解密一个 1024bit 位的数据,所以通常加密数据过长就需要切分处理 def test(o): print('(rsa original data) {}'.format(o)) c = pow(o,e,n) # 加密 v = pow(c,d,n) # 解密 print('(rsa decoding data) {}'.format(v)) print('(rsa encoding data) {}'.format(c)) test(12345678987654321) test(11111111111111111222222222222222222222000) test(33333333333333333333333333333333333333333333333) print();print();print() # 测试质因数分解 def test_rho(num): print('=========== Pollcard Rho ============') import time c = time.time() try: print(v) except: pass v = prime_list_rho(num) q = 1 for i in v: q *= i print('prime_list',v) print('test num: ',num) print('multiplicative:',q) print('cost time:',time.time()-c) test_rho(12345678987654321) test_rho(2222222222222222222222222222)