🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解 AES加密算法 请看 : AES加密:保护隐私,从我做起!
其他优质专栏: 【🎇SpringBoot】【🎉多线程】【🎨Redis】【✨设计模式专栏(已完结)】…等
如果喜欢作者的讲解方式,可以点赞收藏加关注,你的支持就是我的动力
✨更多文章请看个人主页: 码熔burning
一、 什么是RSA?
想象一下,你想给你的朋友小明寄一个秘密包裹 📦,但你担心邮递员或者其他人偷看。于是你俩想了个办法:
- 小明准备了一把锁 🔒(公钥)和一个只有他自己有的钥匙 🔑(私钥)。
- 小明把这把打开的锁 🔒(公钥)复制了很多份,给了所有想给他寄东西的人,包括你。这个锁谁都可以拿到,没关系。
- 你想给小明寄包裹时,就用小明给你的那把打开的锁 🔒(公钥)把包裹锁上。注意:一旦锁上,用这把锁(公钥)是打不开的! 只有小明手里的那把独一无二的钥匙 🔑 才能打开。
- 你把锁好的包裹寄给小明 ✉️。
- 小明收到包裹后,用他自己私藏的钥匙 🔑 轻松打开了包裹,看到了里面的秘密。
在这个过程中:
- 公开的锁 就是 公钥 (Public Key)。谁都能用它来“锁上”(加密)信息。
- 小明私藏的钥匙 就是 私钥 (Private Key)。只有持有者才能用它来“打开”(解密)信息。
- 用公钥锁上,用私钥打开 这个过程,就是 RSA加密和解密 的核心思想 🤔。
所以,RSA是一种“非对称加密算法”。 “非对称”的意思就是,加密用的“锁”(公钥)和解密用的“钥匙”(私钥)是不同的、成对出现的。公钥可以公开,私钥必须保密。
二、 RSA的基本概念
- 非对称加密 (Asymmetric Cryptography): 与对称加密(比如AES,加密和解密用同一把钥匙)不同,它使用一对密钥:公钥和私钥 💡。
- 公钥 (Public Key): 可以公开分发,用于加密数据或验证签名。
- 私钥 (Private Key): 必须由所有者严格保密 🤫,用于解密由对应公钥加密的数据,或用于生成数字签名。
- 密钥对 (Key Pair): 公钥和私钥是数学上相关联的一对 🤝。知道公钥很难(在现有计算能力下几乎不可能)推导出私钥。
- 数学基础: RSA的安全性基于一个数学难题:大整数分解 🤯。要把一个很大的合数(两个大素数的乘积)分解成它的素数因子,在计算上是非常困难的。你的公钥和私钥的生成就依赖于这个原理。
三、 RSA的加密/解密流程
我们用稍微专业一点的说法描述一下(但还是尽量简单):
-
密钥生成:
① 随机选择两个非常大的素数,叫它们 p 和 q。(保密)
② 计算它们的乘积 n = p * q。这个 n 是密钥对的一部分,会包含在公钥和私钥里。(公开)
③ 计算另一个数 φ(n) = (p-1) * (q-1)。这个叫做欧拉函数值。(保密)
④ 选择一个整数 e,要求 e 和 φ(n) 互质(最大公约数为1),并且 1 < e < φ(n)。这个 e 就是公钥指数。(公开)
⑤ 计算一个整数 d,使得 (d * e) % φ(n) = 1。这个 d 就是私钥指数。(保密)- 公钥:(n, e)
- 私钥:(n, d) (有时候也包含p, q等,但核心是n和d)
-
加密过程 (用对方的公钥加密):
① 发送方(比如你)获取接收方(比如小明)的公钥 (n, e)。
② 将要发送的明文消息 M 转换成一个小于 n 的整数 m 🔢。(如果消息太长,会分块处理)
③ 计算密文 c: c = m^e mod n (意思是 m 的 e 次方,然后除以 n 取余数) 🔒
④ 将密文 c 发送给接收方 ➡️。 -
解密过程 (用自己的私钥解密):
① 接收方(小明)使用自己的私钥 (n, d)。
② 收到密文 c。
③ 计算明文 m: m = c^d mod n (意思是 c 的 d 次方,然后除以 n 取余数) 🔑
④ 将得到的整数 m 转换回原始的消息 M。 -
数字签名 (用自己的私钥签名,对方用你的公钥验证):
① 发送方(你)想证明消息是你发的,没被篡改。
② 先计算消息的哈希值 H(M)。
③ 用自己的私钥 (n, d) 对哈希值进行“加密”(实际是签名操作):Signature = H(M)^d mod n ✍️
④ 将原始消息 M 和 签名 Signature 一起发送给接收方。
⑤ 接收方(小明)收到 M 和 Signature。
⑥ 用发送方(你)的公钥 (n, e) 对签名进行“解密”(实际是验证操作):H_verified = Signature^e mod n
⑦ 接收方自己也计算收到消息 M 的哈希值 H(M)。
⑧ 比较 H_verified 和 H(M)。如果两者相等 ✅,说明消息确实是拥有对应私钥的人(你)发的,并且内容没有被篡改。
四、 RSA如何使用Java实现 💻
Java 的 java.security
和 javax.crypto
包提供了实现RSA加密/解密和签名的标准API。
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
public class RsaExample {
public static void main(String[] args) throws Exception {
// 1. 生成RSA密钥对 (实际应用中,密钥通常是预先生成好并存储的) ⚙️
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048); // 密钥长度,常用1024, 2048, 4096
KeyPair keyPair = keyGen.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 要加密的原始数据
String originalMessage = "这是一条需要加密的秘密消息!";
System.out.println("原始消息: " + originalMessage);
// 2. 使用公钥加密 🔒
Cipher encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // 注意指定填充方式
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = encryptCipher.doFinal(originalMessage.getBytes(StandardCharsets.UTF_8));
// 通常将加密后的字节数组用Base64编码,方便传输
String encryptedBase64 = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("加密后 (Base64): " + encryptedBase64);
// 3. 使用私钥解密 🔑
Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
// 先将Base64解码回字节数组
byte[] encryptedBytesFromBase64 = Base64.getDecoder().decode(encryptedBase64);
byte[] decryptedBytes = decryptCipher.doFinal(encryptedBytesFromBase64);
String decryptedMessage = new String(decryptedBytes, StandardCharsets.UTF_8);
System.out.println("解密后消息: " + decryptedMessage);
// --- 数字签名演示 ---
String messageToSign = "这是需要签名的内容";
System.out.println("\n要签名的消息: " + messageToSign);
// 4. 使用私钥签名 ✍️
Signature signature = Signature.getInstance("SHA256withRSA"); // 使用SHA256哈希算法配合RSA
signature.initSign(privateKey);
signature.update(messageToSign.getBytes(StandardCharsets.UTF_8));
byte[] signatureBytes = signature.sign();
String signatureBase64 = Base64.getEncoder().encodeToString(signatureBytes);
System.out.println("生成的签名 (Base64): " + signatureBase64);
// 5. 使用公钥验证签名 ✅
Signature verification = Signature.getInstance("SHA256withRSA");
verification.initVerify(publicKey);
verification.update(messageToSign.getBytes(StandardCharsets.UTF_8));
// 先将Base64解码回字节数组
byte[] signatureBytesFromBase64 = Base64.getDecoder().decode(signatureBase64);
boolean isVerified = verification.verify(signatureBytesFromBase64);
System.out.println("签名验证结果: " + (isVerified ? "成功 🎉" : "失败 ❌"));
// 模拟篡改消息后验证失败
String tamperedMessage = messageToSign + " (已被篡改)";
verification.initVerify(publicKey); // 需要重新初始化
verification.update(tamperedMessage.getBytes(StandardCharsets.UTF_8));
isVerified = verification.verify(signatureBytesFromBase64);
System.out.println("篡改后消息的签名验证结果: " + (isVerified ? "成功 🎉" : "失败 ❌"));
}
}
关键点:
KeyPairGenerator
: 用于生成密钥对。KeyPair
: 包含公钥和私钥的对象。PublicKey
,PrivateKey
: 分别代表公钥和私钥。Cipher
: 用于执行加密和解密操作。需要指定算法 ("RSA"
), 模式 ("ECB"
), 和填充方式 ("PKCS1Padding"
).Signature
: 用于生成和验证数字签名。需要指定哈希算法和签名算法 ("SHA256withRSA"
).Base64
: 由于加密/签名结果是二进制字节数组,不方便直接传输或显示,通常会用Base64编码成字符串。
五、 RSA的应用场景?
RSA 作为非对称加密的基石,被广泛应用在各种需要安全通信和身份验证的场景:
- SSL/TLS (HTTPS) 🌐: 访问
https://
网站时,浏览器和服务器之间建立安全连接,验证服务器身份和安全协商对称密钥。 - SSH (Secure Shell) 💻➡️💻: 安全登录远程服务器,用密钥对进行身份验证。
- VPN (Virtual Private Network) 🛡️: 建立VPN连接时的身份验证和密钥交换。
- 数字证书 (X.509) 📜: 验证网站、软件开发者、个人身份。
- 代码签名 ✍️: 验证软件来源和完整性。
- 安全电子邮件 (PGP/GPG, S/MIME) 📧: 加密邮件内容,签名邮件。
- JSON Web Tokens (JWT) 🔑: 使用 RSA 进行签名,确保内容未被篡改并验证签发者。
- API认证/授权: 客户端使用私钥对请求签名,服务器用公钥验证来源。
- 加密文件系统/磁盘加密: 密钥管理部分可能用到RSA。
基本上,只要涉及到身份验证、确保数据来源可靠性、防止抵赖、以及安全地交换对称密钥这些场景,都可能看到RSA的身影。
六、 RSA的优缺点
-
优点:
- 解决了密钥分发问题 👍: 公钥可以公开,不用担心像对称加密那样传递密钥时的安全问题。
- 安全性高 ✅: 基于成熟的数学难题,密钥足够长时非常安全。
- 可用于数字签名 👍: 能提供身份认证、数据完整性保护和不可否认性。
-
缺点:
- 速度慢 🐢: 加解密运算比对称加密慢很多,不适合直接加密大量数据。
- 计算资源消耗大 😟: 对CPU要求较高。
- 加密数据长度有限制 📏: 单次加密的数据量有限,通常需要结合对称加密使用。
- 密钥管理复杂性 🤔: 私钥必须绝对安全,公钥的真实性也需保证(通常靠证书)。
- 对量子计算的潜在威胁 ⚛️: 未来强大的量子计算机理论上可能破解RSA。
七、 总结
RSA就像那个公开的邮箱锁 🔒 和私密的邮箱钥匙 🔑。
- 好处: 送锁(公钥)很方便 😊,不用担心锁被别人拿到;只有拿钥匙(私钥)的人才能开箱(解密),很安全 💪;还能用钥匙在信 ✉️ 上盖个特殊印章(签名),证明信确实是他写的。
- 坏处: 开锁和锁箱子 📦(加解密)比较费劲(慢 🐢);箱子本身不能太大(加密数据量有限);要是把钥匙弄丢了(私钥泄露)就全完了 😱;未来可能有超级开锁匠(量子计算)能破解这种锁 🤔。
因此,在实际应用中,人们通常把RSA和对称加密结合起来用:用RSA来安全地“递送”对称加密用的那个更快的“钥匙”,然后用对称加密来快速处理大量的“包裹内容”。这就是所谓的混合加密方案,兼顾了安全性和效率!✨