3、常见加密算法详解:AES、RSA、ECC、SHA-256
做加密 SDK 测试,头一件事就是搞懂这些算法到底在干什么。我刚入行那会儿,对着 AES、RSA 这些名字一脸懵,以为全是一回事。后来踩了几次坑才明白——选错算法,安全系数直接归零。今天我就把这四个主流算法掰开揉碎讲一遍,配上我这些年攒下的教训。
核心原则先记住:
- 对称加密(AES) —— 加密快,但密钥分发麻烦
- 非对称加密(RSA、ECC) —— 密钥管理方便,但慢
- 哈希(SHA-256) —— 不可逆,用做“指纹”
实际项目中往往组合使用:非对称交换密钥,对称加密数据,哈希校验完整性。
3.1 AES:对称加密的工业标准
AES 是目前最常用的对称加密算法。说白了就是加密和解密用同一把钥匙。我最早在物联网项目里接触它,当时密钥直接写在固件里——后来被反向工程打了个稀巴烂。从那以后我养成一个习惯:AES 密钥不硬编码。
AES 支持三种密钥长度:128、192、256 位。我个人建议直接用 AES-256,性能开销其实不大,但安全裕量高不少。
工作模式
模式选不对,加密等于白加密。下面是我常用的几种:
| 模式 | 特点 | 推荐场景 | 我的评价 |
|---|---|---|---|
| ECB | 每个块独立加密,相同明文得到相同密文 | 几乎不推荐 | 千万别用,有图样攻击 |
| CBC | 需要初始化向量 (IV),块之间链接 | 传统文件加密 | 能用,但要随机IV |
| GCM | 带认证的加密,同时校验完整性 | 网络传输、TLS | 我最推荐 |
下面是一个用 Python 的 cryptography 库做 AES-GCM 加密的示例(生产环境中请别硬编码密钥):
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
key = AESGCM.generate_key(bit_length=256) # 32字节
aesgcm = AESGCM(key)
nonce = os.urandom(12) # 12字节随机数
plaintext = b"这是要加密的敏感数据"
ciphertext = aesgcm.encrypt(nonce, plaintext, None)
# 解密
decrypted = aesgcm.decrypt(nonce, ciphertext, None)
print(decrypted.decode())
3.2 RSA:非对称加密的老前辈
RSA 基于大整数分解难题,公钥加密、私钥解密,或者反过来做签名。我在金融 SDK 里写过 RSA 签名验证,遇到过最坑的问题:密钥长度不够。几年前还有人用 1024 位,后来被学术界证明可破解,现在至少 2048 位,建议直接上 4096。
RSA 的缺点很明显:慢,而且能加密的数据长度受密钥大小限制。举个例子,2048 位 RSA 一次只能加密 190 字节左右。所以你不会拿 RSA 去加密大文件——它更适合交换对称密钥。
我曾经踩过的坑: 用 RSA 加密一段 300 字节的 JSON,结果发现解密后数据被截断了。查了半天才发现加密数据不能超过密钥长度减去 OAEP padding 开销。后来我改成先用 RSA 加密 AES 密钥,再用 AES 加密实际数据。
RSA 常用的填充方式:
- PKCS#1 v1.5 —— 兼容性好,但有攻击向量(如 Bleichenbacher 攻击)
- OAEP(推荐) —— 更安全,现在基本是标准
签发签名时用 PSS 填充,安全性更高。我一般直接用 cryptography 库的 rsa.OAEP。
3.3 ECC:更高效率的非对称方案
ECC(椭圆曲线加密)用更短的密钥达到和 RSA 同等级别的安全强度。比如 256 位 ECC 密钥 ≈ 3072 位 RSA 密钥。我最早接触 ECC 是在移动端证书登录项目里——手机性能有限,RSA 握手实在太慢了。
你想想看,同样是安全等级,ECC 的密钥小、计算快、带宽省。所以在现代协议中(比如 TLS 1.3、SSH、区块链),ECC 几乎取代了 RSA。
| 安全级别 (bits) | RSA 密钥长度 | ECC 密钥长度 |
|---|---|---|
| 80 | 1024 | 160 |
| 112 | 2048 | 224 |
| 128 | 3072 | 256 |
| 256 | 15360 | 512 |
实际开发中推荐曲线:NIST P-256(兼容性好),或者 Curve25519(X25519,原生防侧信道)。ECDH 用于密钥交换,ECDSA 用于签名。
SECP256R1)就对了。
3.4 SHA-256:不可逆的哈希函数
SHA-256 不是加密,是哈希。它把任意长度的输入压缩成 256 位(32 字节)的摘要,而且不可逆。很多人都问我:“能不能从 SHA-256 还原出原文?” 答案是不能,这是单向函数。
它的用途很明确:
- 文件完整性校验 —— 下载后算 SHA-256,对比官方值
- 密码存储 —— 但不要直接用 SHA-256,要用加盐的慢哈希(如 bcrypt、scrypt)
- 数字签名中的消息摘要 —— 先对消息算哈希,再对哈希签名
我曾经在内部系统里直接用 SHA-256 存用户密码,结果撞库一撞一个准。后来赶紧改成 bcrypt + 随机盐。记住:SHA-256 是“指纹”而不是“锁”。
SHA-256 的抗碰撞性至今没被攻破(截至 2025 年),可以放心用于校验场景。但要注意 长度扩展攻击——如果用作 MAC(消息验证码),要用 HMAC-SHA256,别直接拼接密钥。
import hashlib
data = b"hello world"
digest = hashlib.sha256(data).hexdigest()
print(digest) # 64位十六进制字符串
注意: SHA-256 不是加密。有人把“加密”和“哈希”混着用,导致系统设计出大漏洞。加密可逆,哈希不可逆。千万别用 SHA-256 来“加密”你的数据——它只能保证别人改了你就知道,但不能保密内容。
3.5 算法选型速查表
| 算法 | 类型 | 常用密钥长度 | 性能 | 典型场景 |
|---|---|---|---|---|
| AES-256-GCM | 对称加密(带认证) | 256 位 | 快(硬件加速) | 数据加密、网络传输 |
| RSA-2048 | 非对称加密 | 2048 位 | 慢(指数运算) | 密钥交换、数字签名 |
| ECC P-256 | 非对称加密/密钥交换 | 256 位 | 快(椭圆曲线运算) | 移动端、区块链、TLS 1.3 |
| SHA-256 | 哈希函数 | 输出 256 位 | 很快 | 完整性校验、消息摘要 |
好了,四种算法讲清楚了。你在实际测试 SDK 时,记住组合思路:ECC 交换 AES 密钥,AES-GCM 加密业务数据,SHA-256 校验整体完整性。这套组合拳在绝大多数场景下够用、安全、高效。