加密基础:对称与非对称、哈希与签名
说实话,很多做API网关集成的同学,一上来就问我该用哪种加密。我觉得吧,先把底层的加密原理搞清楚,后面集成才会顺手。这章我们就把对称加密、非对称加密、哈希函数和数字签名这四块地基给夯实了。
对称加密:快,但密钥怎么管?
对称加密,同一个密钥既用来加密,也用来解密。我当年第一个生产项目用的就是 AES-256-GCM,速度快,硬件支持也好。你想想看,加解密一个 1MB 的 JSON 请求体,AES 只需要几毫秒。
核心要点:对称加密做的是 机密性保护。在 API 网关层,主要用来加密传输中的敏感数据。
常用的对称加密算法有这些:
| 算法 | 密钥长度 | 模式 | 特点 |
|---|---|---|---|
| AES | 128 / 256 bit | GCM / CBC / CTR | 最主流,硬件加速 |
| ChaCha20 | 256 bit | Poly1305 | 移动端性能好 |
| 3DES | 168 bit | CBC | 已不推荐,太慢 |
我个人习惯用 AES-256-GCM。GCM 模式自带认证标签,能防止密文被篡改。不过密钥怎么安全地分发给网关和各个微服务呢?这个我放在后面讲。
避坑提醒:我曾经在项目里看到有人用 ECB 模式给银行卡号加密。ECB 模式同样的明文块会产生同样的密文块,说白了就是没隐藏模式。千万别用!
非对称加密:慢,但密钥分发安全
非对称加密有两个密钥——公钥和私钥。公钥可以公开,私钥自己藏好。用公钥加密的数据只有私钥能解密。
这里有个经典场景:客户端用服务器的公钥加密 API 请求里的敏感字段,服务器用私钥解密。这样就绕过了密钥分发问题。
| 算法 | 密钥长度 | 安全强度 | 性能 |
|---|---|---|---|
| RSA | 2048 / 4096 bit | 高 | 慢 |
| ECC | 256 bit | 更高 | 快(同样安全等级) |
我在做支付网关时,遇到过 RSA 加解密太慢的坑。后来切换到 ECC(椭圆曲线加密),同样的安全强度下,性能提升了 3 倍多。你想想看,网关层每秒几千个请求,这点差距就是生死线。
我的建议:新项目直接用 ECC 吧。签名用 ECDSA,密钥交换用 ECDH。RSA 兼容性好但已经够老了。
哈希函数:单向的指纹机
哈希函数,说白了就是给任意长度的数据打一个固定长度的「指纹」。这个指纹不可逆——你不能从指纹反推出原始数据。
在 API 网关里,哈希函数主要干三件事:
- 校验数据完整性——请求体有没有被篡改?计算一次哈希就知道。
- 密码存储——永远不要存明文密码,存密码的哈希值。
- 签名的基础——先对数据取哈希,再对哈希做签名。
我用得最多的是 SHA-256。输出 256 位,32 个字节,安全强度够用。千万别再用 MD5 或 SHA-1 了,它们已经被攻破了。我记得有一次做安全审计,发现内部系统还在用 MD5 校验文件,当场就让改了。
记住:哈希函数不是加密。它是不可逆的,没有密钥这个概念。
数字签名:防抵赖的杀手锏
数字签名 = 先哈希,再用私钥签名。验证的时候,用公钥验签。这个组合拳解决了三个问题:
- 身份认证——是谁发的?
- 数据完整性——数据有没有被改过?
- 不可抵赖——发件人没法否认自己发过。
在 API 网关上,我们经常对请求体做数字签名。客户端用私钥签名,网关用公钥验签。这样一来,即使请求在公网上被截获,攻击者也伪造不了合法的请求。
// 伪代码:签名与验签过程
// 签名(客户端)
message = "POST /api/payment amount=100"
digest = SHA256(message)
signature = ECDSA.sign(digest, privateKey)
// 验签(网关)
digest = SHA256(receivedMessage)
isValid = ECDSA.verify(digest, signature, publicKey)
我曾经踩过的坑:签名时没有包含时间戳和随机数。结果被攻击者重放了一个半小时前的合法请求,差点造成重复支付。后来加上了 nonce + timestamp,才把这个洞补上。
小结:加密组合的选择
这几种加密技术不是孤立的。在实际的 API 网关中,我们经常这样搭配:
- 用非对称加密交换对称密钥(比如 TLS 的握手阶段)
- 用对称加密加密实际数据(AES 快,适合大流量)
- 用哈希 + 私钥做签名(不可抵赖)
- 用公钥验签(身份认证 + 数据完整性)