揭秘公钥加密算法 RSA

了解RSA之前,想必大家都听说过 对称加密算法 ,也就是说信息的收发方会通过实现商订好的密钥,对数据进行加密和解密

1、对称加密

然而这种加密方式有诸多缺陷,随着网络规模的不断增大,每多一个用户就需要保存许多额外的密钥,密钥的管理也将逐渐成为所有人的负担,更加致命的是,密钥必须通过见面协商,而没有办法直接通过网络进行交换,因为密钥的传输过程需要进行加密,而没有密钥则不能进行加密。

那有没有一种可能性,我们用不同的密钥对数据进行加密和解密,其中对数据加密的密钥是对所有人公开的,而对数据接秘密的密钥却仅为接收者持有呢?

在公钥加密算法中,由于公钥是对所有人公开的信息,我们需要保证数据被"公钥"加密之后,不能够被轻易地反推出来,那什么样的算法单向计算容易,而逆向反推却非常难呢?

2、模运算(Modular arithmetic)

又叫做求余运算,像计算机中的伪随机数散列算法(hash)都是他的经典应用,试想一下下面这个例子:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 3 m o d 7 3^3 mod 7 </math>33mod7

用我们小学二年级学过的知识, <math xmlns="http://www.w3.org/1998/Math/MathML"> 3 3 3^3 </math>33 得到27,并对7取余数得到 6,但已知答案是6的情况下,我们应当如何寻找 x 的值呢?
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 x m o d 7 = 6 3^x mod 7 = 6 </math>3xmod7=6

由于求余算法并不可逆,我们只能一个一个数的带进去试;
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 0 m o d 7 = 1 3^0 mod 7 = 1 </math>30mod7=1
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 1 m o d 7 = 3 3^1 mod 7 = 3 </math>31mod7=3
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 2 m o d 7 = 2 3^2 mod 7 = 2 </math>32mod7=2
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 3 m o d 7 = 6 3^3 mod 7 = 6 </math>33mod7=6
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 4 m o d 7 = 4 3^4 mod 7 = 4 </math>34mod7=4
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 5 m o d 7 = 5 3^5 mod 7 = 5 </math>35mod7=5

但如果出现下面这个很大很大的数,再去一一尝试就很不现实了。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 3 x m o d 8761287461782361827361827361278361823761827312 3^x mod 8761287461782361827361827361278361823761827312 </math>3xmod8761287461782361827361827361278361823761827312

这也就是为什么模运算被称作 单向函数,因为对于大数来说,对模运算求逆根本上不现实的,而公钥加密正是利用了模运算的这个特性。假设我们将原始数据表示成一个数 m(message),然后我们对 <math xmlns="http://www.w3.org/1998/Math/MathML"> m e m^e </math>me求e次幂 ,这里的e(encrypt)可以看作是我们加密时用的密钥,然后我们将结果除以N并取余数,最后得到密文 c(cipher)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> m e m o d N = c m^e mod N = c </math>memodN=c

并且根据我们之前讲到的,正向计算出这里的密文c 很简单,但反向推出这里的原始数据却很难;

加密 <math xmlns="http://www.w3.org/1998/Math/MathML"> m e m o d N = c m^e mod N = c </math>memodN=c


解密 <math xmlns="http://www.w3.org/1998/Math/MathML"> c d m o d N = m c^d mod N = m </math>cdmodN=m

我们需要对密文c 求 d次幂,这里的d(decrypt)代表另一个用于解密的密钥,最后得到的结果是原始数据m,为了更好的理解,讲两个公式合并为一个更为简洁的形式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( m e ) d m o d N = m (m^e)^d mod N = m </math>(me)dmodN=m

m的e*d次幂,除以N取余数,将会得到原始数据m,可以发现,如何选取这里的e和d是公钥加密的关键,欧拉定理(Euler's Theorem)公式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> m φ ( n ) ≡ 1 ( m o d n ) mφ(n)≡1(mod n) </math>mφ(n)≡1(mod n)

欧拉定理表示,对于任何一个与n互斥的正整数m,取它的 <math xmlns="http://www.w3.org/1998/Math/MathML"> φ n φ^n </math>φn,并除以n取余数,结果都永远等于1,这里的 <math xmlns="http://www.w3.org/1998/Math/MathML"> φ n φ^n </math>φn是欧拉函数,它代表在小于或等于n的正整数中,有多少个与n互斥的数,举个例子: <math xmlns="http://www.w3.org/1998/Math/MathML"> φ 6 φ^6 </math>φ6 在小于等于6的正整数中,只有1和5互为质数,也就是说,他们除了1以外,并不存在其他公约数,所以 <math xmlns="http://www.w3.org/1998/Math/MathML"> φ n φ^n </math>φn = 2。

在了解了 <math xmlns="http://www.w3.org/1998/Math/MathML"> φ n φ^n </math>φn函数之后,回到欧拉定理,又双叒叕开始变换公式了;
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( m φ ( n ) ) k ≡ 1 k ( m o d n ) (mφ(n))^k≡1^k(mod n) </math>(mφ(n))k≡1k(mod n)

在等式两端同时去k次幂,k代表任意的正整数,接着在两端同时乘以m,
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( ( m φ ( n ) ) k ) ∗ m ≡ 1 k ∗ m ( m o d n ) ((mφ(n))^k)*m≡1^k*m(mod n) </math>((mφ(n))k)∗m≡1k∗m(mod n)

并简化成这样的形式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( ( m k ) φ ) n ) + 1 m o d n = m ((m^k)^φ)^n)^+1 mod n = m </math>((mk)φ)n)+1modn=m

是不是有点眼熟?对了把它和上面的这个公式对比一下:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( m e ) d m o d N = m (m^e)^d mod N = m </math>(me)dmodN=m

你会发现,公式的指数 <math xmlns="http://www.w3.org/1998/Math/MathML"> k φ ( n ) + 1 = e d kφ(n)+1 = ed </math>kφ(n)+1=ed,变换一下得到:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d = ( k φ ( n ) + 1 ) / e d = (kφ(n)+1)/e </math>d=(kφ(n)+1)/e

也就是说,我们选取这里的 k,n,e 来计算出解密的密钥d。实际上,要计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> k φ ( n ) kφ(n) </math>kφ(n)的唯一办法就是对数n做质因数分解,比如 27 = 3 * 3 * 3、11445 = 3 * 5 * 7 * 109 这样,然而对大数的分解是很困难的事情,所以对 <math xmlns="http://www.w3.org/1998/Math/MathML"> k φ ( n ) 的 kφ(n)的 </math>kφ(n)的求解,可以看作是计算上不可行的,但是如果n本身是一个质数,情况就有所不同了,比如对于kφ(7)来说,小于等于7并与7互质的数有1-6,除了7本身,因此 <math xmlns="http://www.w3.org/1998/Math/MathML"> k φ ( 7 ) = 6 kφ(7)=6 </math>kφ(7)=6;同理对于 <math xmlns="http://www.w3.org/1998/Math/MathML"> k φ ( 13 ) kφ(13) </math>kφ(13)来说,与13互质的数,除了13本身,其他的全部都是,因此kφ(13)= 12。

其实对于任何的 <math xmlns="http://www.w3.org/1998/Math/MathML"> k φ ( p ) = p − 1 kφ(p) = p-1 </math>kφ(p)=p−1,除此之外, <math xmlns="http://www.w3.org/1998/Math/MathML"> φ φ </math>φ还有一个重要的特性,对于任意两个互质的整数 p 和 q , <math xmlns="http://www.w3.org/1998/Math/MathML"> φ ( p ) = p − 1 φ(p) = p -1 </math>φ(p)=p−1 可以拆分为 <math xmlns="http://www.w3.org/1998/Math/MathML"> φ ( p ∗ q ) = φ ( p ) ∗ φ ( q ) φ(p*q) = φ(p) * φ(q) </math>φ(p∗q)=φ(p)∗φ(q) ,例如我们可以选取两个质数17和23,由于 <math xmlns="http://www.w3.org/1998/Math/MathML"> φ ( 17 ∗ 23 ) = φ ( 17 ) ∗ φ ( 23 ) φ(17*23) = φ(17) * φ(23) </math>φ(17∗23)=φ(17)∗φ(23) = 16*32 = 352,因此可得: <math xmlns="http://www.w3.org/1998/Math/MathML"> φ ( 17 ∗ 23 ) = φ ( 391 ) = 352 φ(17*23) =φ(391) = 352 </math>φ(17∗23)=φ(391)=352,带入 <math xmlns="http://www.w3.org/1998/Math/MathML"> d = ( k φ ( n ) + 1 ) / e d = (kφ(n)+1)/e </math>d=(kφ(n)+1)/e再得:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d = ( k φ ( n ) + 1 ) / e = ( 5 ∗ 352 + 1 ) / 3 = 587 d = (kφ(n)+1)/e = (5*352+1)/3 = 587 </math>d=(kφ(n)+1)/e=(5∗352+1)/3=587

于是在k=5的情况下,求得用于解密的密钥d=587,在求出了私钥d以后,算法会将e、n公布,作为加密时的公钥,而d将保存下来作为解密时用的私钥,其他人由于不知道p和q这两个关键的质因数,没有办法计算出这里的 <math xmlns="http://www.w3.org/1998/Math/MathML"> φ n φ^n </math>φn,因而无从破解这里的私钥 d,公钥加密正是利用了这个信息的不对等,让加密者能够快速够着出一个 <math xmlns="http://www.w3.org/1998/Math/MathML"> φ n φ^n </math>φn,而其他人却无法在有限的时间内求解它。

3、举个例子

用e = 3,d = 587,n = 391 来模拟一段信息加密解密的过程,我们要加密的字符是"a",它所对应的ascii码是97,于是 <math xmlns="http://www.w3.org/1998/Math/MathML"> 9 7 3 m o d 391 = 79 97^3 mod 391 = 79 </math>973mod391=79,79是我们加密后的密文,为了解密 <math xmlns="http://www.w3.org/1998/Math/MathML"> 7 9 5 87 m o d 391 = 97 79^587 mod 391 = 97 </math>79587mod391=97,因此成功还原了字符"a"。

以上讲到的就是公钥加密算法的全部工作原理,这个算法在首次被发现之后,并被机密作为封了起来,后来又在1977年被三个麻省理工的数学家 Ron Rivest 、Adi Shamir 、 Leonard Adleman 独立发掘,成为当下众所周知的 RSA 加密算法,像数字签名,数字证书,SSH、HTTPS的加密连接,全部都是它的典型应用。

在实际使用中,由于公钥加密的计算量比较大,速度慢,通常会和对称加密算法一同使用,公钥加密算法常被用作最初连接的建立,而真正数据传输的过程,会交由对称加密算法来处理,完结!

相关推荐
高兴达40 分钟前
RPC框架--实现一个非常简单的RPC调用
网络协议·rpc·firefox
凌肖战1 小时前
力扣网C语言编程题:在数组中查找目标值位置之二分查找法
c语言·算法·leetcode
weixin_478689761 小时前
十大排序算法汇总
java·算法·排序算法
深圳安锐科技有限公司2 小时前
深圳安锐科技发布国内首款4G 索力仪!让斜拉桥索力自动化监测更精准高效
运维·安全·自动化·自动化监测·人工监测·桥梁监测·索力监测
潘锦2 小时前
海量「免费」的 OPENAI KEY,你敢用吗?
安全·openai
luofeiju2 小时前
使用LU分解求解线性方程组
线性代数·算法
冰橙子id2 小时前
linux系统安全
linux·安全·系统安全
SKYDROID云卓小助手2 小时前
无人设备遥控器之自动调整编码技术篇
人工智能·嵌入式硬件·算法·自动化·信号处理
游戏开发爱好者83 小时前
iOS App首次启动请求异常调试:一次冷启动链路抓包与初始化流程修复
websocket·网络协议·tcp/ip·http·网络安全·https·udp
2501_915106323 小时前
频繁迭代下完成iOS App应用上架App Store:一次快速交付项目的完整回顾
websocket·网络协议·tcp/ip·http·网络安全·https·udp