密码学|实验三 RSA算法

实验目的:

掌握模幂和模逆的实现算法;通过 RSA 加密和签名算法,了解基于大数分解问题的公钥密码。

实验内容:

  1. 实现模幂和模逆算法
  2. 实现 RSA 加密算法
  3. 实现 RSA 签名算法

实验步骤:

  1. 采用从右到左算法实现模幂运算。
  2. 采用扩展欧几里得算法实现模逆运算。
  3. 生成公私钥对。
  4. 对消息 m,利用模幂程序得到 RSA 密文 c,再验证 c 解密后验证是否为 m
  5. 对消息 m,得到 RSA 签名 s,再验证 s 的正确性。
  6. 改变密钥对和消息,重复上述过程,将实验结果填入表

实验过程

使用Miller-Rabin素性测试确保生成大素数

生成素数
import random
def Miller_Rabin_is_prime(n, k=5):
    """Miller-Rabin素性测试"""
    if n <= 1:
        return False
    elif n <= 3:
        return True
    elif n % 2 == 0:
        return False
    d = n - 1
    s = 0
    while d % 2 == 0:
        d //= 2
        s += 1
    
    for _ in range(k):
        a = random.randint(2, n - 2)
        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(bits):
    """生成指定位数的素数"""
    while True:
        p = random.getrandbits(bits)
        p |= (1 << bits - 1) | 1
        if Miller_Rabin_is_prime(p):
            return p

使用拓展欧几里得算法实现模逆运算

拓展欧几里得算法
def extended_gcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = extended_gcd(b % a, a)
        return (g, x - (b // a) * y, y)

def mod_inverse(a, m):
    g, x, y = extended_gcd(a, m)
    if g != 1:
        raise ValueError("模逆不存在")
    else:
        return x % m

实现快速模幂运算

快速模幂运算
def fast_modular_exponentiation(m, d, n):
    """
    快速模幂运算
    """
    # 将指数d转换为二进制字符串
    binary_d = bin(d)[2:]  
    k = len(binary_d)  
    x = 1
    y = m % n  

    for i in range(k):
        a_i = int(binary_d[i])
        if a_i == 1:
            x = (x * y) % n
            y = (y * y) % n
        else:
            y = (y * y) % n
    return x
生成公私钥对
密钥生成
def generate_keypair(bits=1024):
    p = generate_prime(bits // 2)
    q = generate_prime(bits // 2)
    while p == q:
        q = generate_prime(bits // 2)
    
    n = p * q
    phi = (p - 1) * (q - 1)
    print(f"φ(n) = {phi}")
    while True:
        try:
            e = int(input("输入e值(建议为65537): "))
            if math.gcd(e, phi) != 1:
                print("Error,e必须与φ(n)互质")
            elif e < 2 or e >= phi:
                print("Error,e必须在2和φ(n)-1之间")
            else:
                break
        except ValueError:
            print("错误:请输入一个有效的整数。")
    
    d = mod_inverse(e, phi)
    
    public_key = (e, n)
    private_key = (d, n)
    
    return public_key, private_key

完成具体RSA功能

RSA功能实现
def rsa_encrypt(public_key, plaintext):
    e, n = public_key
    if plaintext >= n:
        raise ValueError("明文必须小于n")
    return fast_modular_exponentiation(plaintext, e, n)

def rsa_decrypt(private_key, ciphertext):
    d, n = private_key
    return fast_modular_exponentiation(ciphertext, d, n)

def rsa_sign(private_key, message):
    return rsa_encrypt(private_key, message)

def rsa_verify(public_key, signature, message):
    decrypted = rsa_decrypt(public_key, signature)
    return decrypted == message

实验结果

n e d m s 签名 c decrypt
6607361578056698093 65537 743236179797604353 231213 4782700734081529582 2836956322425680191 231213
5872539187104964069 65537 896154300040522913 12345 2830542832659584526 2830542832659584526 12345
52259664338030243 65537 12057591550917377 231213 14506512871382930 14506512871382930 231213
26487264889 65537 1181337469 10101100 10505105852 10505105852 10101100
50665843 15647509 3856949 250616 38387790 38387790 250616

image

实验代码

import math
import random

def Miller_Rabin_is_prime(n, k=5):
    """Miller-Rabin素性测试"""
    if n <= 1:
        return False
    elif n <= 3:
        return True
    elif n % 2 == 0:
        return False
    d = n - 1
    s = 0
    while d % 2 == 0:
        d //= 2
        s += 1
    
    for _ in range(k):
        a = random.randint(2, n - 2)
        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(bits):
    """生成指定位数的素数"""
    while True:
        p = random.getrandbits(bits)
        p |= (1 << bits - 1) | 1
        if Miller_Rabin_is_prime(p):
            return p


def extended_gcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = extended_gcd(b % a, a)
        return (g, x - (b // a) * y, y)

def mod_inverse(a, m):
    g, x, y = extended_gcd(a, m)
    if g != 1:
        raise ValueError("模逆不存在")
    else:
        return x % m
def fast_modular_exponentiation(m, d, n):
    """
    快速模幂运算
    """
    # 将指数d转换为二进制字符串
    binary_d = bin(d)[2:]  
    k = len(binary_d)  
    x = 1
    y = m % n  

    for i in range(k):
        a_i = int(binary_d[i])
        if a_i == 1:
            x = (x * y) % n
            y = (y * y) % n
        else:
            y = (y * y) % n

    return x

def generate_keypair(bits=1024):
    p = generate_prime(bits // 2)
    q = generate_prime(bits // 2)
    while p == q:
        q = generate_prime(bits // 2)
    
    n = p * q
    phi = (p - 1) * (q - 1)
    print(f"φ(n) = {phi}")
    while True:
        try:
            e = int(input("输入e值(建议为65537): "))
            if math.gcd(e, phi) != 1:
                print("Error,e必须与φ(n)互质")
            elif e < 2 or e >= phi:
                print("Error,e必须在2和φ(n)-1之间")
            else:
                break
        except ValueError:
            print("错误:请输入一个有效的整数。")
    
    d = mod_inverse(e, phi)
    
    public_key = (e, n)
    private_key = (d, n)
    
    return public_key, private_key

def rsa_encrypt(public_key, plaintext):
    e, n = public_key
    if plaintext >= n:
        raise ValueError("明文必须小于n")
    return fast_modular_exponentiation(plaintext, e, n)

def rsa_decrypt(private_key, ciphertext):
    d, n = private_key
    return fast_modular_exponentiation(ciphertext, d, n)

def rsa_sign(private_key, message):
    return rsa_encrypt(private_key, message)

def rsa_verify(public_key, signature, message):
    decrypted = rsa_decrypt(public_key, signature)
    return decrypted == message

def main():
    print("\n生成RSA密钥对")
    public_key, private_key = generate_keypair()
    print(f"\n公钥 (e, n): {public_key}")
    print(f"私钥 (d, n): {private_key}")
    
    while True:
        print("\n请选择操作:")
        print("1. 加密")
        print("2. 解密")
        print("3. 签名")
        print("4. 验证签名")
        print("5. 退出")
        
        choice = input("请输入选项(1-5): ")
        
        if choice == '1':
            try:
                plaintext = int(input("请输入要加密的明文: "))
                ciphertext = rsa_encrypt(public_key, plaintext)
                print(f"加密结果: {ciphertext}")
            except ValueError as e:
                print(f"错误: {e}")
        
        elif choice == '2':
            try:
                ciphertext = int(input("请输入要解密的密文: "))
                plaintext = rsa_decrypt(private_key, ciphertext)
                print(f"解密结果: {plaintext}")
            except ValueError as e:
                print(f"错误: {e}")
        
        elif choice == '3':
            try:
                message = int(input("请输入要签名的消息: "))
                signature = rsa_sign(private_key, message)
                print(f"签名结果: {signature}")
            except ValueError as e:
                print(f"错误: {e}")
        
        elif choice == '4':
            try:
                signature = int(input("请输入要验证的签名: "))
                message = int(input("请输入原始消息: "))
                if rsa_verify(public_key, signature, message):
                    print("验证成功: 签名有效")
                else:
                    print("验证失败: 签名无效")
            except ValueError as e:
                print(f"错误: {e}")
        
        elif choice == '5':
            print("退出系统。")
            break
        
        else:
            print("无效选项,请重新输入。")

def test_rsa():
    x = int(input("请输入素数位数:"))
    (e,n),(d,n) = generate_keypair(x)
    print("n=", n)
    print("e=", e)
    print("d=", d)
    m = int(input("m="))
    c = fast_modular_exponentiation(m, e, n)
    print("c=", c)
    c = fast_modular_exponentiation(c, d, n)
    print("decrypt=", c)
    s = rsa_sign((e,n),m)
    print("s=", s)
                

if __name__ == "__main__":
    test_rsa()

posted @ 2025-06-17 16:14  lumiere_cloud  阅读(61)  评论(0)    收藏  举报