3. 密码学基础(下):数字签名、密钥交换、随机数与PKI

好,咱们接着往下聊。上一节我们把对称加密、非对称加密和哈希函数过了一遍,这些都是TLS的“砖块”。这一节要讲的,是这些砖块怎么砌成墙——数字签名保证身份、密钥交换保证安全握手、随机数保证不可预测,而PKI则是整个信任体系的骨架。

我个人习惯把这一章叫做“TLS的信任链”。你想想看,没有这些机制,加密再强也没用——你连对面是谁都不知道,加密给谁呢?

3.1 数字签名:不只是“签个名”

数字签名,说白了就是用私钥加密一段摘要,别人用公钥验证。但这里有个关键点:签名不是加密整个消息,而是加密消息的哈希值。

核心流程:

  1. 发送方对消息做哈希,得到摘要
  2. 用私钥加密摘要,生成签名
  3. 接收方用公钥解密签名,得到摘要A
  4. 接收方对消息做哈希,得到摘要B
  5. 比较A和B,一致则签名有效

我在项目中遇到过一个问题:有人直接用RSA加密整个消息当签名。结果消息太长,RSA根本处理不了。嗯,这就是没理解“哈希+签名”这个组合的意义。

常见的签名算法有这些:

算法 密钥长度 签名长度 典型场景
RSA-PSS 2048-4096 bit 与密钥等长 TLS证书签名
ECDSA 256-521 bit 64-132字节 嵌入式TLS握手
Ed25519 256 bit 64字节 轻量级设备

我的建议:在嵌入式场景下,优先选ECDSA或Ed25519。RSA签名太长,对MCU的RAM和Flash都不友好。我曾经在一个Cortex-M4的项目里用RSA 4096签名,结果每次握手要多花200ms——后来换成ECDSA P-256,直接降到30ms。

3.2 密钥交换:DH与ECDH

密钥交换解决的是这个问题:两个从没见过面的人,怎么在公开信道上商量出一个只有他俩知道的秘密?

DH(Diffie-Hellman)就是答案。它的数学原理其实不复杂:

  • 双方约定一个大素数p和一个生成元g
  • 各自生成随机私钥a和b
  • 计算公钥A = g^a mod p,B = g^b mod p
  • 交换公钥后,各自计算共享密钥:K = B^a mod p = A^b mod p

你看,中间人即使拿到了p、g、A、B,也计算不出a或b——这就是离散对数问题的难解性。

但DH有个问题:计算太慢了。尤其是p选得很大时,模幂运算在嵌入式设备上简直是噩梦。

所以有了ECDH——把DH搬到了椭圆曲线上。同样的安全强度,ECDH的密钥更短、计算更快。

安全等级 DH密钥长度 ECDH密钥长度
80 bit 1024 bit 160 bit
128 bit 3072 bit 256 bit
256 bit 15360 bit 512 bit

注意:ECDH虽然快,但曲线选择很关键。我曾经见过有人用secp256r1(P-256)以外的曲线,结果库不支持,调试了整整两天。嵌入式开发里,曲线兼容性比理论安全性更现实。建议统一用NIST P-256或Curve25519。

3.3 随机数生成:TLS的“命根子”

这句话我说得很重,但事实如此。TLS里几乎所有安全机制都依赖随机数:

  • DH/ECDH的私钥
  • TLS握手的Client Random和Server Random
  • 对称加密的IV(初始化向量)
  • 会话ID和Cookie

随机数一旦可预测,整个TLS连接就形同虚设。我见过一个案例:某IoT设备用rand()生成TLS随机数,结果每次重启后握手随机数都一样——攻击者直接重放攻击,轻松破解会话。

嵌入式设备上怎么生成真随机数?

方案 原理 优缺点
硬件TRNG 利用芯片内部热噪声 真随机,但部分MCU没有
ADC噪声采样 悬空ADC引脚读噪声 成本低,速率慢
外部熵源 WiFi/蓝牙射频噪声 依赖外设,不稳定
混合方案 硬件熵源+软件熵池 推荐做法,兼顾安全与性能

我的做法:在STM32上,我习惯用RNG外设(硬件TRNG)作为主熵源,同时用系统滴答定时器的低几位作为辅助熵源。每次TLS握手前,至少收集128字节的随机熵,再通过SHA-256做一次熵提取。这样即使硬件RNG有偏差,也能保证输出均匀。

3.4 证书与PKI:信任的锚点

数字签名解决了“消息是谁发的”,但没解决“这个公钥到底属于谁”。证书就是干这个的——它是一个数字身份证,把公钥和身份绑定在一起。

PKI(公钥基础设施)是管理证书的完整体系,包括:

  • CA(证书颁发机构):签发证书的权威机构
  • RA(注册机构):验证申请者身份
  • 证书库:存储和分发证书
  • CRL/OCSP:证书吊销机制

X.509证书是最常用的格式,里面包含:

证书结构(简化版):
├── 版本号 (V3)
├── 序列号
├── 签名算法 (如 sha256WithRSAEncryption)
├── 颁发者 (CA的DN)
├── 有效期 (notBefore / notAfter)
├── 主体 (证书持有者的DN)
├── 主体公钥信息 (算法 + 公钥)
├── 扩展字段 (密钥用途、基本约束等)
└── CA的签名

在嵌入式TLS里,证书验证是性能瓶颈。我做过一个测试:在ESP32上验证一个2048位RSA证书链(根CA+中间CA+设备证书),耗时约1.2秒。换成ECDSA P-256后,降到0.3秒。

避坑指南:我曾经在一个项目里直接硬编码了根证书,结果根证书过期后所有设备都连不上服务器。后来我加了证书过期检查和OTA更新机制。记住:证书有生命周期,嵌入式设备必须能更新信任锚。

3.5 知识体系总览

下面这张图把这一章的核心逻辑串起来了。你看,数字签名、密钥交换、随机数和PKI不是孤立的——它们共同构成了TLS握手的信任基础。

密码学基础(下)知识体系 密码学基础(下)知识体系 TLS安全基础 数字签名 密钥交换 随机数生成 证书与PKI RSA-PSS ECDSA Ed25519 DH (模幂) ECDH (椭圆曲线) P-256 / Curve25519 硬件TRNG ADC噪声 混合熵池 CA / RA X.509证书 CRL / OCSP 核心逻辑:数字签名验证身份 → 密钥交换协商会话密钥 → 随机数保证不可预测 → PKI提供信任锚 四者缺一不可,共同构成TLS握手的密码学基础

嗯,这一章的内容确实不少。但你要记住:密码学不是拼积木,而是搭骨架。每个组件都有它的位置和职责,少一个都不行。