1. 国密改造概述:为什么要在 Spring Cloud 项目中引入国密算法?
很多朋友第一次接触国密改造时,第一反应都是:“我业务跑得好好的,为什么非要换加密算法?” 说实话,几年前我也是这么想的。直到我在一个金融类项目里亲历了合规检查——对方直接问:“你们的 HTTPS 证书用的是什么算法?签名验签用了哪套标准?” 当时我只用了国际算法,结果被要求限期整改,连着加了两周的班……嗯,从那以后我再也不敢轻视国密这事儿了。
1.1 到底什么是“国密算法”
国密算法,全称是国家商用密码算法,由国家密码管理局发布。目前项目中用得最多的主要是这几种:
| 算法 | 类型 | 常见用途 |
|---|---|---|
| SM2 | 椭圆曲线公钥密码 | 密钥交换、数字签名、证书签发 |
| SM3 | 杂凑算法(类似 SHA-256) | 完整性校验、HMAC |
| SM4 | 分组对称密码 | 数据加密、传输层加密(替代 AES) |
| SM9 | 标识密码(基于身份的密码) | 免证书的认证、密钥协商 |
说白了,国密算法和国际主流算法(RSA、ECDSA、SHA-256、AES)在安全强度上是同一档的,只是在数学结构、实现细节上有差异。我个人的习惯是:如果项目没有强合规要求,我会继续用国际算法;一旦客户明确提到“过等保”“过密评”,那就必须老老实实切国密。
1.2 政策驱动:为什么现在必须重视?
你可能会问:“不就是合规吗?不查我就不改呗。” 但现实是——政策已经在加速落地了。
- 《密码法》:2019 年颁布,2020 年实施,明确要求“关键信息基础设施”应当使用国密算法。你想想看,Spring Cloud 微服务跑在云上,算不算关键信息基础设施?在很多行业里,算。
- 等保 2.0 和密评:等保三级以上系统,必须通过密评(商用密码应用安全性评估)。密评的硬指标之一就是“优先采用国密算法”。
- 金融、政务、医疗行业:这些行业监管最严格。我在去年一个政务项目中,对方直接问:“你们的 Spring Cloud Gateway 能不能支持 SM2 证书做 HTTPS?服务间调能不能用 SM4 加密?” 做不到,项目就拿不到。
1.3 Spring Cloud 改造的核心痛点
为什么我要单独讲 Spring Cloud?因为微服务架构的国密改造比单体系统复杂得多。改一个服务不难,难的是整条链路:
- 网关层:Spring Cloud Gateway / Zuul 的 SSL 握手需要支持 SM2 证书。
- 服务间通信:Feign / RestTemplate 的 HTTP 调用,需要支持 SM4 传输加密或 SM2 签名。
- 注册中心与配置中心:Nacos / Eureka 的心跳数据、配置推送,是否加密?
- 认证鉴权:OAuth2 / JWT 的 签名,是否改用 SM2 或 SM3?
- 数据库连接:JDBC 驱动是否支持 SM4 透明加密?
这些环节如果分头改造,很容易出现“一个服务改好了,另一个服务证书不兼容”的互调问题。所以第一件事不是写代码,而是画一张整体的改造架构图。
我的建议: 先做“国密能力评估”。列出所有需要改的组件,标出优先级——网关和认证中心通常排第一,因为它们是流量入口。然后逐个引入 Bouncy Castle 或腾讯 Kona 等国密 Java 实现,用 SPI 机制替换掉 JDK 默认的 Provider。
1.4 一张图看懂改造逻辑
下面这张图概括了 Spring Cloud 国密改造的核心脉络。从政策驱动出发,到改造的目标系统,再到技术落地的三个关键步骤。我在项目中习惯把它贴在团队 Wiki 首页,让每个人都知道“我们在做什么”以及“为什么做”。
1.5 我的一点经验总结
啰嗦了这么多,最后说几句实在的。
第一,别怕改,但要分步走。 我见过最多的失败案例,就是想着“一步到位全部改”。结果单个服务改好,集成就出问题,最后回滚得不偿失。我的做法是:先改网关和认证中心,然后用灰度环境跑通一个业务链路,再分批推广到所有微服务。
第二,用好开源成果。 Bouncy Castle 已经支持全部国密算法,Spring Boot 2.x 配合 BCFIPS provider 可以直接签发 SM2 证书。腾讯开源的 Kona 国密套件也专为 Spring Cloud 做了适配。不用自己写加密库,减少风险。
小技巧: 在开发阶段,可以用自签的 SM2 证书(openssl 生成),导入信任库。线上再用合规的国密 SSL 证书。这样开发环境不需要买证书,也能提前暴露集成问题。
第三,测试比你想的重要。 我曾经在预发布环境发现,一个服务用国密客户端调用另一个服务时,TLS 握手失败了整整 3 秒——因为默认的 JCE 策略只支持 128 位密钥,而 SM4 用的是 128 位,虽然长度一样,但 Provider 顺序导致了一个不必要的协商步骤。排查这种问题需要你熟悉 Java Security 的 Provider 加载机制。我会在后面章节详细讲怎么配置。