4、密码学基础(下):密钥对生成(RSA/ECC)、密钥存储安全(HSM、TEE)、随机数的重要性

好,咱们接着聊。上一节我们把哈希、对称加密、非对称加密这些概念理了一遍。这一节,咱们要碰点真家伙了——密钥对到底是怎么变出来的?生成完了放哪儿才安全?以及,那个容易被忽略的“随机数”,为什么我总说它是整个PKI的命根子。

说实话,刚入行那会儿,我觉得密钥生成不就是调个OpenSSL命令嘛,几秒钟搞定。直到有一次,我在一个嵌入式设备项目里,发现生成的RSA密钥对居然有规律可循……嗯,从那以后,我对“生成”这两个字就再也不敢马虎了。

4.1 密钥对生成:RSA 与 ECC 的“内功心法”

密钥对生成,说白了就是找两个数学上“互逆”的钥匙。一把公开,一把私藏。但RSA和ECC找钥匙的方法完全不同。

4.1.1 RSA:大整数分解的“老黄牛”

RSA的生成逻辑,我习惯用一句话记:找两个大素数,乘起来,然后算个逆元。具体步骤是这样的:

  1. 选两个大素数 p 和 q。注意,是“大”素数,现在至少2048位,也就是十进制600多位。随机挑,但得通过素性检验。
  2. 计算 n = p × q。n就是公钥的一部分,长度就是密钥长度。
  3. 计算欧拉函数 φ(n) = (p-1)(q-1)。这个值必须保密。
  4. 选一个公钥指数 e。常用65537,为什么?因为它是一个费马素数,二进制是10000000000000001,只有两个1,算得快。
  5. 计算私钥 d,满足 e × d ≡ 1 (mod φ(n))。d就是私钥的核心。

我在项目中见过有人为了省事,直接用OpenSSL默认参数生成1024位RSA。我当时的反应是:“赶紧换,这玩意儿现在用FPGA暴力分解,几天就破了。” 现在行业底线是2048位,我建议直接上4096位,虽然慢一点,但安心。

RSA 密钥强度对照表(2025年视角)

密钥长度安全等级我的建议
1024位已不安全立即淘汰,不要再用
2048位当前可用可接受,但建议逐步迁移
4096位长期安全我个人的首选,性能损失可接受

4.1.2 ECC:椭圆曲线的“短小精悍”

ECC就不一样了。它不靠大数分解,而是靠椭圆曲线上的“点乘”运算。你想想看,在一条曲线上,给定一个点G,你算 k×G 很容易,但给你 G 和 k×G,让你反推 k,难如登天。这就是椭圆曲线离散对数问题。

ECC生成密钥对的步骤简单得多:

  1. 选一条曲线 和曲线上的基点G。比如NIST P-256、secp256r1、或者国密SM2的曲线。
  2. 随机生成一个私钥 k,就是一个大整数。
  3. 计算公钥 Q = k × G,就是点乘运算。

你看,ECC的私钥就是一个随机数,公钥就是一个点。比RSA那一堆 p、q、n、φ、d 清爽多了。而且,256位的ECC,安全强度相当于3072位的RSA。我做过一个IoT项目,设备内存只有几百KB,RSA 2048位的密钥对生成要卡好几秒,换成ECC P-256,瞬间完成。这就是差距。

我的选择建议: 新项目,尤其是资源受限的设备,优先选ECC。如果是兼容老系统,或者需要做RSA签名验签的互操作,那就用RSA 4096位。别混着用,保持统一。

4.2 密钥存储安全:HSM 与 TEE 的“保险柜”

密钥生成出来,放哪儿?你总不能明文写在配置文件里吧?我曾经在一个客户现场,发现他们把私钥直接硬编码在C代码里……我当时就问他:“你这跟把银行卡密码贴在ATM机上有什么区别?”

密钥存储,核心就三个字:防泄露。方案分三六九等,我按安全等级排个序:

4.2.1 HSM:硬件安全模块,银行级的“金库”

HSM是专用硬件,专门干一件事:在硬件内部生成、存储、使用私钥,私钥永远不离开芯片。你调用HSM的API说“给我签个名”,它把数据拿进去,签完把结果吐出来,私钥你连看都看不到。

我参与过一个金融CA项目,根CA的私钥就放在一个HSM里。那个HSM有多夸张?

  • 有物理防篡改外壳,一拆就自毁。
  • 有密钥备份机制,但备份也是加密后分片存储。
  • 操作需要智能卡+密码双因子认证。

说白了,你想偷那个私钥,得先过保安、过指纹锁、过防爆门,最后还得知道HSM的管理员密码。成本极高。

4.2.2 TEE:可信执行环境,手机里的“安全隔间”

TEE是CPU内部的一个安全区域。你的手机、平板、智能电视里基本都有。它和主操作系统(REE)隔离,运行在独立的“安全世界”里。

我做过一个手机端数字身份项目,用户的签名私钥就存在TEE里。App想签名,得通过TEE的API发起请求,TEE在内部用私钥算完,把签名结果返回。就算手机被root了,攻击者也拿不到TEE里的私钥——因为TEE的内存和存储,REE根本访问不了。

注意: TEE虽然安全,但它的安全强度取决于具体实现。有些低端手机的TEE实现有漏洞,我曾经见过一个案例,攻击者通过侧信道攻击从TEE里提取出了密钥。所以,TEE适合做“次一级”的密钥存储,根密钥还是建议用HSM。

4.2.3 软件存储:最后的“底线”

如果实在没有HSM和TEE,只能用软件存,那也得有底线:

  • 加密存储: 私钥用设备唯一密钥加密后存文件系统。
  • 白盒密码: 把密钥和算法混淆在一起,增加逆向难度。
  • Android KeyStore / iOS Keychain: 利用系统级安全存储,虽然不如TEE,但比明文强百倍。

但我得说一句:软件存储只是“延缓”攻击,不是“阻止”攻击。有条件的,还是上硬件。

4.3 随机数的重要性:PKI的“地基”

聊完密钥生成和存储,我得专门说说随机数。你想想看,RSA的p和q怎么来的?ECC的私钥k怎么来的?都是随机数。如果随机数不够随机,整个PKI就是纸糊的。

我讲一个真实案例。2012年,有研究者发现某些嵌入式设备生成的RSA公钥,居然有大量重复的n值。一查原因,是设备里的随机数生成器坏了,每次开机都返回相同的“随机数”。结果就是,所有设备的私钥都一样。你想想,这有多可怕?

4.3.1 真随机 vs 伪随机

类型来源特点典型例子
真随机数(TRNG)物理噪声源不可预测,但速度慢芯片热噪声、放射性衰变
伪随机数(PRNG)算法+种子可复现,速度快/dev/urandom、OpenSSL的RAND_bytes

在PKI里,我们通常用PRNG,但种子必须来自TRNG。说白了,就是拿一小段真随机数,去“喂养”一个伪随机数生成器,让它源源不断地产出高质量的随机数。

4.3.2 随机数的“三大纪律”

我总结过三条,每次做安全评审都会拿出来对照:

  1. 不可预测性: 攻击者即使知道之前的随机数,也无法推断下一个。
  2. 均匀分布: 0和1出现的概率应该各占50%,不能有偏。
  3. 无周期性: 不能出现重复的模式。

我曾经在评审一个物联网平台时,发现他们用的随机数库是标准C库的rand()。我当时就指出:“这个库的周期只有2^31,而且种子是时间戳,攻击者只要知道设备上线时间,就能预测所有密钥。” 后来他们换成了基于硬件TRNG的随机数方案。

避坑指南: 永远不要用 rand()、srand(time(NULL)) 生成密钥。在Linux上,用 /dev/urandom 或 getrandom()。在嵌入式设备上,优先使用芯片自带的硬件随机数生成器(HRNG)。

4.4 本章知识体系:一张图看懂

下面这张图,我把密钥对生成、存储安全、随机数三者的关系画了出来。你一看就明白:随机数是源头,密钥生成是过程,安全存储是归宿。

密钥对生成与存储安全知识体系 密钥对生成与存储安全知识体系 随机数(TRNG/PRNG) PKI 的“地基” 密钥对生成 RSA(大整数分解) | ECC(椭圆曲线离散对数) 私钥 = 随机数 | 公钥 = 从私钥推导 密钥存储安全 HSM(硬件安全模块) TEE(可信执行环境) 软件加密存储 核心原则:私钥永不离开安全边界 随机数质量 → 密钥强度 → 存储安全,环环相扣

你看,整个链条从随机数开始,到密钥生成,再到安全存储,任何一个环节出问题,整个PKI体系就垮了。我这些年做安全评审,发现90%的问题都出在随机数质量或密钥存储上。生成算法本身反而很少出错——因为大家都用标准库。

我的个人习惯: 每次项目启动,我都会先问三个问题:

  • 随机数从哪里来?有没有硬件熵源?
  • 密钥在哪儿生成?HSM、TEE还是软件?
  • 私钥存哪儿?怎么防泄露?

这三个问题问完,项目的安全基线基本就定了。

好了,这一节的内容就到这儿。密钥对生成和存储,是设备PKI里最“硬核”的部分之一。理解了这些,后面讲证书签发、设备注册,你就知道为什么每一步都要这么“折腾”了。