第4章 密钥存储:从文件到硬件,你选对了吗?
密钥存储这件事,我见过太多项目栽跟头了。有人直接把私钥写在配置文件里,有人存数据库但不加密,还有人把HSM当摆设。其实选对存储方式,比你想象中更重要。
这一章我们聊聊常见的密钥存储手段——文件、数据库、HSM、以及各种容器格式。你可能会问:不就是存个密钥吗,至于这么讲究?嗯,我们一个个看。
文件存储:最方便,也最危险
说白了一句话:把密钥当普通文件存。开发阶段图省事,很多人这么干。但我建议你至少做到两点:
- 密钥文件权限必须严格(Linux下
chmod 600) - 文件内容必须加密——明文存私钥,跟把密码贴电脑上没区别
我在项目中遇到过一个小团队,他们把SM2私钥直接写进 config.json,还上传到Git仓库。结果呢?被扫描工具发现,当天就被安全团队要求重做整个密钥体系。避坑指南:明文密钥永远不要进版本控制。
数据库存储:集中管理,但要看住钥匙
用数据库统一管理密钥,适合多应用共享的场景。常见的做法是建一张密钥表,存ID、算法、密钥密文、有效期等。
但有个关键点:密钥本身的加密密钥(KEK)放哪? 你想想看,如果KEK也存同一个数据库,那加密就没意义了。我自己的习惯是:KEK来源于外部——环境变量、HSM或者专门的密钥管理服务。
| 存储方式 | 优点 | 缺点 |
|---|---|---|
| 明文文件 | 简单直接 | 易泄露、难轮换 |
| 加密文件(如PKCS#8) | 标准、可传输 | 需要额外保护口令 |
| 数据库存储 | 集中管理、审计方便 | KEK保护是关键 |
| HSM存储 | 硬件隔离、防物理攻击 | 成本高、性能有损耗 |
HSM存储:银行级的安全选择
HSM全称硬件安全模块,说白了就是一个专门干「密钥运算」的黑盒子。密钥生成、签名、加密全在硬件里完成,私钥永远不会离开设备。
曾经有个金融客户问我:HSM这么贵,值吗?我反问他:「你的私钥值多少钱?」如果泄露可能导致上千万损失,那HSM就是保险。
国密场景下,目前主流的HSM都支持SM2/SM3/SM4。对接时要注意两点:
- HSM厂商的PKCS#11接口实现是否完整
- 密钥备份方案——HSM坏了,你的密钥能恢复吗?
密钥容器格式:PKCS#8、PEM、DER
这几个格式你可能经常碰见。我帮你理清区别:
- PKCS#8:标准私钥封装格式,支持加密(用口令保护)。国密SM2私钥建议用这个格式导出。
- PEM:文本格式,Base64编码,带
-----BEGIN ...-----头尾。其实就是把DER用Base64包裹一层。 - DER:二进制格式,文件小,但不可读。
实际项目中,我通常用PKCS#8加密存储私钥,扩散给其他服务时用PEM格式传输。举个例子:
# 导出SM2私钥为加密PKCS#8(PEM格式)
gmssl sm2 -ec_paramgen_curve:sm2p256v1 -genkey -out sm2.key.pem
gmssl pkcs8 -topk8 -in sm2.key.pem -out sm2.enc.pem -passout pass:yourpass
# 查看私钥信息
gmssl pkcs8 -in sm2.enc.pem -passin pass:yourpass -info
提示: 如果你用OpenSSL 3.x,注意国密曲线名称是 SM2 而不是 sm2p256v1。不同版本差异很大,建议先 openssl ecparam -list_curves 确认支持情况。
本地安全存储方案:实战中的选择
本地安全存储,核心思路就是「把密钥藏好」。根据平台不同,方案也不同:
- Linux:使用密钥环(keyutils)、Trousers或直接依赖文件权限 + dm-crypt
- Windows:DPAPI(Data Protection API)加密密钥后存注册表或文件
- Android/iOS:使用KeyStore/Keychain,由TEE保护
我曾经被一个嵌入式项目问住:没有操作系统、没有TPM,怎么存SM2私钥?最后方案是:把密钥拆成两份(门限签名?来不及改架构了),一份固化在Boot ROM,一份存外部加密Flash,上电后合成。
警告: 不要自己发明密钥衍生算法!使用标准KDF(如PBKDF2、scrypt)从口令导出加密密钥。我们见过有人自己写循环取模,结果密钥空间只有2^24,暴力破解几分钟就出来了。
好了,这一章的知识点就这些。下面这张图可以帮你快速回忆几种存储方式的关系:
总结一下:没有银弹。你的场景、预算、合规要求决定了选择。但有一条底线——绝不要明文存私钥,无论用哪种方式。