4. 密码学基础回顾:对称加密、非对称加密、哈希函数与数字签名

说实话,做 TEE 开发这几年,我最大的感触就是:密码学不是选修课,是生存技能。你想想看,TEE 的核心价值就是“在硬件隔离区里安全地做密码运算”。如果你连 AES、RSA、SHA-256 这些基本功都模棱两可,那后面部署签名验签流程时,踩坑几乎是必然的。

这一章咱们不搞数学推导,我直接带你过一遍最常用的四种密码原语,重点放在它们怎么配合、各自解决什么问题、以及我在实际项目中踩过的坑。

4.1 对称加密:AES 是绝对主力

对称加密,说白了就是一把钥匙开一把锁。加密和解密用同一个密钥。速度快,适合加密大量数据。

现在业界标准就是 AES(Advanced Encryption Standard)。我个人习惯用 AES-256-GCM,原因很简单:它不光加密,还带认证,能防篡改。

模式 特点 我的建议
AES-ECB 简单,但相同明文块产生相同密文 千万别用,我在审计中见过多次因此泄露模式
AES-CBC 需要 IV,密文链式依赖 可用,但要注意 IV 随机性
AES-GCM 加密 + 认证,AEAD 模式 首选,TEE 内部通信我全用这个
避坑指南:我曾经在项目里直接用 AES-CBC 加密会话密钥,结果忘了校验 IV 的完整性。攻击者翻转 IV 就能控制解密后的第一个明文块。后来全部改成 GCM 模式,省心多了。

4.2 非对称加密:RSA 与 ECC 的选择

非对称加密,密钥成对出现——公钥加密,私钥解密。它解决了对称加密最头疼的问题:密钥分发。

实际部署中,非对称加密很少用来加密大量数据(太慢),而是用来加密对称密钥或做数字签名。

RSA:老牌劲旅

RSA 基于大整数分解难题。我常用的密钥长度是 2048 位,1024 位已经不安全了,4096 位性能开销太大。

# 生成 RSA 2048 密钥对(OpenSSL 示例)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.pem
openssl rsa -pubout -in private.pem -out public.pem

ECC:后起之秀

ECC(椭圆曲线密码)用更短的密钥提供同等安全强度。256 位的 ECC 密钥 ≈ 3072 位的 RSA 密钥。在 TEE 这种资源受限环境里,ECC 优势明显。

算法 密钥长度(安全等价) 签名速度 验签速度
RSA-2048 112 位安全强度 慢 快
ECC P-256 128 位安全强度 快 较快
Ed25519 128 位安全强度 极快 极快
注意:ECC 虽然好,但曲线选择有坑。不要自己实现曲线参数,直接用标准曲线(如 NIST P-256、Curve25519)。我曾经见过有人用了一个非标准曲线,结果存在小群攻击漏洞,私钥被恢复出来。

4.3 哈希函数:SHA-256 是底线

哈希函数把任意长度的数据映射成固定长度的摘要。它是单向的,不可逆。SHA-256 输出 256 位(32 字节)的摘要。

在 TEE 场景里,哈希函数有三个核心用途:

  • 完整性校验:验证代码或数据有没有被篡改
  • 数字签名的基础:先对消息哈希,再对哈希值签名
  • 派生密钥:结合 HKDF 等算法生成会话密钥
# SHA-256 计算示例(Python)
import hashlib
message = b"Hello, TEE!"
digest = hashlib.sha256(message).hexdigest()
print(digest)  # 输出 64 个十六进制字符
核心原则:永远不要对原始消息直接签名或加密。先哈希,再操作。这能防止长度扩展攻击、选择明文攻击等多种问题。

4.4 数字签名原理:签名与验签的完整流程

数字签名解决的是身份认证和不可否认性问题。你想想看,我怎么证明一段代码确实是你签发的?

流程其实很简单:

  1. 签名方:对消息做哈希 → 用私钥加密哈希值 → 得到签名
  2. 验签方:对消息做哈希 → 用公钥解密签名 → 比对两个哈希值

下面这张图把整个流程串起来了,我建议你多看几遍:

数字签名与验签完整流程 签名方 原始消息 M SHA-256 哈希 私钥加密 输出:签名 S 传输 (M, S) 验签方 SHA-256 哈希 公钥解密 比较两个哈希值是否相等 相等 → 签名有效 | 不等 → 签名无效

4.5 四种原语如何协同工作

在实际的 TEE 签名验签部署中,这四种原语不是孤立使用的。我总结了一个典型的混合加密 + 签名流程:

  1. 发送方:用对称密钥(AES-GCM)加密消息体
  2. 发送方:用接收方公钥(RSA/ECC)加密对称密钥
  3. 发送方:对密文做 SHA-256 哈希,用自己私钥签名
  4. 接收方:用发送方公钥验签,确认身份
  5. 接收方:用自己的私钥解密出对称密钥
  6. 接收方:用对称密钥解密消息体
为什么这么复杂?因为每种算法都有自己的短板。对称加密快但密钥分发难,非对称加密解决了密钥分发但慢,哈希保证完整性,签名保证身份。组合起来,才能构建一个完整的安全通道。

4.6 我在 TEE 项目中踩过的坑

最后分享几个真实教训:

  • 密钥生命周期管理:我曾经把 RSA 私钥直接硬编码在 TA 代码里。后来做安全审计时被直接打回。正确的做法是用 TEE 的密钥存储 API,让私钥永远不离开安全区。
  • 哈希长度扩展攻击:早期用 SHA-256 做 MAC 时,直接用了 H(secret || message) 这种构造。攻击者可以在不知道密钥的情况下伪造合法消息。后来改用 HMAC-SHA256 才解决。
  • 随机数生成:在 TEE 里不要用标准库的 rand(),要用 TEE 提供的硬件随机数生成器。我见过有人用伪随机数生成会话密钥,结果被预测出来。

嗯,密码学基础就回顾到这里。这些原语是后面所有签名验签流程的基石。你如果能把 AES、RSA/ECC、SHA-256 和数字签名的配合逻辑理清楚,后面部署 TEE 签名验签流程时,就会觉得顺理成章了。