低配版的 RSA 当然不能在生产环境使用,但当做一个小玩具把玩一下还是非常适合的,因为它非常优美漂亮!
可能对数学好的人来说是常识,但我在学习RSA 算法时惊呆了:加密和解密的公式居然一模一样!
两个看起来完全相反的事情,做的事情居然相同!
这让我为它的简洁,和对称性着迷!
对了,RSA 是非对称加密算法,但是加解密的过程却对称,很有趣。
当然,它是非对称加密算法,原因是它的加密密钥和解密密钥并不相同。而加密和解密用相同密钥的算法,才是真正的对称加密算法。
但正是这种非对称中的对称,才让人觉得优雅。

RSA

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

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

RSA 加密过程

假设 Alice 想要向 Bob 发送一条消息,那么 Alice 就需要使用 Bob 的公钥对消息进行加密,然后再将加密后的消息发送给 Bob。Bob 收到消息后,就可以使用自己的私钥对消息进行解密,从而得到 Alice 发送的明文消息。

RSA 算法的加密过程如下:

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

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

其加密过程可以表示为如下公式:

密文 = 明文E mod N

即,RSA 的密文是对代表明文的数字的 E 次方取模,其中 N 是两个大素数的乘积。也就是说,将明文和自己做 E 次乘法,然后将其结果除以 N 取余数,得到的余数就是密文。

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

上述加密公式中出现了两个数,E 和 N。任何人只要知道了这两个数,都能完成加密运算。所以 E 和 N 是 RSA 加密的密钥,也就是公钥。

注意,E 和 N 本身不是密钥对,它们两个数共同组成了一个公钥。总之,RSA 加密就是“求E次方的 mod N”。

下面我们来看一看 RSA 的解密过程。

RSA 解密过程

RSA 的解密和加密一样简洁,公式如下:

明文 = 密文D mod N

即,RSA 的明文是对代表密文的数字的 D 次方取模,其中 N 是两个大素数的乘积。也就是说,将密文和自己做 D 次乘法,然后将其结果除以 N 取余数,得到的余数就是明文。

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

这样来看,RSA 不仅简洁,而且其加密和解密的形式是一样的。加密是求“E次方的 mod N”,而解密是求“D次方的 mod N”。

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

但是为了理解,不妨拿小素数来举例,比如 17 和 23。这两个数的乘积是 391,这个数就是 N。但是注意,这时的 17 和 23 只是为了生成 N,并不是 E 和 D 本身。

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

接下来,求 D。D 需要满足如下条件:

E x D mod 176 = 1

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

如果明文是 123,那么加密过程如下:

密文 = 1237 mod 391 = 246。

解密过程如下:

明文 = 246201 mod 391 = 123。

这样,就完成了加密和解密的过程。

:::warning 明文必须小于N,这是由于解密运算也需要 mod N,而 mod N 的结果必然小于 N。如果明文大于 N,那么解密后的结果就不是明文本身了。
以上示例使用了123作为明文,如果再选择更大的数比如 392,就会出现问题。因为 392 > 391。记住,明文必须小于 N。
另外,我们在求出 E = 7 和 D = 201 时,使用了另外两个质数,即 17 和 23。这两个质数虽然不是密钥 D,但是也不能被泄露,否则就可以通过它们来计算出 D。泄露这两个质数对和泄露私钥是等价的。 :::

RSA 签名

RSA 算法还可以用于签名,后面要介绍的 RS256 就是它在 JWT 中的应用实例。�

常用的签名算法

HS256 和 RS256 是 JWT 最常用的签名算法,比如在下图中所展示的 authing 的控制面板中就对身份令牌 JWT 提供了两种签名算法的选择界面。

image.png

SHA 和 RSA 是两类不同的算法,而 HS256 和 RS256 则分别是这两类不同的算法在 JWT 中的具体应用实例,下面分别介绍一下它们。

HS256

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

HS256使用同一个密钥进行签名和验证,因此必须确保密钥的安全性。在开发应用时,启用JWT,使用HS256更加安全,但你必须确保密钥不被泄露。

RS256

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

HS256 和 RS256 的区别

HS256和RS256都是JWT(Json Web Token)常用的签名算法,它们的主要区别在于使用的密钥类型和安全性。

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

总结

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