数字签名方案深度对比:SM2 vs ECDSA vs EdDSA

实践教程 · 2026-06-03 · 29 阅读

为什么需要对比这三种方案

数字签名是密码学的核心原语,用于身份认证、数据完整性保护和不可否认性。SM2、ECDSA、EdDSA 是目前最主流的三种方案,但它们的设计哲学、安全假设和性能特征差异显著。

特性SM2ECDSAEdDSA
标准来源国密 GM/T 0003-2012NIST FIPS 186-4RFC 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 2139F0A0

ECDSA 曲线参数(以 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 27D2604B

EdDSA 曲线参数(以 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)
关键特性:SM2 的签名值与消息和公钥都绑定,提供了比 ECDSA 更强的安全属性。

ECDSA 签名

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)
关键风险:如果 k 值泄露或重复,私钥可直接计算。2010 年 Sony PS3 被破解就是因为 k 值固定。

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 signature

EdDSA 签名

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)
关键优势:确定性签名,不需要随机数生成器,天然抵抗 k 值泄露攻击。

PYTHON
from cryptography.hazmat.primitives.asymmetric import ed25519

def eddsa_sign(private_key: ed25519.Ed25519PrivateKey, message: bytes) -> bytes:
    """Ed25519 签名"""
    return private_key.sign(message)

安全性对比

已知攻击

攻击类型SM2ECDSAEdDSA
k 值泄露私钥泄露私钥泄露不适用(确定性)
k 值重复私钥泄露私钥泄露不适用
侧信道攻击需要防护需要防护天然抵抗
故障攻击需要防护需要防护需要防护

安全强度

方案安全强度等效对称密钥
SM2-256128 位AES-128
ECDSA P-256128 位AES-128
Ed25519128 位AES-128

性能对比

以下数据基于 Intel i7-12700H,Python 3.11,仅供参考:

操作SM2ECDSA P-256Ed25519
密钥生成0.5 ms0.3 ms0.1 ms
签名0.8 ms0.5 ms0.05 ms
验签1.2 ms0.8 ms0.15 ms
签名长度64 B64 B64 B
EdDSA 在签名和验签速度上显著领先,主要得益于 Edwards 曲线的高效点运算。

适用场景选型

选择 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*