步骤
- 素数生成
- 计算n的欧拉函数
- 选择随机与n互质整数e
- 生成整数d(e*d%m = 1)
素数生成
大素数生成方案选择Miller-Rabin检测,可以参考这篇文章:https://blog.youkuaiyun.com/qq_33828894/article/details/81358051
1.首先将输入的字符转为16进制数
def mess2long(message):
message_byte = bytes(message,encoding="utf-8")
num = int(binascii.b2a_hex(message_byte),16)
return num
2.计算素数
#开始选择p q
def random_prime(half_len):
while True:
n = random.randint(0, 1 << half_len)#求2^half_len之间的大数
if n % 2 != 0:
found = True
# 随机性测试
for i in range(0, 5): #5的时候错误率已经小于千分之一
if prime_test(n) == False:
found = False
break
if found == True:
return n
#Miller-Rabin
def prime_test(n):
"""
测试n是否为素数
"""
q = n - 1
k = 0
# 寻找k,q 是否满足2^k*q =n - 1
while q % 2 == 0:
k += 1
q = q // 2
a = random.randint(2, n - 2)
# 如果 a^q mod n= 1, n 可能是一个素数
if fast_mod(a, q, n) == 1:
return True
# 如果存在j满足 a ^ ((2 ^ j) * q) mod n == n-1, n 可能是一个素数
for j in range(0, k):
if fast_mod(a, (2 ** j) * q, n) == n - 1:
return True
# n 不是素数
return False
3.生成n e d
def generate_key(key_len): #key_len要比消息长度大
"""
生成n, e, d
"""
p = random_prime(key_len // 2)
q = random_prime(key_len // 2)
n = p * q
ph_n = (p -1) * (q -1)
print("ph_n:"+str(ph_n))
e = 65537 #e取固定值
d = generate_d(ph_n, e)
return (n ,e, d)
4.进行加密 / 解密
def fast_mod(b, n, m):
"""
快速幂
"""
ret = 1
tmp = b
while n:
if n & 0x1:
ret = ret * tmp % m
tmp = tmp * tmp % m
n >>= 1
return ret
全部代码附上Github
一些坑
- Python2环境下,字符串默认存储是二进制流,即str=bytes,因此可以这样转换。Python3二者有区分,因此需要将str转为bytes
- 进制转换
binascii.b2a_hex(data)意思是将二进制流data转为十六进制,data的每一个比特都被转为对应十六进制的2位,因此返回结果是data长度的二倍。
binascii.b2a_hex(data)意思是将十六进制串转为二进制流data,其中十六进制串长度必须是偶数,否则返回类型错误。
#实现读小端序显示十六进制
#way1 通过binascii包下方法
x=binascii.b2a_hex(str)
print(x.decode())
#way2 使用int.from_bytes()转为int
y = int.from_bytes(str,byteorder='little',signed='false')
print(hex(y))
参考
https://www.jianshu.com/p/fbb8bf7baa97
https://blog.youkuaiyun.com/qq_33828894/article/details/81358051
https://blog.youkuaiyun.com/qq_15727809/article/details/83513074
http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html
6729

被折叠的 条评论
为什么被折叠?



