加密算法基础:对称加密、非对称加密、哈希算法
先问大家一个问题:你在设计接口时,有没有想过数据到底怎么保护?
很多人一上来就说「用HTTPS就行了」。但说实话,HTTPS只解决了传输层的安全,到了业务层,我们还得自己管权限、防篡改。而这一切的根基,就是今天要聊的三种加密算法。
我个人习惯把加密算法比作工具箱里的三把扳手——各有各的用处,用错了地方,轻则性能爆炸,重则安全漏洞。咱们一个个看。
对称加密:又快又简单,但钥匙怎么给?
对称加密,就是加密和解密用同一把钥匙。你想想看,就像你用一把锁锁住保险箱,开锁也是同一把钥匙。速度非常快,适合加密大量数据。
常用的对称加密算法有:
- AES(Advanced Encryption Standard)—— 目前最主流,密钥长度128、192、256位
- DES —— 老古董了,密钥太短(56位),别用了
- 3DES —— 兼容阶段用,性能差,逐步淘汰
- SM4 —— 国密标准,国内项目经常碰到
我在项目中遇到过这么个坑:有人把AES的密钥写死在代码里,结果代码泄露,整个系统数据裸奔。记住,对称加密的最大难题不是算法本身,而是密钥分发。你怎么安全地把钥匙交给对方?
非对称加密:公钥私钥,完美解决钥匙传递
非对称加密,用一对钥匙:公钥加密,私钥解密。公钥随便给人,私钥自己藏好。这样你不需要事先跟对方商量密钥,就能安全通信。
常见的非对称算法:
- RSA —— 最经典,密钥长度至少2048位,1024位已被破解
- ECC(椭圆曲线加密) —— 同等安全强度下,密钥短、速度快,推荐使用
- SM2 —— 国密椭圆曲线算法,国内合规必备
我曾经犯过一个错误:直接用RSA加密了100KB的JSON,结果接口响应时间飙升到5秒,被领导骂了一顿。嗯,从那以后我就记住了:非对称加密只适合加密小数据块,比如密钥、哈希值。
哈希算法:不是加密,但比加密更常用
哈希算法,严格来说不是加密,因为它是单向的。你没法从哈希值还原原文。但它用来做权限验证、数据完整性校验非常合适。
常见哈希算法:
- MD5 —— 128位,现在已经被破解,只能做校验,不能用于安全场景
- SHA-1 —— 160位,同样不安全,别再用了
- SHA-256 —— 安全,256位,推荐
- SM3 —— 国密哈希,256位
你可能会问:为什么哈希算法在细粒度权限控制里这么重要?
因为令牌、签名、防篡改、密码存储都靠它。举个具体例子:我们做接口签名时,通常把请求参数排序后用哈希算法计算一个摘要,加上时间戳和密钥,防止请求被篡改。这就是哈希的经典用法。
三种算法的对比
| 特性 | 对称加密 | 非对称加密 | 哈希算法 |
|---|---|---|---|
| 钥匙数量 | 一把密钥 | 公钥+私钥 | 无钥匙 |
| 是否可逆 | 可逆(解密) | 可逆(解密) | 不可逆 |
| 性能 | 快 | 慢 | 很快 |
| 主要用途 | 加密大量数据 | 密钥交换、数字签名 | 完整性校验、密码存储 |
| 推荐算法 | AES-256-GCM | ECC(P-256) | SHA-256 |
代码示例:看看真实项目怎么用
下面给出一段伪代码风格的Java示例,展示三种算法在接口签名中的协作。
// 1. 用AES加密请求体(对称加密)
byte[] body = "userId=123&action=read".getBytes();
SecretKey aesKey = KeyGenerator.getInstance("AES").generateKey();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encryptedBody = cipher.doFinal(body);
// 2. 用RSA公钥加密AES密钥(非对称加密)
PublicKey rsaPublicKey = loadPublicKey();
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
rsaCipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
byte[] encryptedKey = rsaCipher.doFinal(aesKey.getEncoded());
// 3. 用SHA-256计算整个请求的签名(哈希)
String raw = encryptedBody + "|" + encryptedKey + "|timestamp=1700000000";
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(raw.getBytes());
String requestSignature = Base64.getEncoder().encodeToString(hash);
// 最终发送:encryptedBody + encryptedKey + requestSignature
好了,三种算法讲完了。你可能发现一个规律:没有一种算法是万能的。我们需要把它们组合起来,才能构建安全的细粒度权限控制体系。下一环节我们就会看到它们如何协作——不过那是后面的事了。