【杭电密码学实验】python实现 超大整数 RSA 快速加解密

 

  

代码如下: 

import random
from random import randint
import sys


sys.setrecursionlimit(100000)#修改默认递归深度为100000

'''
超大整数超大次幂然后对超大的整数取模
(base ^ exponent) mod n
'''


def exp_mode(base, exponent, n):
    bin_array = bin(exponent)[2:][::-1]
    r = len(bin_array)
    base_array = []

    pre_base = base
    base_array.append(pre_base)

    for _ in range(r - 1):
        next_base = (pre_base * pre_base) % n
        base_array.append(next_base)
        pre_base = next_base

    a_w_b = __multi(base_array, bin_array, n)
    return a_w_b % n


def __multi(array, bin_array, n):
    result = 1
    for index in range(len(array)):
        a = array[index]
        if not int(bin_array[index]):
            continue
        result *= a
        result = result % n  # 加快连乘的速度
    return result


# 求两个数字的最大公约数(欧几里得算法)
def gcd(a, b):
    if b == 0:
        return a
    else:
        return gcd(b, a % b)


'''
扩展欧几里的算法
计算 ax + by = 1中的x与y的整数解(a与b互质)
'''


def ext_gcd(a, b):
    if b == 0:
        x1 = 1
        y1 = 0
        x = x1
        y = y1
        r = a
        return r, x, y
    else:
        r, x1, y1 = ext_gcd(b, a % b)
        x = y1
        y = x1 - a // b * y1
        return r, x, y


def rabin_miller(num):  # rabin_miller算法
    s = num - 1
    t = 0
    while s % 2 == 0:
        s = s // 2
        t += 1

    for trials in range(5):
        a = random.randrange(2, num - 1)
        v = pow(a, s, num)
        if v != 1:
            i = 0
            while v != (num - 1):
                if i == t - 1:
                    return False
                else:
                    i = i + 1
                    v = (v ** 2) % num
    return True


def is_prime(num):  # 素数判断
    # 排除0,1和负数
    if num < 2:
        return False

    # 创建小素数的列表,可以大幅加快速度
    # 如果是小素数,那么直接返回true
    small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
                    103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
                    211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
                    331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
                    449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577,
                    587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
                    709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
                    853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
                    991, 997]
    if num in small_primes:
        return True

    # 如果大数是这些小素数的倍数,那么就是合数,返回false
    for prime in small_primes:
        if num % prime == 0:
            return False

    # 如果这样没有分辨出来,就一定是大整数,那么就调用rabin算法
    return rabin_miller(num)


# 得到大整数,默认位数为1024
def get_prime(key_size=1024):  # 此处设置素数位数
    while True:
        num = random.randrange(2 ** (key_size - 1), 2 ** key_size)
        if is_prime(num):
            return num


# 字符转换成asc
def Transfer_To_Ascii(messages):
    result = []
    for message in messages:
        result.append(ord(message))
    return result


def is_sushu(sushu):
    for i in range(2, sushu):
        if sushu % i == 0:
            return False
    return True


def Is_Huzhi(a, b):
    while a % b:  # 辗转相除法判断互质
        a, b = b, a % b
    if b > 1:
        return False
    else:
        return True


def Creat_E(oula):
    top = oula
    while True:
        i = randint(2, top)
        for e in range(i, top):
            if Is_Huzhi(e, oula):
                return e
        top = i


# 生成公钥私钥,p、q为两个超大质数
def gen_key(p, q):
    n = p * q
    fy = (p - 1) * (q - 1)  # 计算与n互质的整数个数 欧拉函数
    e = Creat_E(fy)  # 选取e
    a = e
    b = fy
    r, x, y = ext_gcd(a, b)
    # 计算出的x不能是负数,如果是负数,说明p、q、e选取失败,不过可以把x加上fy,使x为正数,才能计算。
    if x < 0:
        x = x + fy
    d = x
    # 返回:   公钥     私钥
    return (n, e), (n, d)


# 加密 m是被加密的信息 加密成为c
def encrypt(m, pubkey):
    n = pubkey[0]
    e = pubkey[1]

    c = exp_mode(m, e, n)
    return c


# 解密 c是密文,解密为明文m
def decrypt(c, selfkey):
    n = selfkey[0]
    d = selfkey[1]

    m = exp_mode(c, d, n)
    return m


if __name__ == "__main__":
    p = get_prime()
    q = p
    while p == q:
        q = get_prime()
    '''生成公钥私钥'''
    pubkey, selfkey = gen_key(p, q)
    print('输入明文:')
    text = input()
    m1 = Transfer_To_Ascii(text)
    length = len(m1)
    c_list = []
    for i in m1:
        c_list.append(encrypt(i, pubkey))
    print('密文:')
    print(c_list)
    b_list = []
    for i in c_list:
        b_list.append(decrypt(i, selfkey))
    print('解密后:')
    for i in b_list:
        print(chr(i), end='')

参考博客:

RSA加密算法Python实现_feng锋~的博客-CSDN博客_rsa算法python实现https://blog.csdn.net/qq_49597570/article/details/11378911425行代码实现完整的RSA算法(Python3.X版本)_※六边形战士※的博客-CSDN博客_rsa算法pythonhttps://blog.csdn.net/bian_h_f612701198412/article/details/87202462生成大素数(python实现),包含素性检测_钢琴线与小刀的博客-CSDN博客_python生成大素数https://blog.csdn.net/qq_38115310/article/details/88034676?ops_request_misc=&request_id=&biz_id=102&utm_term=python%20%E5%A4%A7%E6%95%B4%E6%95%B0%E7%B4%A0%E6%80%A7%E7%9B%91%E6%B5%8B&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-88034676.nonecase&spm=1018.2226.3001.4187

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值