低配版的 RSA 当然不能在生产环境使用,但当做一个小玩具把玩一下还是非常适合的,因为它非常优美漂亮!

<font style=color:rgb(18, 18, 18);>可能对数学好的人来说是常识,但我在学习RSA 算法时惊呆了:加密和解密的公式居然一模一样!

<font style=color:rgb(18, 18, 18);>两个看起来完全相反的事情,做的事情居然相同!

<font style=color:rgb(18, 18, 18);>这让我为它的简洁,和对称性着迷!

<font style=color:rgb(18, 18, 18);>对了,RSA 是非对称加密算法,但是加解密的过程却对称,很有趣。

<font style=color:rgb(18, 18, 18);>当然,它是非对称加密算法<font style=color:rgb(18, 18, 18);>,原因是它的加密密钥和解密密钥并不相同。而加密和解密用相同密钥的算法,才是真正的对称加密算法。

<font style=color:rgb(18, 18, 18);>但正是这种非对称中的对称,才让人觉得优雅。

<font style=color:rgb(18, 18, 18);>RSA

<font style=color:rgb(18, 18, 18);>RSA 是一种非对称加密算法,它需要一对密钥,分别是公钥和私钥。公钥用于加密,私钥用于解密。RSA 算法的原理是,将明文进行加密,得到密文,然后再使用私钥对密文进行解密,得到明文。RSA 算法的安全性基于大数分解的难度,即使在今天,也没有任何一种算法可以在合理的时间内对大数进行分解。所以,只要密钥的长度足够长,就可以保证 RSA 算法的安全性。

<font style=color:rgb(18, 18, 18);>它的名字源于它的发明者 Ron Rivest、Adi Shamir 和 Leonard Adleman 的姓氏首字母。该算法曾在美国取得专利,不过现在已经过期。我们来看一看它的加密过程。

<font style=color:rgb(18, 18, 18);>RSA 加密过程

<font style=color:rgb(18, 18, 18);>假设 Alice 想要向 Bob 发送一条消息,那么 Alice 就需要使用 Bob 的公钥对消息进行加密,然后再将加密后的消息发送给 Bob。Bob 收到消息后,就可以使用自己的私钥对消息进行解密,从而得到 Alice 发送的明文消息。

<font style=color:rgb(18, 18, 18);>RSA 算法的加密过程如下:

  1. <font style=color:rgb(18, 18, 18);>首先,Bob 生成一对密钥,分别是公钥和私钥。公钥是公开的,任何人都可以获得,而私钥则是保密的,只有 Bob 自己知道。
  2. <font style=color:rgb(18, 18, 18);>Bob 将公钥发送给 Alice。
  3. <font style=color:rgb(18, 18, 18);>Alice 使用 Bob 的公钥对消息进行加密,得到密文。
  4. <font style=color:rgb(18, 18, 18);>Alice 将密文发送给 Bob。
  5. <font style=color:rgb(18, 18, 18);>Bob 使用自己的私钥对密文进行解密,得到明文。
  6. <font style=color:rgb(18, 18, 18);>Bob 得到明文后,就可以对消息进行处理了。

<font style=color:rgb(18, 18, 18);>那么,这个公钥和密钥究竟是什么呢?RSA 算法的公钥和私钥都是一对大素数,在实际应用中,这两个大素数的长度一般都是 1024 位或者 2048 位,这样就可以保证 RSA 算法的安全性。

<font style=color:rgb(18, 18, 18);>其加密过程可以表示为如下公式:

<font style=color:rgb(18, 18, 18);>密文 = 明文E<font style=color:rgb(18, 18, 18);> mod N

<font style=color:rgb(18, 18, 18);>即,RSA 的密文是对代表明文的数字的 E 次方取模,其中 N 是两个大素数的乘积。也就是说,将明文和自己做 E 次乘法,然后将其结果除以 N 取余数,得到的余数就是密文。

<font style=color:rgb(18, 18, 18);>RSA 和对称密码不一样,不用做复杂的函数和操作,没有将比特序列挪来挪去的烦琐过程,也不用做 XOR 等运算,相比之下,显得非常简洁。

<font style=color:rgb(18, 18, 18);>上述加密公式中出现了两个数,E 和 N。任何人只要知道了这两个数,都能完成加密运算。所以 E 和 N 是 RSA 加密的密钥,也就是公钥。

<font style=color:rgb(18, 18, 18);>注意,E 和 N 本身不是密钥对,它们两个数共同组成了一个公钥。总之,RSA 加密就是“求E次方的 mod N”。

<font style=color:rgb(18, 18, 18);>下面我们来看一看 RSA 的解密过程。

<font style=color:rgb(18, 18, 18);>RSA 解密过程

<font style=color:rgb(18, 18, 18);>RSA 的解密和加密一样简洁,公式如下:

<font style=color:rgb(18, 18, 18);>明文 = 密文D<font style=color:rgb(18, 18, 18);> mod N

<font style=color:rgb(18, 18, 18);>即,RSA 的明文是对代表密文的数字的 D 次方取模,其中 N 是两个大素数的乘积。也就是说,将密文和自己做 D 次乘法,然后将其结果除以 N 取余数,得到的余数就是明文。

<font style=color:rgb(18, 18, 18);>和加密过程一样,解密过程中也出现了两个数,D 和 N。任何人只要知道了这两个数,都能完成解密运算。所以 D 和 N 是 RSA 解密的密钥,也就是私钥(由于 N 是公钥的一部分,是公开的,所以单独将 D 称为私钥也是可以的)。在本小节最开头的例子中,只有 Bob 自己知道 D 和 N,所以只有 Bob 才能完成解密运算。

<font style=color:rgb(18, 18, 18);>这样来看,RSA 不仅简洁,而且其加密和解密的形式是一样的。加密是求“E次方的 mod N”,而解密是求“D次方的 mod N”。

<font style=color:rgb(18, 18, 18);>如果美妙的算法,当然不是随便一个数都可以作为 E 和 D 的。E 和 D 必须满足一定的条件,才能保证 RSA 算法的正确性。前面提到,E 和 D 是一对大素数,长度要达到1024位或者2048位,否则不能保证安全性。

<font style=color:rgb(18, 18, 18);>但是为了理解,不妨拿小素数来举例,比如 17 和 23。这两个数的乘积是 391,这个数就是 N。但是注意,这时的 17 和 23 只是为了生成 N,并不是 E 和 D 本身。

<font style=color:rgb(18, 18, 18);>为了求 E 和 D,还需要求出 16 和 22 的最小公倍数。这个最小公倍数是 176,通过它,可以得到 E 和 D。首先,E 和 176 必须互质,这样的数有 1、3、5、7、11、13、17、19、23、25<font style=color:rgb(18, 18, 18);>注意,25并不是质数,即公钥不必是质数,只要和176互质就可以了。<font style=color:rgb(18, 18, 18);>…… 等等,我们这里选择 7 来作为 E。即公钥已经产生了,那就是(7,391)。

<font style=color:rgb(18, 18, 18);>接下来,求 D。D 需要满足如下条件:

<font style=color:rgb(18, 18, 18);>E x D mod 176 = 1

<font style=color:rgb(18, 18, 18);>其中 E = 7,那么可以找到一个质数 D = 201,使得上面的等式成立。这样,私钥就产生了,那就是(201,391)。

<font style=color:rgb(18, 18, 18);>如果明文是 123,那么加密过程如下:

<font style=color:rgb(18, 18, 18);>密文 = 1237<font style=color:rgb(18, 18, 18);> mod 391 = 246。

<font style=color:rgb(18, 18, 18);>解密过程如下:

<font style=color:rgb(18, 18, 18);>明文 = 246201<font style=color:rgb(18, 18, 18);> mod 391 = 123。

<font style=color:rgb(18, 18, 18);>这样,就完成了加密和解密的过程。

:::warning <font style=color:rgb(18, 18, 18);>明文必须小于N,这是由于解密运算也需要 mod N,而 mod N 的结果必然小于 N。如果明文大于 N,那么解密后的结果就不是明文本身了。

<font style=color:rgb(18, 18, 18);>以上示例使用了123作为明文,如果再选择更大的数比如 392,就会出现问题。因为 392 > 391。记住,明文必须小于 N。

<font style=color:rgb(18, 18, 18);>另外,我们在求出 E = 7 和 D = 201 时,使用了另外两个质数,即 17 和 23。这两个质数虽然不是密钥 D,但是也不能被泄露,否则就可以通过它们来计算出 D。泄露这两个质数对和泄露私钥是等价的。

:::

<font style=color:rgb(18, 18, 18);>RSA 签名

RSA 算法还可以用于签名,后面要介绍的 RS256 就是它在 JWT 中的应用实例。<font style=color:rgb(18, 18, 18);>�

<font style=color:rgb(18, 18, 18);>常用的签名算法

<font style=color:rgb(18, 18, 18);>HS256 和 RS256 是 JWT 最常用的签名算法,比如在下图中所展示的 authing 的控制面板中就对身份令牌 JWT 提供了两种签名算法的选择界面。

<font style=color:rgb(18, 18, 18);>

1701174098148 632ef5dc 9ae1 4f12 bf2b ce953cce6732

<font style=color:rgb(18, 18, 18);>SHA 和 RSA 是两类不同的算法,而 HS256 和 RS256 则分别是这两类不同的算法在 JWT 中的具体应用实例,下面分别介绍一下它们。

<font style=color:rgb(18, 18, 18);>HS256

<font style=color:rgb(18, 18, 18);>HS256(HMAC SHA-256)是一种对称加密算法,它需要一个密钥,这个密钥既用于加密,也用于解密。HS256 算法的原理是,将 Header 和 Payload 两部分的 Base64 字符串用“.”连接起来,然后使用密钥对其进行 HMAC SHA-256 算法加密,得到一个签名字符串。这个签名字符串就是 JWT 的第三部分,也就是 Signature。当 JWT 接收方收到 JWT 时,会对其进行解密,然后再使用同样的密钥对 Header 和 Payload 两部分的 Base64 字符串进行 HMAC SHA-256 算法加密,得到一个签名字符串,然后将这个签名字符串和接收到的 JWT 的第三部分进行比较,如果两者相同,就说明 JWT 没有被篡改过。

<font style=color:rgb(18, 18, 18);>HS256使用同一个密钥进行签名和验证,因此必须确保密钥的安全性。在开发应用时,启用JWT,使用HS256更加安全,但你必须确保密钥不被泄露。

<font style=color:rgb(18, 18, 18);>RS256

<font style=color:rgb(18, 18, 18);>RS256(RSA SHA-256)是一种非对称密钥算法,它使用公共/私钥对进行签名和验证。公钥用于验证签名,因此不需要保护(大多数标识提供方或者说身份提供商使其易于获取和使用),私钥用于生成签名,因此必须保密。如果你无法控制客户端,无法做到密钥的完全保密,RS256会是更好的选择,因为JWT的使用方只需要知道公钥。

<font style=color:rgb(18, 18, 18);>HS256 和 RS256 的区别

<font style=color:rgb(18, 18, 18);>HS256和RS256都是JWT(Json Web Token)常用的签名算法,它们的主要区别在于使用的密钥类型和安全性。

<font style=color:rgb(18, 18, 18);>总结来说,选择HS256还是RS256取决于你的具体需求。如果你需要更高的安全性,且能确保密钥的安全性,可以选择HS256。如果你无法确保密钥的安全性,或者需要在不安全的网络环境中通信,可以选择RS256。

<font style=color:rgb(18, 18, 18);>

<font style=color:rgb(18, 18, 18);>总结

<font style=color:rgb(209, 213, 219);background-color:rgb(52, 53, 65);>这篇文章总结了 RSA 加密算法的基本概念和工作原理。RSA 算法是一种非对称加密算法,使用一对密钥(公钥和私钥)进行加密和解密。公钥用于加密,私钥用于解密。文章强调了 RSA 算法的安全性依赖于大数分解的难度,并说明了加密和解密过程中使用的公式。此外,文章还解释了 RSA 的签名过程和常用的签名算法(HS256 和 RS256)之间的区别。最后,文章提醒读者选择加密算法时应考虑安全需求和密钥保密性。