第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 本章知识体系总览

下面这张图,把环境搭建的完整流程串了一下。跟着它,不容易漏步骤。

Java国密环境搭建流程结构图 Java国密开发环境搭建流程 1. 安装JDK 11+ 2. 配置JAVA_HOME 3. 验证 java -version 4. 安装/配置IntelliJ IDEA,设置项目SDK、编码UTF-8、换行符 5. 创建Maven项目,编写pom.xml,添加国密SDK依赖 bcprov-jdk15on (核心算法) bcpkix-jdk15on (证书扩展) 6. 执行 mvn dependency:tree 校验依赖 环境搭建完成后,即可在代码中调用SM2/SM3/SM4接口

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也能调了。咱们就具备了跑国密代码的基础。回到最开始说的,很多问题都出在环境上。打好地基,后面就顺了。