一、实验目的
- 理解和掌握RSA加密和解密的基本原理。
- 学习如何使用Python进行RSA加密和解密操作。
- 理解公钥和私钥在加密通信中的应用。
二、实验内容
2.1 RSA加密和解密
给定以下Python代码,该代码实现了一个简单的RSA加密和解密过程:
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes, inverse
def generate_keys(bit_length=512):
p = getPrime(bit_length)
q = getPrime(bit_length)
n = p * q
phi = (p - 1) * (q - 1)
e = 65537
d = inverse(e, phi)
return ((e, n), (d, n))
def encrypt(message, public_key):
e, n = public_key
m = bytes_to_long(message)
c = pow(m, e, n)
return c
def decrypt(ciphertext, private_key):
d, n = private_key
m = pow(ciphertext, d, n)
message = long_to_bytes(m)
return message
# 生成公钥和私钥
public_key, private_key = generate_keys()
# 加密消息
message = b"Hello, RSA!"
ciphertext = encrypt(message, public_key)
print("加密后的密文:", ciphertext)
# 解密消息
decrypted_message = decrypt(ciphertext, private_key)
print("解密后的消息:", decrypted_message)
任务1:
运行上述代码,观察加密和解密的结果,将运行截图粘贴在下方空白处:
【实验结果】:
1. 首先安装所需要的pycryptodome库
2. 运行代码(两次),打印出公钥、私钥、加密后的密文以及解密后的消息
【分析】:由于每次运行时产生的素数p , q是随机的,所以每次生成的公钥、私钥各不相同,因此使用公钥加密后的密文也不同,但都成功的解密出原始消息b"Hello, RSA!"。
2.2 解密挑战
分析下面的代码:
from Crypto.Util.number import *
def generate_rsa_keys():
prime1 = getPrime(12)
prime2 = getPrime(12)
secret_message =r’你的专属加密信息{flag}’
message_integer = bytes_to_long(secret_message)
encryption_exponent = 65537
modulus = prime1 * prime2
encrypted_message = pow(message_integer, encryption_exponent, modulus)
print(modulus, encryption_exponent, encrypted_message)
return prime1, prime2
def encrypt_sum_of_primes(prime1, prime2):
large_prime1 = getPrime(24)
large_prime2 = getPrime(24)
new_encryption_exponent = 65537
sum_of_primes = prime1 + prime2
new_modulus = large_prime1 * large_prime2
new_encrypted_message = pow(sum_of_primes, new_encryption_exponent, new_modulus)
print(new_modulus, new_encryption_exponent, new_encrypted_message, (large_prime1 + 1) * (large_prime2 + 1))
prime1, prime2 = generate_rsa_keys()
encrypt_sum_of_primes(prime1, prime2)
任务2:
根据附件中你的专属输出,解密出原始消息flag(将代码单独提交): b’666’
【实验结果】:
成功解密出原始消息flag
【解题思路】:
专属加密信息设置为: flag = b’666’
得到的专属输出为:
10316951 65537 5291271
102502415603123 65537 50723952663102 102502435865760
解题思路的流程图如下:
1. 根据 new_modulus和value = (large_prime1 + 1) * (large_prime2 + 1)的值,我们可以通过调用find_primes_1函数找出第二次加密过程的大素数:
Large Prime 1: 9755567 Large Prime 2: 10507069
2. 根据Large Prime 1和Large Prime 2的值,我们可以解密第二次加密过程,从而得到第一次加密过程两个素数的和:
Prime 1 + Prime 2: 6600
3. 再根据第一次加密过程的两素数之和,以及modulus,我们可以通过调用find_primes_2函数找出第一次加密过程的素数:
Prime 1: 4057 Prime 2: 2543
4. 最后根据Prime 1和Prime 2,我们可以解密第一次加密过程,从而得到原始消息的值,并将其转化为字节序列,最终得到原始消息:
flag: b'666'
【实验代码】:
from Crypto.Util.number import *
# 第一次加密,加密原始消息
def generate_rsa_keys():
prime1 = getPrime(12)
prime2 = getPrime(12)
secret_message = b'999'
message_integer = bytes_to_long(secret_message)
encryption_exponent = 65537
modulus = prime1 * prime2
encrypted_message = pow(message_integer, encryption_exponent, modulus)
print(modulus, encryption_exponent, encrypted_message, prime1, prime2)
return modulus, encryption_exponent, encrypted_message, prime1, prime2
# 第二次加密,加密第一次加密产生的 p1 p2 的和
def encrypt_sum_of_primes(prime1, prime2):
large_prime1 = getPrime(24)
large_prime2 = getPrime(24)
new_encryption_exponent = 65537
sum_of_primes = prime1 + prime2 # p1 + p2
new_modulus = large_prime1 * large_prime2
new_encrypted_message = pow(sum_of_primes, new_encryption_exponent, new_modulus)
print(new_modulus, new_encryption_exponent, new_encrypted_message,
(large_prime1 + 1) * (large_prime2 + 1), large_prime1, large_prime2)
return new_modulus, new_encrypted_message, (large_prime1 + 1) * (large_prime2 + 1)
# 寻找第二次加密过程中的大素数
def find_primes_1(new_modulus, value):
for i in range(2 ** 12, 2 ** 24):
if new_modulus % i == 0 and isPrime(i):
prime1 = i
prime2 = new_modulus // i
if (prime1 + 1) * (prime2 + 1) == value:
return prime1, prime2
# 寻找第一次加密过程中的素数(判别式法)
def find_primes_2(modulus, sum_of_primes):
delta = sum_of_primes ** 2 - 4 * modulus
# 没有实数解
if delta < 0:
return None, None
# 计算判别式的平方根
sqrt_delta = int(delta ** 0.5)
# 计算p1和p2
p1 = (sum_of_primes + sqrt_delta) // 2
p2 = sum_of_primes - p1
# p1和p2不是素数
if p1 * p2 != modulus or not isPrime(p1) or not isPrime(p2):
return None, None
return p1, p2
# 获得专属输出
modulus, e, encrypted_message, prime1, prime2 = generate_rsa_keys()
new_modulus, new_encrypted_message, value = encrypt_sum_of_primes(prime1, prime2)
# 打印第二次加密过程的大素数
large_prime1, large_prime2 = find_primes_1(new_modulus, value)
print("Large Prime 1:", large_prime1)
print("Large Prime 2:", large_prime2)
# 对第二次加密过程进行解密,求出第一次加密过程的两个素数之和
r2 = (large_prime1 - 1) * (large_prime2 - 1)
d2 = inverse(e, r2)
sum_of_primes = pow(new_encrypted_message, d2, new_modulus)
print('Prime 1 + Prime 2:', sum_of_primes)
# 打印第一次加密过程的素数
p1, p2 = find_primes_2(modulus, sum_of_primes)
print("Prime 1:", p1)
print("Prime 2:", p2)
# 对第一次加密过程进行解密,并转化为字节序列,得到原始消息
r1 = (p1 - 1) * (p2 - 1)
d1 = inverse(e, r1)
flag = pow(encrypted_message, d1, modulus)
flag = long_to_bytes(flag)
print("flag:", flag)
2.3 进阶挑战
分析下面的代码:
from Crypto.Util.number import *
def generate_rsa_keys():
prime1 = getPrime(12)
prime2 = getPrime(12)
secret_message =r’{flag}’
message_integer = bytes_to_long(secret_message)
encryption_exponent = 65537
modulus = prime1 * prime2
encrypted_message = pow(message_integer, encryption_exponent, modulus)
print(modulus, encryption_exponent, encrypted_message)
return prime1, prime2
def encrypt_sum_of_primes(prime1, prime2):
large_prime1 = getPrime(12)
large_prime2 = getPrime(12)
new_encryption_exponent = 65537
sum_of_primes = prime1 * prime2
new_modulus = large_prime1 * large_prime2
new_encrypted_message = pow(sum_of_primes, new_encryption_exponent, new_modulus)
print(new_modulus, new_encryption_exponent, new_encrypted_message, (large_prime1 + 1) * (large_prime2 + 1))
prime1, prime2 = generate_rsa_keys()
encrypt_sum_of_primes(prime1, prime2)
任务3:
对于下面给定的输出,解密出原始消息flag:
9629309 65537 974875
11688661 65537 3061056 11681824
将解密代码结果写在后面(代码文件单独提交): b'123'
【实验结果】:
解密得到第一次加密过程的素数为:2689 3581,以及原始消息flag = b'123'
【解题思路】:
解题思路的流程图如下:
1. 根据第一次加密过程的modulus,我们使用费马因式分解法暴力求出第一次加密过程的两个素数:
Prime 1: 2689 Prime 2: 3581
2. 根据Prime 1和Prime 2,我们可以解密第一次加密过程,从而得到原始消息的值,并将其转化为字节序列,最终得到原始消息:
flag = b'123'
【实验代码】:
from Crypto.Util.number import *
import math
modulus, encryption_exponent, encrypted_message= 9629309, 65537, 974875
new_modulus, new_encryption_exponent, new_encrypted_message,phi2=11688661, 65537, 3061056, 11681824
# 费马因式分解函数 对一个给定奇数进行因式分解, 对于给定的n,找到a, b使得a^2 - b^2 = n,则n可以因式分解为(a+b)和(a-b)
# 具体实现是通过检查a^2 - n 是否是完全平方数,是的话则存在b,不是则增加a的值
def fermat(modulus):
assert modulus % 2 != 0
a = math.ceil(math.sqrt(modulus)) # 计算它的平方根,然后对结果进行向上取整
b_2 = a * a - modulus
while not is_square(b_2):
a += 1
b_2 = a * a - modulus
return a - int(math.sqrt(b_2)), a + int(math.sqrt(b_2))
# 检查一个数是否为完全平方数
def is_square(n):
return int(math.sqrt(n)) ** 2 == n
# 寻找第一次加密过程的素数
p, q = fermat(modulus)
print("第一次加密过程的素数为:", p, q)
# 对第一次加密过程进行解密
phi = (p - 1) * (q - 1)
d = inverse(encryption_exponent, phi)
m = pow(encrypted_message, d, modulus)
# 转换为字节序列,得到原始消息
flag = long_to_bytes(m)
print("flag = ", flag)