RSA 加密、解密算法实现

590 阅读5分钟

一、 算法介绍

RSA加密算法

  • 一种非对称加密算法,在公开密钥加密和电子商业中被广泛使用。RSA是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的。当时他们三人都在麻省理工学院工作。RSA 就是他们三人姓氏开头字母拼在一起组成的。

OAEP 算法

  • 费斯妥密码的一种形式,它使用一对随机预言 G 和 H 在进行非对称加密之前处理明文。OAEP 与任何安全的陷门单向置换f 结合使用在随机预言模型中被证明是一种在选择明文攻击(IND-CPA)下语义安全的组合方案。当使用某些陷门置换(如 RSA)实现时,OAEP 也被证明可以抵抗选择密文攻击。OAEP 可用于构建全有或全无转换(all-or-nothing transform)。OAEP 满足以下两个目标:1、添加随机性元素,这可用于将确定性加密方案(如传统 RSA)转变为概率加密方案。2、通过确保无法反转陷门单向置换 f,从而无法恢复明文的任何部分,来防止密文的部分解密(或造成其他信息泄漏)。当 OAEP 与任何陷门置换一起使用时,OAEP 的原始版本(Bellare/Rogaway, 1994)在随机预言机模型中显示了一种“明文知晓性”的形式(他们声称这意味着对选择密文攻击是安全的)。然而随后的结果与这一点相抵触,表明 OAEP 仅是 IND-CCA1 安全的。但是与 RSA-OAEP 的情况一样,当将OAEP与使用标准加密指数的 RSA 置换一起使用时,在随机预言模型中证明了原始方案是 IND-CCA2 安全的。[2]Victor Shoup 提供了一种改进的方案(称为 OAEP+),该方案可与任何陷门单向置换配合使用,以解决此问题。[3]近期的研究表明,在标准模型中(即当哈希函数未建模为随机预言时),无法在假定 RSA 问题的难度下证明 RSA-OAEP 具有 IND-CCA2 安全性。

ElGamal加密算法

  • 一个基于迪菲-赫尔曼密钥交换的非对称加密算法。它在1985年由塔希尔·盖莫尔提出。GnuPG和PGP等很多密码学系统中都应用到了ElGamal算法。ElGamal加密算法可以定义在任何循环群G上。它的安全性取决于G上的离散对数难题。而在实际使用中,ElGamal加密系统通常应用在混合加密系统中。例如:用对称加密体制来加密消息,然后利用ElGamal加密算法传递密钥。这是因为在同等安全等级下,ElGamal加密算法作为一种非对称密码学系统,通常比对称加密体制要慢。对称加密算法的密钥和要传递的消息相比通常要短得多,所以相比之下使用ElGamal加密密钥然后用对称加密来加密任意长度的消息,这样要更快一些。

二、术语解释(RSA)

  • 明文:真实的数据信息,包括但不限于文本、图片等数据类型。
  • 密文:数据经过加密算法运算之后所生成的一组数据信息。
  • 密钥:在加密的过程中自动生成的一个唯一的参数,也是解密的必须元素。

三、一些定理、性质以及函数库(RSA)

  • 欧拉函数φ(n)指不超过n且与n互质的正整数的个数,其中n是一个正整数。性质:它在整数n上的值等于对n进行素因子分解后,所有的素数上的欧拉函数之积。
  • 欧拉定理 若 n, a 为正整数,且 n, a 互素,则等式 a ^ φ(n) = 1 (mod n) 成立。
  • 扩展欧几里得算法是对欧几里得算法(又叫辗转相除法)的扩展。已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式 ax + by = gcd(a, b)。
  • GMP(全称是GNU Multiple Precision Arithmetic Library,即GNU高精度算术运算库),它是一个开源的高精度运算库,其中不但有普通的整数、实数、浮点数的高精度运算,还有随机数生成,尤其是提供了非常完备的数论中的运算接口,比如Miller-Rabin素数测试算法、大素数生成、欧几里德算法、求域中元素的逆、Jacobi符号、legendre符号等。下文代码中使用的 gmpy2 正是python对 GMP 的封装版。

四、算法实现步骤(RSA)

  1. 随机选择两个 1024比特的不同秘密大素数p与q;
  2. 分别计算N = p * q和φ( N) = (p-1) * (q-1) 的值;
  3. 选择一个小于φ( N) 且与φ( N) 互素的正整数e;
  4. 计算e的乘法逆元d = e - 1(mod φ( N));
  5. 利用数制转换将明文分组,使每组中明文m的取值范围在1至N-1之间;
  6. 执行加密运算c = m ^ e(mod N),将明文m加密成密文c;
  7. 执行解密运算m = c ^ d(mod N),将密文c恢复成明文m。

代码实现(RSA)

  • 注:为了提高算法的执行效率,我们借助了 gmpy2 函数库。它提供的每个基础 API 都是经过精心优化的。相对于自己实现的 API 的速度要快很多。
import time
from time import sleep
from gmpy2 import gmpy2

def encrypt(p,q,e,m):
   
    start = time.time()
    sleep(1)

    N = p * q
    d = gmpy2.invert(e, (p - 1) * (q - 1))
    c = gmpy2.powmod(m, e, N)
    print('密文:', c)
    print('明文:', gmpy2.powmod(c, d, N))
    end = time.time()
    print('耗时:',(end - start) * 1000 - 1000,'ms')

def decipher(p,q,e,m):
   
    start = time.time()
    sleep(1)

    N = p * q
    dp = gmpy2.invert(e,p - 1)
    dq = gmpy2.invert(e,q - 1)
    pq = gmpy2.invert(q,p)
    c = gmpy2.powmod(m,e,N)
    print('密文:',c)

    m1 = gmpy2.powmod(c,dp,p)
    m2 = gmpy2.powmod(c,dq,q)
    h = gmpy2.f_mod(pq * gmpy2.f_mod((m1 - m2),p),p)
    print('明文:',m2 + h * q)

    end = time.time()\
    print('耗时:',(end - start) * 1000 - 1000,'ms')\

p = gmpy2.getPrime(1024,randfunc=None)

q = gmpy2.getPrime(1024,randfunc=None)
e = 65537
m = input('输入明文信息m: ')
encrypt(p,q,e,m)
decipher(p,q,e,m)