题目4 私钥存储安全:文件系统、数据库、密钥库

私钥一旦泄露,整个SM2体系就等于废了。我见过太多因为存储环节出问题的案例——权限没设好、备份文件没加密、数据库被拖库……说白了,存储安全是密钥生命周期里最容易被忽视,但后果最严重的环节。这一章咱们就聊聊几种常见的存储方式,以及该怎么巡检。

一句话记住: 私钥不是普通数据,它的存储必须和操作系统、数据库、应用程序隔离,最好做到「能用就行,不能看」。

文件系统存储

这是最常见也最容易出问题的方式。很多团队直接把私钥文件丢在项目目录下,权限是755甚至777。我记得有个项目,运维图省事,把SM2私钥放在/etc/ssl/private/,结果目录权限是drwxr-xr-x,任何人都能读文件。后来被安全扫描扫出来,紧急整改。

文件系统存储的核心风险有三个:

  • 权限失控: 私钥文件必须设置为400(仅属主可读)或600(属主可读写)。运行SM2程序的用户必须单独创建,不能复用nginx、mysql等高权限账号。
  • 明文落盘: 很多开发者直接把PEM格式的私钥字符串写死在配置里。这等于把钥匙挂在门上。至少要用openssl enc -aes-256-cbc加密后再存,运行时在内存中解密。
  • 备份泄露: 备份脚本经常把整个/etc或/opt目录打包,私钥跟着一起被丢到NAS或云存储。我曾经审计过一个客户,他们的备份文件权限是644,任何人拿到备份就能得到所有SM2私钥。
巡检要点:
  • 检查所有私钥文件的ls -l权限,确保≤600。
  • 检查私钥文件所在的上级目录权限,不能是777。
  • 检查备份脚本和备份存储位置,私钥不能出现在未加密的备份包中。

数据库存储

把私钥塞进数据库?说实话,我劝你千万别这么干。但现实中确实有人这么做——把私钥作为varchar(2048)字段存到MySQL里。你觉得安全?SQL注入、数据库备份泄露、慢查询日志写入……任何一处出问题,私钥就裸奔了。

如果一定要用数据库存储,必须满足以下条件:

  1. 加密存储: 不能存明文。使用数据库自带的AES_ENCRYPT()或应用层先加密再存。密钥管理另用一个独立系统。
  2. 访问隔离: 即使是DBA,也不能通过SELECT *直接看到私钥。可以通过数据库的列级加密、权限控制,或者使用视图只返回脱敏信息。
  3. 审计日志: 谁在什么时间访问了私钥列,必须有记录。我见过一个案例,开发用UPDATE语句批量改了私钥字段,结果生产环境全部瘫痪。
我曾经踩过的坑: 有个团队把SM2私钥存到MongoDB的文档里,字段名叫private_key,然后整个数据库没设任何访问密码就被暴露到公网。扫到后我直接指导他们销毁所有私钥,重新生成。存储方案必须和开发、运维讲清楚:数据库不是密钥保险箱。

密钥库(HSM / TPM / KeyStore)

这才是专业做法。硬件安全模块(HSM)、可信平台模块(TPM)、Java KeyStore、PKCS#11接口的软件令牌,这些才是SM2私钥该待的地方。为什么?因为私钥一旦生成,永远不能离开密钥库——签名运算在密钥库内部完成,外界只能拿到结果,拿不到私钥本身。

存储方案 安全等级 性能 成本 典型场景
文件系统(明文) 低 高 无 临时测试,不可用于生产
文件系统(加密) 中 高 低 小型业务,需配合内存解密
数据库(加密存储) 中 中 低 多应用共享密钥时考虑
软件KeyStore(PKCS#12/JKS) 中高 中 无 Java生态、微服务
HSM / TPM 极高 低(硬件加密) 高 金融、政务、关键基础设施

我个人偏好是:能用HSM就用HSM,哪怕买个便宜的云HSM也行。如果预算有限,至少用pkcs11-tool配合软令牌(比如SoftHSMv2),把私钥导入令牌后,应用代码通过PKCS#11接口调用签名,私钥永远不出令牌。我帮一个支付系统做过这样的改造,之后安全审计直接过了。

实践建议:
  • 如果使用Java KeyStore,请使用PKCS12格式而非JKS,密码强度至少16位以上。
  • HSM一定要开启双人控制(Dual Control)——管理员和操作员分开,私钥导出需要两人同时在场。
  • 定期做密钥轮换测试:能不能在不影响业务的情况下生成新私钥并废弃旧私钥?如果做不到,说明密钥库架构有问题。

存储安全巡检清单

巡检不光是看配置,还要动手验证。下面是我自己常用的检查步骤,你可以在巡检时照着做:

  1. 列出所有SM2私钥文件(找*.pem、*.key、keystore等),检查权限。
  2. 检查进程内存:用gdb -p 或procmem查看SM2签名服务进程的内存中是否有私钥明文(正常情况不应有)。
  3. 检查数据库表字段:看是否有存储私钥但没有加密的列(SELECT * FROM information_schema.columns)。
  4. 检查HSM/KeyStore的访问日志:是否有非授权尝试?是否有异常时间段的导出请求?
  5. 模拟备份恢复:从备份中能否轻松拿到私钥?如果能,说明备份方案不合格。
SM2私钥存储安全架构 SM2私钥存储 文件系统存储 数据库存储 密钥库(HSM/TPM) 权限不足(777) 明文落盘 备份泄露 SQL注入风险 日志记录明文 DBA可见 硬件隔离 签名不暴露密钥 双人控制 巡检目标:确保私钥不被文件系统、数据库、备份、日志、内存等任何介质泄露 推荐方案:产线环境必须使用HSM或同等安全等级的密钥库

最后再啰嗦一句:私钥存储不是「选一个就行」,而是要根据业务场景做风险权衡。别因为怕麻烦就选最简单的明文文件存储——等到被通报了再改,代价就大了。我每年都会在自己的系统上跑一遍巡检脚本,把存储安全这件事当成例行公事,而不是出事后补救的措施。