4. 密码学基础(二):数字签名算法简介与签名验证原理

数字签名是 SLO 签名证据校验的核心技术。它提供了身份认证、数据完整性和不可否认性三大安全属性。本节将深入剖析三种主流签名算法——RSA、ECDSA 和 Ed25519 的数学原理、签名生成与验证流程,并对比其适用场景。

4.1 数字签名基本模型

任何数字签名方案都由三个核心算法组成:密钥生成 (KeyGen)、签名 (Sign) 和验证 (Verify)。签名者使用私钥对消息签名,验证者使用对应的公钥验证签名的有效性。

核心概念:数字签名不是对消息本身加密,而是对消息的哈希值进行签名运算。这保证了签名效率与消息长度的解耦。
数字签名通用流程 数字签名通用流程 签名者 (Signer) 私钥 (Private Key) 消息 M 签名算法 Sign 输出 签名 σ (M, σ) 发送 验证者 (Verifier) 公钥 (Public Key) 消息 M + 签名 σ 验证算法 Verify 通过 / 拒绝

4.2 RSA 数字签名

RSA 签名算法基于大整数分解难题。其签名过程本质上是使用私钥对消息哈希进行“解密”运算,验证过程则使用公钥进行“加密”运算。

4.2.1 算法流程

  1. 密钥生成:选择两个大素数 p 和 q,计算 n = p × q 和欧拉函数 φ(n) = (p-1)(q-1)。选择公钥指数 e(通常为 65537),计算私钥指数 d ≡ e⁻¹ mod φ(n)。公钥为 (n, e),私钥为 (n, d)。
  2. 签名生成:计算消息哈希 h = Hash(M),签名 σ = hd mod n。
  3. 签名验证:计算 h' = σe mod n,比较 h' 是否等于 Hash(M)。
安全警告:RSA 签名必须使用填充方案(如 PKCS#1 v1.5 或 PSS)。直接对哈希值进行“裸”RSA 签名极易遭受选择明文攻击和存在性伪造攻击。

4.2.2 参数对比

参数 典型值 安全强度 签名长度
RSA-2048 n=2048 bit 112 bit 256 字节
RSA-3072 n=3072 bit 128 bit 384 字节
RSA-4096 n=4096 bit 150 bit 512 字节

4.3 ECDSA 数字签名

ECDSA(椭圆曲线数字签名算法)基于椭圆曲线离散对数难题(ECDLP)。相比 RSA,ECDSA 在同等安全强度下使用更短的密钥和签名长度,性能更优。

4.3.1 算法流程

  • 密钥生成:选择椭圆曲线参数 (p, a, b, G, n, h)。私钥 d 为随机整数,公钥 Q = d × G(椭圆曲线点乘)。
  • 签名生成:选择随机数 k,计算点 (x₁, y₁) = k × G,计算 r = x₁ mod n。计算 s = k⁻¹ × (Hash(M) + d × r) mod n。签名对为 (r, s)。
  • 签名验证:计算 w = s⁻¹ mod n,计算 u₁ = Hash(M) × w mod n,u₂ = r × w mod n。计算点 P = u₁ × G + u₂ × Q。验证 P 的 x 坐标 mod n 是否等于 r。
实践要点:ECDSA 的随机数 k 必须随机且唯一。如果两次签名使用了相同的 k,攻击者可以直接计算出私钥。著名的 PlayStation 3 签名密钥泄露事件正是源于此漏洞。

4.3.2 常用曲线

曲线名称 密钥长度 安全强度 签名长度 典型应用
secp256k1 256 bit 128 bit 64 字节 比特币、区块链
P-256 (secp256r1) 256 bit 128 bit 64 字节 TLS、WebAuthn
P-384 (secp384r1) 384 bit 192 bit 96 字节 政府级安全

4.4 Ed25519 数字签名

Ed25519 是基于扭曲爱德华曲线(Curve25519)的高性能签名算法。它由 Daniel J. Bernstein 等人设计,以恒定时间执行、抗侧信道攻击和极高性能著称。

4.4.1 算法特点

  • 确定性签名:Ed25519 使用确定性随机数生成,消除了 ECDSA 中随机数重用风险。
  • 恒定时间:所有运算在恒定时间内完成,天然抵抗时序攻击。
  • 小体积:公钥 32 字节,签名 64 字节,密钥生成和签名速度极快。
  • 哈希绑定:签名过程中将公钥哈希绑定到签名中,防止多密钥碰撞攻击。

4.4.2 算法流程

  1. 密钥生成:私钥 sk 为 32 字节随机数。通过 SHA-512 哈希私钥得到 (a, prefix)。公钥 pk = a × B(B 为基点)。
  2. 签名生成:计算 r = SHA-512(prefix || M) mod L,计算 R = r × B。计算 S = (r + SHA-512(R || pk || M) × a) mod L。签名对为 (R, S)。
  3. 签名验证:计算 h = SHA-512(R || pk || M) mod L。验证 S × B == R + h × pk。
性能对比:在同等安全强度(128 bit)下,Ed25519 的签名速度约为 ECDSA P-256 的 2-3 倍,验证速度约为 1.5-2 倍。RSA-2048 的验证速度较快,但签名速度慢且密钥体积大。
三种签名算法对比 三种签名算法核心对比 RSA-2048 密钥: 2048 bit 签名: 256 字节 安全强度: 112 bit 签名慢 / 验证快 需填充方案 ECDSA P-256 密钥: 256 bit 签名: 64 字节 安全强度: 128 bit 需高质量随机数 随机数重用风险 Ed25519 密钥: 256 bit 签名: 64 字节 安全强度: 128 bit 确定性签名 恒定时间执行 推荐:新系统优先选择 Ed25519;兼容性要求高时选择 RSA;区块链场景选择 ECDSA

4.5 签名算法选择建议

在 SLO 签名证据校验场景中,选择签名算法需综合考虑性能、安全性、兼容性和生态支持。

场景 推荐算法 理由
高性能微服务 SLO 校验 Ed25519 签名快、体积小、恒定时间、无随机数风险
与现有 PKI 体系集成 RSA-3072/4096 广泛兼容、证书链成熟、硬件支持好
区块链/去中心化场景 ECDSA (secp256k1) 生态标准、签名长度短、链上验证高效
合规性要求高的场景 ECDSA P-384 满足政府级安全标准、NIST 推荐

4.6 代码示例:Ed25519 签名与验证

以下示例使用 Python 的 cryptography 库演示 Ed25519 签名的完整流程。这是 SLO 证据校验中最推荐的实现方式。

from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives import serialization

# 1. 密钥生成
private_key = ed25519.Ed25519PrivateKey.generate()
public_key = private_key.public_key()

# 2. 序列化公钥(用于分发)
public_key_bytes = public_key.public_bytes(
    encoding=serialization.Encoding.Raw,
    format=serialization.PublicFormat.Raw
)
print(f"公钥 (32字节): {public_key_bytes.hex()}")

# 3. 签名生成
message = b"SLO: latency_p99 < 200ms, window=5m"
signature = private_key.sign(message)
print(f"签名 (64字节): {signature.hex()}")

# 4. 签名验证
try:
    public_key.verify(signature, message)
    print("✓ 签名验证通过:消息完整且来自持有私钥的签名者")
except Exception as e:
    print(f"✗ 签名验证失败: {e}")

# 5. 篡改检测示例
tampered_message = b"SLO: latency_p99 < 300ms, window=5m"
try:
    public_key.verify(signature, tampered_message)
    print("✗ 不应通过(篡改消息)")
except Exception:
    print("✓ 正确拒绝篡改消息")
实践建议:在生产环境中,建议将公钥以 Base64 或 Hex 格式存储在配置中心或密钥管理服务(KMS)中。签名值应附加在 SLO 证据的元数据字段中,与原始消息一同传输。

4.7 签名校验在 SLO 中的关键作用

在 SLO 签名证据校验课程中,数字签名解决了以下核心问题:

  • 来源认证:验证 SLO 报告确实来自声称的服务或监控系统。
  • 防篡改:确保 SLO 数据在传输和存储过程中未被修改。
  • 不可否认:签名者无法否认曾生成过该 SLO 证据。
  • 审计追溯:结合时间戳,形成可验证的 SLO 证据链。