系统安全实验 ---- RSA加密与解密实践

一、实验目的

  • 理解和掌握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(将代码单独提交): b666          

【实验结果】:

成功解密出原始消息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 1Large Prime 2的值,我们可以解密第二次加密过程,从而得到第一次加密过程两个素数的和:

        Prime 1 + Prime 2: 6600

3. 再根据第一次加密过程的两素数之和,以及modulus,我们可以通过调用find_primes_2函数找出第一次加密过程的素数:

        Prime 1: 4057 Prime 2: 2543

4. 最后根据Prime 1Prime 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 1Prime 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)

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值