RSA加密方案
用到的算法:
1.快速模幂算法
def quickMod(x, n, p):
result = 1
while n > 0:
if n & 1: # 判断二进制最低位是否为1
result = (result * x) % p
x = (x * x) % p
n >>= 1 # 右移一位,相当于除以2
return result
这段代码是一个快速模幂算法,用于计算 (x^n \mod p) 的值。函数接受三个参数 x, n, p,分别代表底数、指数和模数。算法通过循环迭代的方式,将指数 n 转换为二进制形式,然后根据二进制形式逐位计算结果。具体来说,当二进制形式的 n 的最低位为 1 时,将结果 result 乘以 x 并对 p 取模;然后将 x 自乘并对 p 取模;最后将 n 右移一位(相当于除以 2)。最终得到的 result 就是 (x^n \mod p) 的值。
2.Miller-Rabin算法
def getprime():#Miller-Rabin算法
def is_prime(n, k=5):
if n <= 1 or (n > 2 and n % 2 == 0):
return False
elif n == 2 or n == 3:
return True
s, d = 0, n - 1
while d % 2 == 0:
s, d = s + 1, d // 2
for _ in range(k):
a = random.randint(2, n - 1)
x = pow(a, d, n)
if x == 1 or x == n - 1:
continue
for _ in range(s - 1):
x = pow(x, 2, n)
if x == n - 1:
break
else:
return False
return True
def generate_prime(min_value, max_value, k=5):
while True:
n = random.randint(min_value, max_value)
if is_prime(n, k):
return n
# 使用示例:
prime = generate_prime(10**528,10**529) # 生成一个10的16次方到10的17次方之间的素数
print(prime)
return prime
这段代码是一个用于生成素数的函数。它使用了Miller-Rabin算法来判断一个数是否为素数。
首先,代码定义了一个内部函数is_prime(n, k),其中n是待判断的数,k是进行Miller-Rabin算法的迭代次数。函数首先判断n是否小于等于1或者大于2且为偶数,如果是则返回False。然后判断n是否等于2或者3,如果是则返回True。
接下来,代码计算出n-1的二进制表示中最低位的1的位置s和d。然后进行k次迭代,每次迭代选择一个随机数a,计算x = a^d mod n。如果x等于1或者x等于n-1,则继续下一次迭代。否则,对x进行s-1次平方运算,如果得到的结果等于n-1,则继续下一次迭代。如果所有迭代都无法满足条件,则返回False。最后,如果所有迭代都通过了,函数返回True,表示n可能是一个素数。
接着,代码定义了另一个内部函数generate_prime(min_value, max_value, k),用于生成指定范围内的素数。函数使用一个无限循环,每次生成一个在[min_value, max_value]范围内的随机数n,并调用is_prime函数判断n是否为素数。如果是素数,则返回n。
最后,代码使用示例展示了如何使用这个函数来生成一个在10^3
到10^4之间的素数,并将结果打印出来。最后,函数返回生成的素数。
最终代码部分
但是只能加密数字,若想要加密字符则需要构造字典,可以参考这篇文章http://t.csdnimg.cn/buxyB
import math
import random
from sympy import mod_inverse
def quickMod(x, n, p):
result = 1
while n > 0:
if n & 1: # 判断二进制最低位是否为1
result = (result * x) % p
x = (x * x) % p
n >>= 1 # 右移一位,相当于除以2
return result
def RSA_encrypt(p, q, e, m):
n = p * q
c = quickMod(m, e, n)
return c
def RSA_decrypt(p, q, e, c):
n = p * q
d = mod_inverse(e, (p-1)*(q-1))
m = quickMod(c, d, n)
return m
def get_e(phi_n):
# 选择常用的e,这里以65537为例,它与大多数φ(n)互质
# 65537是费马素数,且NIST SP800-78 Rev 1 (2007) 曾强调“不允许使用比65537更低的公钥指数e”,但PKCS#1却从未有过类似的建议。
e = 65537
# 确保e与φ(n)互质
assert math.gcd(e, phi_n) == 1, "e must be coprime to phi(n)"
return e
def getprime():#Miller-Rabin算法
def is_prime(n, k=5):
if n <= 1 or (n > 2 and n % 2 == 0):
return False
elif n == 2 or n == 3:
return True
s, d = 0, n - 1
while d % 2 == 0:
s, d = s + 1, d // 2
for _ in range(k):
a = random.randint(2, n - 1)
x = pow(a, d, n)
if x == 1 or x == n - 1:
continue
for _ in range(s - 1):
x = pow(x, 2, n)
if x == n - 1:
break
else:
return False
return True
def generate_prime(min_value, max_value, k=5):
while True:
n = random.randint(min_value, max_value)
if is_prime(n, k):
return n
# 使用示例:
prime = generate_prime(10**3,10**4) # 生成一个10的3次方到10的4次方之间的素数
print(prime)
return prime
def get_valid_input(message):
while True:
try:
value = input(message)
return value
except ValueError:
print("无效的输入,请重新输入一个整数。")
if __name__ == "__main__":
m = int(get_valid_input("请输入明文: "))
p = int(getprime())
q = int(getprime())
phi_n = (p - 1) * (q - 1)
e = get_e(phi_n)
c = RSA_encrypt(p, q, e, m)
print("加密后的密文为:", c)
print("解密后的明文为:", RSA_decrypt(p, q, e, c))