第二章:密钥生命周期管理

密钥这东西,说白了就是一把锁的钥匙。但跟普通钥匙不一样,密钥从出生到销毁,每个环节都可能出问题。我做了这么多年嵌入式安全,见过太多因为密钥管理不当导致整个系统被攻破的案例。

今天咱们就聊聊密钥的全生命周期模型。嗯,就是密钥从生成、分发、存储、使用到销毁的完整过程。

2.1 密钥生成:起点决定安全高度

密钥生成是第一步,也是最容易被忽视的一步。我个人习惯把密钥生成比作「生孩子」——底子不好,后面再怎么折腾也白搭。

核心原则:密钥必须具有足够的熵(Entropy),且生成过程不可预测。

我在项目中遇到过不少厂商直接用软件随机数生成器(PRNG)来生成密钥。你想想看,PRNG 的种子如果被猜到,那所有密钥就等于公开了。所以我的建议是:

  • 硬件真随机数生成器(TRNG):利用芯片内部的物理噪声源,比如热噪声、振荡器抖动等
  • 混合模式:TRNG 生成种子 + 密码学安全的 PRNG(CSPRNG)扩展
  • 避免使用:标准库的 rand()、时间戳、设备序列号等可预测源
// 不推荐的密钥生成方式
uint8_t key[16];
srand(time(NULL));  // 种子可预测!
for (int i = 0; i < 16; i++) {
    key[i] = rand() % 256;
}

// 推荐的硬件 TRNG 方式
uint8_t key[16];
if (HAL_TRNG_GenerateRandomNumber(&htrng, (uint32_t*)key, 4) != HAL_OK) {
    // 处理错误,不能使用降级方案!
    Error_Handler();
}

⚠️ 我曾经见过一个产品,密钥生成用的是设备 MAC 地址 + 出厂时间戳的哈希值。攻击者只要拿到一台设备,就能推算出所有同批次设备的密钥。这种低级错误,千万别犯。

2.2 密钥分发:传输中的生死考验

密钥生成好了,怎么送到目标设备上?这就是分发阶段要解决的问题。说白了,密钥分发就是「如何在不可信的信道上安全地传递秘密」。

我习惯把分发方式分为两类:

分发方式 适用场景 安全等级
预置烧录(工厂烧录) 量产设备 高(物理安全可控)
密钥协商(如 ECDH) 动态配对 中高
安全通道分发(TLS/DTLS) OTA 更新 中
明文传输 绝对不要用 无

这里有个坑:很多人觉得工厂烧录就万事大吉了。其实不然。我记得有个项目,工厂的烧录脚本直接把密钥明文打印在日志里。嗯,你猜怎么着?那批设备的密钥全被泄露了。

💡 我的经验:工厂烧录时,一定要用加密通道把密钥传给烧录器。烧录器本身也要有防篡改机制。最好用 HSM(硬件安全模块)来管理烧录过程中的密钥。

2.3 密钥存储:最容易被攻破的环节

密钥存储是整个生命周期中最脆弱的环节。为什么?因为密钥一旦存到设备里,就脱离了我们的直接控制。攻击者可以物理接触设备,用各种手段提取密钥。

你想想看,如果密钥直接以明文形式存在 Flash 里,那跟没加密有什么区别?

常见的存储方式安全等级如下:

  • ❌ 明文存储:直接写在 Flash 或 EEPROM 中
  • ⚠️ 软件加密存储:用另一个密钥加密后存储(鸡生蛋问题)
  • ✅ 硬件安全单元(HSM/Secure Element):密钥永远不离开安全芯片
  • ✅ 物理不可克隆函数(PUF):利用芯片物理特性生成唯一密钥
// 错误示范:密钥明文存储
const uint8_t secret_key[32] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
    // ... 密钥直接暴露在二进制文件中
};

// 正确做法:使用安全元件 API
uint8_t key_handle;
if (SE_GenerateKey(SE_KEY_TYPE_AES_128, &key_handle) != SE_OK) {
    Error_Handler();
}
// 后续操作使用 key_handle 引用密钥,而非直接读取密钥值

⚠️ 我曾经拆解过一款 IoT 设备,用逻辑分析仪抓 SPI 总线,直接读到了 Flash 中存储的 AES 密钥。因为厂商把密钥放在了一个固定的偏移地址,而且没有做任何加密保护。这种设计,说白了就是给攻击者送人头。

2.4 密钥使用:运行时安全

密钥在运行时被使用,这个阶段最容易出现侧信道攻击。比如功耗分析、电磁辐射分析、时序分析等。

我个人习惯把密钥使用安全归结为三点:

  1. 最小权限原则:每个密钥只用于特定用途,不要复用
  2. 隔离执行:密钥操作在安全环境中执行(如 TrustZone、TEE)
  3. 防侧信道:使用常数时间实现,避免基于数据的分支
// 不安全的比较方式(时序侧信道)
int memcmp_unsafe(const uint8_t *a, const uint8_t *b, size_t len) {
    for (size_t i = 0; i < len; i++) {
        if (a[i] != b[i]) return 0;  // 一旦不匹配就返回,时序可被分析
    }
    return 1;
}

// 安全的常数时间比较
int memcmp_safe(const uint8_t *a, const uint8_t *b, size_t len) {
    volatile uint8_t result = 0;
    for (size_t i = 0; i < len; i++) {
        result |= a[i] ^ b[i];  // 始终执行完整循环
    }
    return (result == 0);
}

💡 避坑指南:我曾经调试过一个加密模块,发现每次加密操作的时间都不一样。后来一查,是因为代码里根据密钥的某个比特位做了条件分支。攻击者只要测量几百次加密时间,就能还原出完整的密钥。嗯,从那以后我写密码学代码,都会刻意检查有没有非恒定时间的操作。

2.5 密钥销毁:善始善终

密钥销毁是生命周期中最后一步,也是最容易被忽略的一步。很多人觉得「设备不用了,密钥自然就没了」。其实不然。

你想想看,如果设备被回收、转卖或者丢弃,密钥还留在 Flash 里,那后续的持有者就能轻易读取。这在金融支付、身份认证等场景下是致命的。

密钥销毁的几个要点:

  • 物理销毁:最彻底的方式,但成本高
  • 覆写销毁:多次写入随机数据(至少 3 次,参考 NIST 标准)
  • 安全擦除:利用芯片提供的安全擦除指令(如 Flash 的批量擦除)
  • 不可逆:销毁后必须无法恢复
// 安全的密钥销毁函数
void secure_key_erase(uint8_t *key_buffer, size_t len) {
    volatile uint8_t *ptr = key_buffer;
    
    // 第一步:写入全 0
    for (size_t i = 0; i < len; i++) ptr[i] = 0x00;
    
    // 第二步:写入全 1
    for (size_t i = 0; i < len; i++) ptr[i] = 0xFF;
    
    // 第三步:写入随机数据
    for (size_t i = 0; i < len; i++) ptr[i] = (uint8_t)rand();
    
    // 第四步:再次写入全 0
    for (size_t i = 0; i < len; i++) ptr[i] = 0x00;
    
    // 防止编译器优化掉这些写入操作
    __asm volatile("" : : "r"(ptr) : "memory");
}

⚠️ 注意:对于 NAND Flash,简单的覆写可能无法彻底擦除数据。因为 Flash 的磨损均衡机制会把数据映射到不同物理块。我建议使用芯片厂商提供的安全擦除 API,或者直接销毁整个存储芯片。

2.6 全生命周期模型总结

好了,咱们把密钥从生到死的五个阶段都过了一遍。我画了一张图,把这五个阶段串起来:

密钥生命周期管理模型 生成 Generation 分发 Distribution 存储 Storage 使用 Usage 销毁 Destruction 每个阶段的关键安全要求 高熵源 不可预测 加密传输 身份认证 硬件隔离 防物理提取 最小权限 防侧信道 彻底擦除 不可恢复 销毁后不可再进入生命周期

这张图把五个阶段串成了一个闭环。注意看,销毁之后有一条虚线箭头指向生成——但这其实是个警示:密钥一旦销毁,就不能再被使用。如果需要新密钥,必须重新走一遍完整的生命周期。

我在实际项目中总结了一个经验:密钥生命周期管理,说白了就是「信任链」的管理。从生成时的信任根(Root of Trust),到分发时的信任传递,再到存储和使用的信任维持,最后到销毁时的信任终结。任何一个环节断裂,整个安全体系就崩塌了。

核心要点回顾:

  • 生成:用硬件 TRNG,别用软件伪随机
  • 分发:加密通道 + 身份认证,别明文传输
  • 存储:硬件隔离(HSM/SE/PUF),别放 Flash 明文
  • 使用:常数时间实现,别留侧信道漏洞
  • 销毁:多次覆写 + 物理销毁,别留残余数据

嗯,密钥生命周期管理就聊到这儿。记住一句话:密钥安全不是某一个环节的事,而是整个链条的事。链条的强度,取决于最弱的那一环。

可可精品资料库