3. 国密算法库选择:BC与GMSSL对比,Maven依赖配置
做国密改造,第一个跳出来的实际问题就是:算法库用哪个?
说实话,选错库会让你后面多走不少弯路。我自己在早期项目里踩过这个坑,所以这一章我们踏踏实实把BC和GMSSL这两个主流方案掰扯清楚。
嗯,咱们先理清一个概念:BC是Bouncy Castle的简称,全球通用的加密库;GMSSL则是国密标准算法的专用开源实现。两者都能做国密,但定位差别挺大。
3.1 两个库的核心差异
我习惯从几个关键维度来判断一个库靠不靠谱。你想想看,生产环境不比搞实验,库的稳定性、社区活跃度、合规性都得过一遍。
| 对比维度 | Bouncy Castle (BC) | GMSSL |
|---|---|---|
| 协议覆盖 | 全面(RSA、ECC、SM2/3/4) | 专注国密(SM2/SM3/SM4) |
| 合规认证 | 商用密码产品认证通过 | 密码行业标准遵循 |
| 社区活跃度 | 极高,持续维护 | 中等,更新节奏偏慢 |
| Spring集成 | 原生支持、文档丰富 | 需额外适配 |
| 性能表现 | 成熟优化,适合通用场景 | SM2签名/验签更快 |
3.2 为什么我更推荐BC?
说一个真实案例。有一次我接手一个Spring Cloud网关的改造项目,团队初选用了GMSSL。起初测试环境跑得挺顺,但一到线上就出了怪问题——RSA与SM2证书混用的TLS握手经常失败。
追查下来才发现,是GMSSL对JCE(Java Cryptography Extension)的默认Provider支持不够完整。当时我们得手动修改Bouncy Castle的Provider优先级,才能让RSA和SM2共存。说白了,GMSSL的API设计更“原生”,但和Spring Security的集成花了不少力气。
从那以后,我养成了一个习惯:非国密专有场景,优先上BC。它就像是瑞士军刀,什么都能干,而且Spring生态默认就认得它。
3.3 Maven依赖配置实战
直接上代码吧。我用的是Spring Boot 2.7.x + Spring Cloud 2021.0.x的版本组合,BC的Maven坐标如下:
<!-- Bouncy Castle 核心包 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<!-- Bouncy Castle PKIX/CMS 扩展 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<!-- 可选:TLS/DTLS 支持 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bctls-jdk15on</artifactId>
<version>1.70</version>
</dependency>
另外,
bcprov-jdk15on 是Provider核心,bcpkix 负责证书链处理。如果只做SM2/3/4签名验签,只引入bcprov即可。
如果是GMSSL的方案,配置是这样的:
<dependency>
<groupId>com.gmssl</groupId>
<artifactId>gmssl-xkcp</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.gmssl</groupId>
<artifactId>gmssl-jce</artifactId>
<version>1.1.0</version>
</dependency>
你看,GMSSL的坐标明显少——它本身不做多余的事情。但问题在于,当你需要在Gateway里同时支持国际TLS和国密TLS时,GMSSL的JCE Provider注册会覆盖Bouncy Castle的一些服务。嗯,要处理这个就得调整Provider的优先级顺序。
3.4 选型总结与避坑
我的建议很直接:如果你的国密改造涉及Spring Cloud Gateway、Feign、Ribbon这些组件,直接用BC绕开麻烦。如果项目是纯国密内部调用,且硬件加密机只支持GMSSL协议,那选GMSSL更加轻量。
- 我曾遇到过BC和GMSSL同时出现在classpath中,导致SM2验签返回false。排查半天,发现是Provider冲突——Security.addProvider()的顺序问题。解决方案是显式指定优先用哪个Provider。
- 还有一次,测试环境用JDK 8编译,生产环境是JDK 11。BC 1.70对JDK 11的签名算法有细微调整,不升级版本直接报错。所以版本对齐也很关键。
- 另外,别把bcprov和bcprov-ext混用。我记得有一次问题就是因为同时引入了两个Provider类,导致运行时抛出DuplicateProvider异常。
3.5 知识结构一览
我把这一章的核心逻辑画成了图。你看,从你的项目需求出发,最终要落在稳定的Maven依赖上。
从图上可以看得很清楚:向左走是BC路线,适合Spring Cloud全家桶;向右走是GMSSL路线,适合单一国密环境。别站中间纠结,那是给自己找麻烦。