3 常见签名算法:HMAC‑SHA256、RSA‑SHA256、ECDSA
签名算法是接口认证的“指纹”。你发给服务器的每个请求,都得带上一个别人伪造不了的标记。常见的方案就三种:对称的 HMAC‑SHA256,以及非对称的 RSA‑SHA256 和 ECDSA。我这些年接手的项目里,从内部 API 到开放平台,基本逃不出这三个圈子。下面逐个拆开聊。
3.1 HMAC‑SHA256:简单粗暴的对称签名
HMAC 全称是 Hash‑based Message Authentication Code。说白了就是:把共享密钥和消息揉在一起,算一次 SHA256,然后把结果塞进请求头。
为什么叫“对称”?因为签和验用的是同一个密钥。你俩事先约定好一个 secret,你拿它算签名,服务器拿它验签名。一旦泄露,谁都能伪造请求。
import hmac
import hashlib
import base64
def sign_hmac_sha256(secret: str, message: str) -> str:
# 密钥、消息都转成 bytes
h = hmac.new(secret.encode('utf-8'),
message.encode('utf-8'),
hashlib.sha256)
# 通常用 Base64 对外传输,省得出现不可见字符
return base64.b64encode(h.digest()).decode()
HMAC‑SHA256 的优点是快。我测过一个用 Python 写的网关,每秒能验 2 万次签名,CPU 几乎没感觉。缺点是密钥分发麻烦——你和几百个第三方应用共享同一个 secret?那风险就大了。所以它更适合内部系统间调用。
| 场景 | 推荐度 | 原因 |
|---|---|---|
| 服务间 RPC | ★★★★★ | 密钥可控,性能高 |
| 开放平台 | ★★☆☆☆ | 密钥泄露难以追溯 |
| 小程序/移动端 | ★★★☆☆ | 防逆向难度大,需配合动态密钥 |
3.2 RSA‑SHA256:非对称老大哥
RSA 签名用的是公钥和私钥对。我拿私钥签名,你把我的公钥扔给任何人,他们都能验,但只有我能签。这就是非对称的魅力——你不需要保护公钥,只需要保护好私钥。
签名过程:先对消息算 SHA256 摘要,然后用私钥加密这个摘要。验证时用公钥解密,再对比摘要。当然实际实现用的是 PKCS#1 v1.5 或 PSS 填充,不是为了加密,而是为了抗攻击。
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
def sign_rsa_sha256(private_key_pem: str, message: str) -> str:
key = RSA.import_key(private_key_pem)
h = SHA256.new(message.encode())
# pkcs1_15 是标准填充
signature = pkcs1_15.new(key).sign(h)
return base64.b64encode(signature).decode()
def verify_rsa_sha256(public_key_pem: str, message: str, signature_b64: str) -> bool:
key = RSA.import_key(public_key_pem)
h = SHA256.new(message.encode())
try:
pkcs1_15.new(key).verify(h, base64.b64decode(signature_b64))
return True
except (ValueError, TypeError):
return False
我参与过一个开放平台项目,选择 RSA‑SHA256 是因为第三方应用可以只存公钥,不怕泄露。但刚上线时发现验签速度只有 3000 TPS,比 HMAC 慢了一个数量级。嗯,这里要注意:RSA 的验签比签名更慢,如果服务端需要验大量请求,最好加缓存或升级机器。
| 指标 | RSA‑SHA256 | HMAC‑SHA256 |
|---|---|---|
| 密钥管理 | 私钥保密,公钥公开 | 双方共享同一个 secret |
| 签名性能 | 较慢(约 5000 次/秒) | 极快(约 50000 次/秒) |
| 验签性能 | 更慢(约 2000 次/秒) | 与签名相同 |
| 签名长度 | 256 字节(2048 bit) | 32 字节 |
3.3 ECDSA:短小精悍的现代方案
ECDSA 是基于椭圆曲线的签名算法。它跟 RSA 一样是非对称的,但密钥更短、签名更紧凑。256 位椭圆曲线安全性等价于 3072 位 RSA。你想想看,同样安全等级,ECDSA 签名只有 64 字节(r + s 各 32 字节),对于带宽敏感的场景简直是救命。
实现上,Python 标准库没有直接提供 ECDSA,但 cryptography 包很好用。用 P‑256 曲线(也叫 secp256r1)最流行。
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec, utils
from cryptography.hazmat.primitives import serialization
def sign_ecdsa_sha256(private_key_pem: str, message: str) -> str:
key = serialization.load_pem_private_key(private_key_pem.encode(), password=None)
# 使用 ECDSA + SHA256,编码为 DER 格式
signature = key.sign(message.encode(), ec.ECDSA(hashes.SHA256()))
return base64.b64encode(signature).decode()
def verify_ecdsa_sha256(public_key_pem: str, message: str, signature_b64: str) -> bool:
from cryptography.exceptions import InvalidSignature
key = serialization.load_pem_public_key(public_key_pem.encode())
try:
key.verify(base64.b64decode(signature_b64), message.encode(), ec.ECDSA(hashes.SHA256()))
return True
except InvalidSignature:
return False
ECDSA 的验签速度接近 RSA,但签名速度更快。我记得有一个 IoT 项目,设备用 ESP32,算力有限。用 RSA 2048 签名需要 500ms,换成 ECDSA P‑256 只用了 80ms——设备电池寿命提升了一大截。选什么算法,还得看你的硬件跑不跑得动。
| 算法 | 密钥对生成 | 签名速度(参考) | 验签速度 | 签名长度 |
|---|---|---|---|---|
| HMAC‑SHA256 | 不适用 | ~50 000 /s | ~50 000 /s | 32 B |
| RSA‑SHA256 2048 | 慢(秒级) | ~5 000 /s | ~2 000 /s | 256 B |
| ECDSA P‑256 | 快(毫秒级) | ~8 000 /s | ~2 500 /s | 64 B |
最后来一个总对比表,方便你决策时快速参考。
| 维度 | HMAC‑SHA256 | RSA‑SHA256 | ECDSA |
|---|---|---|---|
| 密钥类型 | 对称(一个 secret) | 非对称(私钥+公钥) | 非对称(私钥+公钥) |
| 签名长度 | 32 字节 | 256 字节(2048 bit) | 64 字节(P‑256) |
| 签名速度 | ★★★★★ | ★★★☆☆ | ★★★★☆ |
| 验签速度 | ★★★★★ | ★★☆☆☆ | ★★★☆☆ |
| 密钥分发难度 | 高(双方需安全信道) | 低(公钥可公开) | 低(公钥可公开) |
| 抗量子计算 | 弱 | 弱 | 弱(但可升级到 ECC 安全等级) |
| 推荐场景 | 内部 RPC、微服务 | 开放平台、遗留系统 | 移动端、IoT、新项目 |