数字签名方案深度对比:SM2 vs ECDSA vs EdDSA
为什么需要对比这三种方案
数字签名是密码学的核心原语,用于身份认证、数据完整性保护和不可否认性。SM2、ECDSA、EdDSA 是目前最主流的三种方案,但它们的设计哲学、安全假设和性能特征差异显著。
| 特性 | SM2 | ECDSA | EdDSA |
|---|---|---|---|
| 标准来源 | 国密 GM/T 0003-2012 | NIST FIPS 186-4 | RFC 8032 |
| 曲线类型 | 素数域 Weierstrass | 素数域 Weierstrass | 扭曲 Edwards |
| 签名确定性 | 确定性 | 随机(需安全随机数) | 确定性 |
| 签名长度 | 64 字节 | 64 字节(P-256) | 64 字节(Ed25519) |
| 验签速度 | 中等 | 较慢 | 快 |
数学基础
椭圆曲线密码学概述
三种方案都基于椭圆曲线离散对数问题(ECDLP):给定曲线上的点 G 和 Q = kG,计算 k 在计算上不可行。
Weierstrass 曲线(SM2、ECDSA 使用):
CODE
y² = x³ + ax + b (mod p)扭曲 Edwards 曲线(EdDSA 使用):
CODE
ax² + y² = 1 + dx²y² (mod p)Edwards 曲线的优势:点加法公式统一(不需要区分点和倍点),天然抵抗某些侧信道攻击。
SM2 曲线参数
SM2 使用 256 位素数域上的椭圆曲线,推荐曲线 sm2p256v1:
CODE
p = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
a = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC
b = 28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93
n = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123
Gx = 32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7
Gy = BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0ECDSA 曲线参数(以 P-256 为例)
NIST P-256(secp256r1)是最广泛使用的曲线:
CODE
p = 2^256 - 2^224 + 2^192 + 2^96 - 1
a = -3
b = 5AC635D8 AA3A93E7 B3EBBD55 769886BC 651D06B0 CC53B0F6 3BCE3C3E 27D2604BEdDSA 曲线参数(以 Ed25519 为例)
Ed25519 使用 Curve25519 的 Edwards 形式:
CODE
p = 2^255 - 19
a = -1
d = -121665/121666 (mod p)签名算法详解
SM2 签名
SM2 签名算法(GM/T 0003.2-2012)流程:
- 计算消息摘要:e = H(Z_A || M),其中 Z_A 包含用户身份和公钥信息
- 生成随机数 k ∈ [1, n-1]
- 计算椭圆曲线点:(x₁, y₁) = kG
- 计算:r = (e + x₁) mod n
- 计算:s = ((1 + d_A)⁻¹ · (k - r·d_A)) mod n
- 签名值为 (r, s)
PYTHON
from gmssl import sm2, sm3, func
def sm2_sign(private_key: str, public_key: str, message: bytes) -> tuple:
"""SM2 签名"""
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
# 计算 Z 值(用户标识 + 公钥的哈希)
za = sm2_crypt._sm3_z(b"1234567812345678", bytes.fromhex(public_key))
# 计算消息摘要
e = sm3.sm3_hash(func.bytes_to_list(za + message))
e = int(e, 16)
# 签名(内部实现)
sign = sm2_crypt.sign(message, private_key)
return signECDSA 签名
ECDSA 签名流程(FIPS 186-4):
- 计算消息摘要:e = HASH(M)
- 生成随机数 k ∈ [1, n-1](必须密码学安全随机)
- 计算椭圆曲线点:(x₁, y₁) = kG
- 计算:r = x₁ mod n
- 计算:s = k⁻¹ · (e + r·d) mod n
- 签名值为 (r, s)
PYTHON
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
def ecdsa_sign(private_key, message: bytes) -> bytes:
"""ECDSA 签名"""
signature = private_key.sign(
message,
ec.ECDSA(hashes.SHA256())
)
return signatureEdDSA 签名
EdDSA 签名流程(RFC 8032):
- 计算私钥哈希:H(h) = hash(private_key)
- 生成确定性随机数:r = H(H(h)[32:] || M)
- 计算椭圆曲线点:R = rB
- 计算:S = (r + H(R || A || M) · a) mod n
- 签名值为 (R, S)
PYTHON
from cryptography.hazmat.primitives.asymmetric import ed25519
def eddsa_sign(private_key: ed25519.Ed25519PrivateKey, message: bytes) -> bytes:
"""Ed25519 签名"""
return private_key.sign(message)安全性对比
已知攻击
| 攻击类型 | SM2 | ECDSA | EdDSA |
|---|---|---|---|
| k 值泄露 | 私钥泄露 | 私钥泄露 | 不适用(确定性) |
| k 值重复 | 私钥泄露 | 私钥泄露 | 不适用 |
| 侧信道攻击 | 需要防护 | 需要防护 | 天然抵抗 |
| 故障攻击 | 需要防护 | 需要防护 | 需要防护 |
安全强度
| 方案 | 安全强度 | 等效对称密钥 |
|---|---|---|
| SM2-256 | 128 位 | AES-128 |
| ECDSA P-256 | 128 位 | AES-128 |
| Ed25519 | 128 位 | AES-128 |
性能对比
以下数据基于 Intel i7-12700H,Python 3.11,仅供参考:
| 操作 | SM2 | ECDSA P-256 | Ed25519 |
|---|---|---|---|
| 密钥生成 | 0.5 ms | 0.3 ms | 0.1 ms |
| 签名 | 0.8 ms | 0.5 ms | 0.05 ms |
| 验签 | 1.2 ms | 0.8 ms | 0.15 ms |
| 签名长度 | 64 B | 64 B | 64 B |
适用场景选型
选择 SM2 的场景
- 国内政务、金融等合规要求国密的系统
- 需要与国密 TLS(GM/T 0024-2014)集成的应用
- 需要双证书(签名证书 + 加密证书)的场景
选择 ECDSA 的场景
- 需要与国际系统互操作的场景
- 已有 NIST 曲线基础设施的系统
- TLS 1.3 客户端证书(广泛支持)
选择 EdDSA 的场景
- 高性能签名需求(如区块链、证书透明度)
- 需要确定性签名的场景
- 新项目,无历史兼容性负担
互操作性注意事项
- 曲线参数不兼容:三种方案使用不同的曲线,密钥不能混用
- 签名格式差异:SM2 使用 (r, s) 原始格式,ECDSA 常用 DER 编码,Ed25519 使用固定 64 字节
- 哈希算法绑定:SM2 绑定 SM3,ECDSA 通常绑定 SHA-256,Ed25519 绑定 SHA-512
总结
三种数字签名方案各有优势:SM2 满足国密合规,ECDSA 生态最广,EdDSA 性能最优。选择时应根据合规要求、性能需求和互操作性综合考虑。对于新项目,如果没有国密合规要求,EdDSA(特别是 Ed25519)是推荐选择。
*参考来源:*
- *GM/T 0003-2012《SM2 椭圆曲线公钥密码算法》*
- *GM/T 0003.2-2012《SM2 第2部分:数字签名算法》*
- *NIST FIPS 186-4《Digital Signature Standard》*
- *RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)*
- *Daniel J. Bernstein et al., "High-speed high-security signatures", 2012*