4. 常见非对称加密算法:RSA、ECC原理及SDK实现
聊完对称加密,咱们来看看非对称加密。它解决了一个核心问题——密钥分发。对称加密里,通信双方得事先约定同一个密钥,这在实际场景中非常麻烦。非对称加密则用一对密钥:公钥公开,私钥保密。公钥加密的数据只能用私钥解密,反过来私钥签名可以用公钥验签。这套机制撑起了现代互联网的安全基石。
非对称加密速度慢,通常只用来加密少量数据(比如对称密钥)或做数字签名。在数据防泄漏场景中,我们用非对称加密来保护密钥交换环节,避免密钥在传输中被窃取。另外,先哈希再签名也能确保数据的完整性和来源可信。
下面针对两种主流算法——RSA 和 ECC,我结合项目经验讲讲它们的原理和 SDK 实现要点。
4.1 RSA 算法:大数分解难题
RSA 是应用最广泛的非对称加密算法,依赖大整数分解的数学难题。简单说,两个大质数相乘很容易,但从乘积反推出这两个质数却极其困难。RSA 的安全性就建立在这个不对称性上。
密钥生成过程:选两个大质数 p 和 q,计算 n = p * q,再找 e 和 d 使得 e*d ≡ 1 (mod φ(n)),其中 φ(n) = (p-1)*(q-1)。公钥是 (n, e),私钥是 (n, d)。加密时计算 c = m^e mod n,解密时 m = c^d mod n。签名过程类似,只是用私钥加密,公钥验证。
RSA 的密钥长度通常为 2048 位或 4096 位。位数越长越安全,但加解密速度也越慢。2048 位是目前推荐的最低安全标准,4096 位用于高安全场景。
| 密钥长度 | 安全级别 | 性能表现 | 推荐场景 |
|---|---|---|---|
| 1024 位 | 已不安全 | 较快 | 不再使用 |
| 2048 位 | 中等(~112 位对称安全) | 可接受 | 常规业务 |
| 4096 位 | 高(~128 位对称安全) | 较慢 | 金融、政务 |
SDK 实现示例(Java):
// 初始化密钥对生成器
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048); // 我习惯用2048位
KeyPair keyPair = keyGen.generateKeyPair();
PublicKey pubKey = keyPair.getPublic();
PrivateKey privKey = keyPair.getPrivate();
// 加密数据(RSA加密原数据有长度限制,2048位最多加密245字节)
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] encrypted = cipher.doFinal(data);
// 解密数据
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decrypted = cipher.doFinal(encrypted);
// 签名
Signature signer = Signature.getInstance("SHA256WithRSA");
signer.initSign(privKey);
signer.update(data);
byte[] signature = signer.sign();
// 验签
signer.initVerify(pubKey);
signer.update(data);
boolean verified = signer.verify(signature);
4.2 ECC 算法:椭圆曲线离散对数难题
ECC 是新一代非对称加密算法,基于椭圆曲线离散对数难题。它的核心优势是短密钥、高强度。256 位的 ECC 密钥就能提供和 3072 位 RSA 相当的安全性,而且计算效率更高。
ECC 的数学原理相对复杂:椭圆曲线上的点构成一个阿贝尔群,定义点加法和标量乘法。私钥是一个随机整数,公钥是私钥乘以生成元 G 得到的点。已知公钥求私钥,就是离散对数问题,目前没有多项式时间解法。
ECC vs RSA 对比:
| 对比维度 | RSA | ECC |
|---|---|---|
| 安全性基础 | 大整数分解 | 椭圆曲线离散对数 |
| 密钥长度(同安全性) | 3072 位 | 256 位 |
| 加解密速度 | 慢(尤其是私钥操作) | 快(私钥操作优势明显) |
| 签名速度 | 签名慢、验签快 | 签名快、验签较快 |
| 密钥生成速度 | 慢(找大质数) | 快 |
| 带宽占用 | 大(密钥、签名长度大) | 小(密钥、签名长度短) |
为什么 ECC 性能更优?我没法给你讲透所有数学细节,但说个直观感受:ECC 用 256 位密钥能达到 AES-128 的安全级别,而 RSA 需要 3072 位。位数少,计算量自然小。这在移动端和 IoT 设备上尤其重要。
SDK 实现示例(Java):
// 生成ECC密钥对
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
keyGen.initialize(new ECGenParameterSpec("secp256r1")); // 我用这条曲线,兼容性好
KeyPair keyPair = keyGen.generateKeyPair();
PublicKey pubKey = keyPair.getPublic();
PrivateKey privKey = keyPair.getPrivate();
// ECC不直接用于加解密(复杂,且性能不如对称加密)
// 通常用于数字签名和密钥交换
// ECDSA签名
Signature signer = Signature.getInstance("SHA256withECDSA");
signer.initSign(privKey);
signer.update(data);
byte[] signature = signer.sign();
// 验签
signer.initVerify(pubKey);
signer.update(data);
boolean ok = signer.verify(signature);
// ECDH密钥交换(双方交换公钥后,各自计算共享密钥)
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
keyAgreement.init(privKey);
keyAgreement.doPhase(peerPublicKey, true);
byte[] sharedSecret = keyAgreement.generateSecret(); // 这就是对称密钥
4.3 算法选型与避坑指南
选择 RSA 还是 ECC?其实没有答案。我结合项目经验给出建议:
- 新项目优先选 ECC:密钥短、性能好、安全性高。除非要兼容老旧系统。
- 遗留系统继续用 RSA:改动成本高,且 RSA 在 2048 位以上仍足够安全。
- 移动端/IoT 必须考虑 ECC:带宽和算力有限,ECC 优势明显。
- 高安全场景用 4096 位 RSA 或 384 位 ECC:但要评估性能影响。
另外,不要自己实现加密算法!这是铁律。用标准库(Java JCA、OpenSSL、Bouncy Castle 等)和公认的算法标识。你想想看,自己写个 RSA 实现,万一哪步错了,密钥就可能被破解。我见过有人用自制 RSA,结果因为随机数生成器伪随机导致密钥可预测……嗯,那项目后来重写了。
4.4 安全防御与 SDK 实现要点
光会用 API 还不够,还得防攻击。非对称加密有几个常见风险:
- 侧信道攻击:攻击者通过时间、功耗、电磁泄漏等物理特征推断密钥。实现时必须用常数时间算法,避免密钥相关分支。
- 填充预言攻击:攻击者观察解密是否报错来猜测明文。用 OAEP 填充并统一报错信息可以防御。
- 密钥泄露:私钥必须严格保护,最好用硬件安全模块(HSM)或安全隔区存储。
- 重放攻击:签名数据中加入时间戳或随机数,确保唯一性。