第2章:Java开发环境搭建与国密SDK引入
这一章,咱们来把地基打牢。说实话,很多国密适配的问题,最后都出在环境上。
我见过不少同事,代码写得很漂亮,结果一跑就报ClassNotFoundException。折腾半天,原来JDK版本不对,或者依赖没拉下来。嗯,咱们没必要走这个弯路。
2.1 准备Java开发环境
先说JDK。国密SDK对JDK版本有要求吗?有,而且比较严格。
核心要点:目前主流国密SDK(比如Bouncy Castle、国内厂商的GM/T实现)要求JDK 8及以上,但JDK 8的某些小版本有兼容性问题。我个人习惯用JDK 11,稳定,踩的坑少。
2.1.1 下载与安装
去哪里下载?推荐三个渠道:
- Oracle JDK(商业环境注意授权)
- OpenJDK(我一般用这个,免费)
- Adoptium(原AdoptOpenJDK,社区维护,很稳定)
安装没什么好说的,下一步下一步。但配环境变量要小心——
# Windows 示例
JAVA_HOME=C:\Program Files\Java\jdk-11.0.18
PATH=%JAVA_HOME%\bin;%PATH%
# Linux / macOS 示例(写到 ~/.bashrc 或 ~/.zshrc)
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-11.0.18.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH
雷区:JAVA_HOME别指到JRE目录!指错了,Maven/Gradle会找不到编译器。我曾经有个项目,就是吃了这个亏,编译报错看了半天。
2.1.2 验证安装
配完了,跑一下验证命令:
java -version
javac -version
输出里要有版本号和架构信息。比如:
openjdk version "11.0.18" 2023-04-18
Java(TM) SE Runtime Environment (build 11.0.18+10-LTS)
Java HotSpot(TM) 64-Bit Server VM (build 11.0.18+10-LTS, mixed mode)
技巧:如果有多版本JDK,可以用 jenv(macOS/Linux)或切换环境变量来管理。别图省事直接改系统PATH,容易搞乱。
2.2 集成开发环境(IDE)配置
推荐IntelliJ IDEA。Eclipse也行,但我用IDEA顺手一些。
2.2.1 安装与首次启动
社区版(免费)就够用。如果想用企业版功能,可以申请开源许可试试。
启动后,关键配置:
- 设置项目SDK:File → Project Structure → Project → SDK,选你刚装好的JDK 11。
- 设置编码:File → Settings → Editor → File Encodings,全部改成UTF-8。国密算法经常涉及中文字符和二进制串,编码不一致会出诡异问题。
- 设置换行符:建议用LF(Unix风格),跨平台兼容性好。
特别注意:IDE默认编码如果跟项目不一致,SM3/SM4计算出来的摘要值会完全不同。这不是算法错了,是编码错了——我曾经排查了整整一天才发现是IDE的锅。
2.3 项目创建与依赖引入
咱们用Maven来管理依赖。Gradle也行,但我习惯Maven,社区资源多。
2.3.1 创建Maven项目
IDEA里:File → New → Project → Maven → 勾选"Create from archetype"(其实不用选,咱们手动配pom.xml就行)。
项目骨架大概长这样:
my-gm-demo/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ └── resources/
│ └── test/
│ └── java/
2.3.2 引入国密SDK
目前最通用的国密SDK是Bouncy Castle。它实现了SM2、SM3、SM4等国密标准。
在pom.xml里添加依赖:
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
</dependencies>
版本说明:bcprov是核心加密库,bcpkix是证书/X.509相关扩展。如果只做SM3/SM4计算,只加bcprov就够了。做数字证书验证时,两个都要加。
2.3.3 检查依赖是否拉取成功
Maven会自动下载。跑一下:
mvn dependency:tree
输出里会列出所有依赖树。你要看到org.bouncycastle:bcprov-jdk15on:1.70这项。
如果网络不好,Maven会卡在下载上。我建议设个阿里云镜像:
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>central</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
避坑:Bouncy Castle的jar包在国内网络有时不稳定。提前把仓库切到阿里云,能省很多时间。我一般项目启动前就先配好镜像,别等到报错了再回头改。
2.4 本章知识体系总览
下面这张图,把环境搭建的完整流程串了一下。跟着它,不容易漏步骤。
2.5 环境验证:写一个最小的国密调用
光配完了不行,咱们得跑起来。写一个最简单的SM3哈希计算,验证SDK能正常调用。
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
public class GmEnvCheck {
public static void main(String[] args) {
String input = "hello, 国密世界";
SM3Digest sm3 = new SM3Digest();
byte[] msg = input.getBytes();
sm3.update(msg, 0, msg.length);
byte[] hash = new byte[sm3.getDigestSize()];
sm3.doFinal(hash, 0);
System.out.println("SM3 Hash: " + Hex.toHexString(hash));
}
}
如果控制台打印出一串64位的十六进制字符串,那就是成功了。
踩坑实录:为什么不用String.getBytes()的默认编码?因为这玩意儿在不同操作系统上不一样。在Linux上是UTF-8,在Windows上是GBK。你想想看,同一个文件两边算出来的SM3结果不一样,查都查不出来。所以我推荐在getBytes里显式指定Charset.forName("UTF-8")。我曾经就在这上面吃过亏,修了三天才发现是编码不一致。
2.6 常见问题速查表
我把初学者常遇到的问题整理了一下。你可以收藏这个表,遇到问题先对号入座。
| 问题现象 | 可能原因 | 快速解决 |
|---|---|---|
| java.lang.NoClassDefFoundError | 依赖没下载完整/版本冲突 | 清理Maven缓存,重新刷新依赖 |
| SM3结果与在线工具不一致 | 编码不统一(UTF-8 vs GBK) | getBytes("UTF-8")显式指定 |
| javax.crypto包找不到 | JDK版本过低/使用了JRE而不是JDK | 检查JAVA_HOME指向JDK目录 |
| 代码提示找不到SM3Digest | Maven项目未正确引入Bouncy Castle | 检查pom.xml,确认artifactId和版本号 |
个人习惯:我每次建新项目,都会先跑这个SM3验证代码。几分钟的事,但能确保环境是干净的。后面再出问题,那肯定是逻辑错了,不是环境问题。
环境搭好了,依赖也拉下来了,SDK也能调了。咱们就具备了跑国密代码的基础。回到最开始说的,很多问题都出在环境上。打好地基,后面就顺了。