RSA密码算法 + python代码

RSA算法描述

​ RSA( Rivest-Shamir-Adleman )是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

RSA 的加密和解密

密钥对:公钥:( e , n ) ; 私钥:( d , n ) 。e: encryption d: decryption n: number

加密: c = m e   m o d   n c = m^e \ mod \ n c=me mod n

解密: m = c d   m o d   n m = c^d \ mod \ n m=cd mod n

在这里插入图片描述

生成密钥对

n = p ⋅ q n = p \cdot q n=pq

φ ( n ) = ( p − 1 ) ⋅ ( q − 1 ) \varphi (n) = (p - 1) \cdot (q - 1) φ(n)=(p1)(q1)

加密钥 e 满足 g c d ( e ,   φ ( n ) ) = 1 gcd(e,\ \varphi(n) ) = 1 gcd(e, φ(n))=1 且 e 是素数

解密钥 d 满足 e ⋅ d   m o d   φ (   n   ) = 1 e\cdot d\ mod\ \varphi(\,n\,) = 1 ed mod φ(n)=1 , 即 e 在模 m 上的逆元

RSA 算法证明

(1)m 和 n 互素

利用欧拉定理证明:

c = m e   m o d   n c = m^e \ mod \ n c=me mod n

c d   m o d   n = m e d   m o d   n c^d\ mod\ n = m^{ed}\ mod\ n cd mod n=med mod n # 等式两边同时取 d 次幂, 再取模;

= m k φ ( n ) + 1   m o d   n = m^{k\varphi(n)+1}\ mod\ n =mkφ(n)+1 mod n # 因为 e,d 满足 e ⋅ d   m o d   φ (   n   ) = 1 e\cdot d\ mod\ \varphi(\,n\,) = 1 ed mod φ(n)=1 ,所以 e d = k φ ( n ) + 1 ed = k\varphi(n)+1 ed=kφ(n)+1

= m   ( m φ ( n )   m o d   n ) k   m o d   n = m\ (m^{\varphi(n)}\ mod\ n)^k\ mod\ n =m (mφ(n) mod n)k mod n # 乘法取模的结合律 m φ ( n )   ≡ 1   m o d   n m^{\varphi(n)}\ \equiv 1\ mod\ n mφ(n) 1 mod n

= m   m o d   n = m\ mod\ n =m mod n # 因为 m 和 n 互素,所以根据欧拉定理,有 m φ ( n )   m o d   n = 1 m^{\varphi(n)}\ mod\ n = 1 mφ(n) mod n=1

(2)m 和 n 不互素

因为m,n不互素,意味着m,n有公约数。故 m 只能是 p 或 q 的倍数。由于 m<n , 所以 m 不能是 pq 的倍数。因此无论 m 是 p 的倍数还是 q 的倍数,只需要证明其一,另一个同理可证。

不妨设 m = tp , 其中 t 为整数,则 gcd(m, q) = 1. 由欧拉定理:

m φ ( q ) ≡ 1   m o d   q m^{\varphi(q)}\equiv 1\ mod\ q mφ(q)1 mod q

( m φ ( q ) ) k φ ( p ) ≡ 1 φ ( p )   m o d   q (m^{\varphi(q)})^{k\varphi(p)}\equiv 1^{\varphi(p)}\ mod\ q (mφ(q))kφ(p)1φ(p) mod q

m k φ ( n ) ≡ 1   m o d   q m^{k\varphi(n)}\equiv 1\ mod\ q mkφ(n)1 mod q

因此,存在一个整数 r 使得 m k φ ( n ) = r q + 1 m^{k\varphi(n)}= rq+1 mkφ(n)=rq+1 ,此时,等式两边同乘 m = tp 得:
m k φ ( n ) + 1 = m + r q t p = m + r t n 即   m k φ ( n ) + 1 ≡ m + ( t r ) n   m o d   n ≡ m   m o d   n m^{k\varphi(n)+1} = m + rqtp = m + rtn \\ 即\ m^{k\varphi(n)+1}\equiv m+(tr)n\ mod\ n\equiv m\ mod\ n mkφ(n)+1=m+rqtp=m+rtn mkφ(n)+1m+(tr)n mod nm mod n
综上所述:无论 m 与 n 是否互素,此算法成立。

代码部分:

import random

def fastExpMod(b, n, m):
    '''
    return : b^n mod m
    '''
    result = 1
    while n != 0:
        if (n & 1) == 1:  # 按位与操作
            result = (result * b) % m
        b = (b * b) % m
        n = n >> 1  # 位数右移操作
    return result


def Euclid(a, b):
    '''
    欧几里得算法 ax + by = gcd(a,b)
    Return : [x , y , gcd(a,b)]
    '''
    X = [1, 0, a]
    Y = [0, 1, b]
    while Y[2] != 0:
        Q = X[2] // Y[2]
        NEW_Y = [i * Q for i in Y]
        T = list(map(lambda x: x[0] - x[1], zip(X, NEW_Y)))
        X = Y.copy()
        Y = T.copy()
    return X


def fermatPrimeTest(m, k):
    '''
    费马素性检验算法
    m : 给定整数
    k : 安全参数,重复K次
    '''
    if m % 2 == 0:
        return False
    for i in range(k):
        a = random.randint(2, m - 2)
        g = Euclid(a, m)
        if g[2] == 1:
            r = fastExpMod(a, m - 1, m)
            if r == 1:
                continue
            else:
                return False
        else:
            return False
    return True


def findPrime(lower, upper):
    '''
    return : 一个位于upper和lower之间的素数
    '''
    while True:
        n = random.randint(lower, upper)
        if fermatPrimeTest(n, 6) == True:
            return n


def selectE(fn):
    '''
    fn : euler function
    Return : e
    '''
    while True:
        e = random.randint(1, fn)
        temp = Euclid(e, fn)
        if temp[2] == 1:
            return e


def keyGenerate(lower, upper):
    '''
    给定两个素数p和q生成的区间
    return : e,n,d
    '''
    p = findPrime(lower, upper)
    q = findPrime(lower, upper)
    print("p:" + str(p) + "   q:" + str(q))
    # print("q:"+str(q))
    n = p * q
    fn = (p - 1) * (q - 1)
    e = selectE(fn)
    temp = Euclid(e, fn)  # 欧几里得算法求逆元
    d = temp[0]
    if d < 0:  # 由于e和fn互素故一定存在逆元
        d = d + fn  # 保证d为正数
    return e, n, d


def Encryption_Decryption():
    e, n, d = keyGenerate(1000, 10000)  # 密钥生成
    # 更改keyGenerate函数的两个参数,可以改变生成素数的位数大小。
    print("public key (e,n):", end="")
    print("(" + str(e) + "  ,  " + str(n) + ")\n")
    print("private key d: " + str(d) + "\n")
    m = random.randint(1, n)  # m < n m为明文
    print("Plaintext: " + str(m))
    c = fastExpMod(m, e, n)  # 加密  c为密文 m^e mod n
    print("\nEncryption of PlainText: " + str(c))
    x = fastExpMod(c, d, n)  # 解密 c^d mod n
    print("\nDecryption of CipherText: " + str(x))
    if x == m:
        print("\nThe plaintext and ciphertext are the same.")


if __name__ == "__main__":
    Encryption_Decryption()
    

个人博客:qinquanquan.com

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qinquanquan_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值