2. 密码学基础:对称加密、非对称加密、哈希函数、数字签名

做 HSM 密钥边界安全,说白了绕不开四样东西:对称加密、非对称加密、哈希函数、数字签名。你别看它基础,我这些年跟硬件安全模块打交道,翻车最多的往往不是协议层,而是这些底层原语用错了。

举个例子。有一次客户说他们的 HSM 密钥导出功能老被审计部门打回,我过去一看,好家伙——用 ECB 模式加密密钥包。同一密钥块在密文里重复出现,简直就是直接告诉对手「这里有规律」。咱们挨个捋清楚。

2.1 对称加密

对称加密就是加密和解密用同一把钥匙。速度快,适合大批量数据。我习惯把它想象成一把锁——谁拿着钥匙谁就能开。

常用算法:AES(Advanced Encryption Standard),密钥长度 128/192/256 位。DES 已经过时了,别碰。3DES 还能在一些老旧系统里见到,但 NIST 已经不建议用了。

工作模式很重要。我列个表,你一看就明白。

模式特点常见坑
ECB每个数据块独立加密明文规律会泄露到密文
CBC前一个密文块参与当前块加密初始化向量必须随机
GCM加密同时提供完整性校验nonce 重复完蛋
CTR计数器模式,可并行密钥流不可重用
警告:ECB 模式在 HSM 中几乎绝不能用。我曾经见过一个密钥管理方案用 ECB 加密 16 字节的密钥块,结果前 4 字节是固定魔数,后 4 字节是密钥类型——密文前 8 字节完全一致。审计方一眼就识别出来了。HSM 里通常强制要求 CBC 或者 GCM。

对称加密在 HSM 里通常用来保护传输中的密钥(Key Transport),或者加密存储在模块内部的工作密钥。嗯,注意一点:HSM 导出的密钥包会用对称密钥再加密一层,这个密钥本身由 HSM 主密钥派生。

// 伪代码:HSM 内部对称加密密钥包
// AES-256-GCM 模式
key_package = aes_gcm_encrypt(
    plaintext_key, 
    key_encryption_key (KEK), 
    iv = secure_random(12 bytes),
    aad = key_attributes_metadata
)
// 输出: iv || ciphertext || tag

2.2 非对称加密

非对称加密有一对钥匙:公钥加密,私钥解密。或者私钥签名,公钥验签。它解决了密钥分发问题——公钥可以公开,私钥必须锁在 HSM 里。

常用算法:RSA(Rivest–Shamir–Adleman)和 ECC(Elliptic Curve Cryptography)。我个人偏爱 ECC,同等安全强度下密钥更短,对 HSM 内存友好。

你的 HSM 生成 RSA 2048 位密钥对,公钥可以导出,私钥永远不离开硬件边界。这是基本原则。我遇到过有人把私钥用 PKCS#8 导出到文件里,美其名曰「备份」——这不是备份,是裸奔。

关键概念:非对称加密在 HSM 场景下主要用于密钥封装(Key Encapsulation)和数字签名。比如用对方的 RSA 公钥加密一个会话密钥,对方用 HSM 内部的私钥解密。整个过程中明文密钥不落盘。

ECC 里常用的曲线是 P-256(secp256r1)和 P-384。国密标准用 SM2。别用那些非主流的曲线,审计过不去。

2.3 哈希函数

哈希函数把任意长度数据压缩成固定长度的摘要。它是单向的,不可逆。说白了就是「指纹」。

常用算法:SHA-256(输出 32 字节),SHA-384,SHA-512。MD5 和 SHA-1 已经撞车了,不要再用了。

哈希在 HSM 里干三件事:

  1. 完整性校验:固件镜像、配置文件的哈希,确保没人篡改。
  2. 派生密钥:用 HKDF(基于 HMAC 的密钥派生函数),输入主密钥和上下文,输出工作密钥。
  3. 消息摘要:先对消息做哈希,再对哈希签名,效率高。

这里有个坑:哈希碰撞。你想想看,如果两个不同文件哈希一样,那签名就可能被伪造。目前 SHA-256 是安全的,但量子计算来了之后可能要升级到 SHA-3。

2.4 数字签名

数字签名 = 哈希 + 非对称加密。发送方用私钥签名,接收方用公钥验签。保证来源可信(认证)+ 内容没改(完整性)+ 无法抵赖(不可否认性)。

我经常跟团队说:HSM 最核心的使命就是管理签名私钥。签名私钥一旦泄露,整个信任链就塌了。

常见的签名算法:RSA-PSS(带概率性的填充方案)、ECDSA(基于 ECC)、EdDSA(Ed25519)。HSM 通常支持 RSA-PSS 和 ECDSA。EdDSA 支持度少一些,但性能更好。

避坑指南:我曾经接手过一个项目,HSM 签名只用了 PKCS#1 v1.5 填充方案。审计方说这个方案有已知攻击面,建议升级到 RSA-PSS。虽然实际攻击很难,但合规不过就是不行。后来我们全部切换到 PSS 了。现在新项目我都会默认用 PSS 或 ECDSA。

签名过程大致是这样:

1. 对原文 M 做 SHA-256 哈希 → H
2. 用 HSM 中存储的私钥对 H 做签名 → S
3. 输出签名 S 和原文 M
4. 验证方用公钥解密 S 得到 H1,再计算 M 的哈希 H2
5. 比较 H1 == H2,一致则签名有效

这里你需要注意:签名操作必须在 HSM 内部完成。私钥不能出 HSM 的边界。调用者只能传入待签名的哈希值(或者原文让 HSM 自己做哈希),然后收回来一个签名值。

2.5 四种原语的关系(一图胜千言)

下面这张图把四者的关系和典型应用串起来了。你可以看到它们如何在 HSM 场景下协同工作。

密码学四件套关系图(HSM场景) 对称加密 AES-256-GCM 非对称加密 RSA / ECC / SM2 哈希函数 SHA-256 / SHA-3 数字签名 RSA-PSS / ECDSA 密钥封装 先哈希再签名 私钥签名 HSM 中私钥不出边界 签名操作在硬件内部完成 哈希用于完整性校验

2.6 总结一下实践要点

  • 对称加密:优先用 AES-256-GCM,不用 ECB。HSM 里密钥加密密钥(KEK)用对称方式保护传输中的密钥。
  • 非对称加密:公钥随意导出,私钥死守 HSM。RSA 2048 起步,ECC P-256 够用。
  • 哈希函数:SHA-256 是基线。用于派生密钥时一定要加盐(HKDF)。
  • 数字签名:避免 PKCS#1 v1.5,用 RSA-PSS 或 ECDSA。签名私钥的备份要经过加密华强认证。
工程师备忘:每次跟 HSM 交互,问自己三个问题:①这个密钥在哪个边界内存在?②这个操作是加密、签名还是哈希?③结果落盘时有没有被保护?三问之后,八成漏洞能挡掉。

嗯,基础牢固了,后面讲 HSM 的密钥生命周期、访问控制、安全策略才能接得上。别着急,一步一步来。