RSA算法实现以及一些坑

步骤

  • 素数生成
  • 计算n的欧拉函数
  • 选择随机与n互质整数e
  • 生成整数d(e*d%m = 1)
素数生成

大素数生成方案选择Miller-Rabin检测,可以参考这篇文章:https://blog.youkuaiyun.com/qq_33828894/article/details/81358051
1.首先将输入的字符转为16进制数

def mess2long(message):
     message_byte = bytes(message,encoding="utf-8")
     num = int(binascii.b2a_hex(message_byte),16)
     return num

2.计算素数

#开始选择p q
def random_prime(half_len):
    while True:
        n = random.randint(0, 1 << half_len)#求2^half_len之间的大数
        if n % 2 != 0:
            found = True
            # 随机性测试
            for i in range(0, 5):   #5的时候错误率已经小于千分之一
                if prime_test(n) == False:
                    found = False
                    break
            if found == True:
                return n

#Miller-Rabin
def prime_test(n):
        """
        测试n是否为素数
        """
        q = n - 1
        k = 0
        # 寻找k,q 是否满足2^k*q =n - 1
        while q % 2 == 0:
            k += 1
            q = q // 2
        a = random.randint(2, n - 2)
        # 如果 a^q mod n= 1, n 可能是一个素数
        if fast_mod(a, q, n) == 1:
            return True
        # 如果存在j满足 a ^ ((2 ^ j) * q) mod n == n-1, n 可能是一个素数
        for j in range(0, k):
            if fast_mod(a, (2 ** j) * q, n) == n - 1:
                return True
        # n 不是素数
        return False

3.生成n e d

def generate_key(key_len): #key_len要比消息长度大
    """
    生成n, e, d
    """
    p = random_prime(key_len // 2)
    q = random_prime(key_len // 2)
    n  = p * q
    ph_n = (p -1) * (q -1)
    print("ph_n:"+str(ph_n))
    e = 65537 #e取固定值
    d = generate_d(ph_n, e)
    return (n ,e, d)

4.进行加密 / 解密

def fast_mod(b, n, m):
    """
    快速幂
    """
    ret = 1
    tmp = b
    while n:
        if n & 0x1:
            ret = ret * tmp % m
        tmp = tmp * tmp % m
        n >>= 1
    return ret

全部代码附上Github

一些坑
  • Python2环境下,字符串默认存储是二进制流,即str=bytes,因此可以这样转换。Python3二者有区分,因此需要将str转为bytes
  • 进制转换
    binascii.b2a_hex(data)意思是将二进制流data转为十六进制,data的每一个比特都被转为对应十六进制的2位,因此返回结果是data长度的二倍。
    binascii.b2a_hex(data)意思是将十六进制串转为二进制流data,其中十六进制串长度必须是偶数,否则返回类型错误。
#实现读小端序显示十六进制
#way1  通过binascii包下方法
x=binascii.b2a_hex(str)
print(x.decode())

#way2  使用int.from_bytes()转为int
y = int.from_bytes(str,byteorder='little',signed='false')
print(hex(y))
参考

https://www.jianshu.com/p/fbb8bf7baa97
https://blog.youkuaiyun.com/qq_33828894/article/details/81358051
https://blog.youkuaiyun.com/qq_15727809/article/details/83513074
http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值