Windows 下构建 liboqs-java教程(超详细) ⚠️ 重要声明本文为原创内容因被抄袭我不得不在 CSDN 上重新发布。 原文链接点击这里访问原文‍ 我是原文作者转载时请务必标明出处Windows 下构建 liboqs-java实现PQC算法的调用liboqs-java并不是一个纯 Java 库它底层依赖的是由 C 语言实现的后量子密码学库liboqs。也就是说虽然我们最终是在 Java / Spring Boot 项目中调用 PQC 算法但真正执行算法逻辑的是 native 层。Java 代码通过 JNI 调用oqs-jni.dll再由该动态库链接并调用底层的liboqs。一、本文目标本文将完整演示如何在 Windows 环境下构建并使用liboqs-java主要包括以下内容在 Windows 上编译liboqs构建可用的liboqs-java.jar运行官方示例验证构建结果在 Spring Boot 项目中引入该 JAR通过 Java 代码调用 ML-KEM 等后量子密码算法二、环境与工具本文使用的环境如下Windows 10 / Windows 11 MinGW-w64 CMake JDK Maven Git建议使用较新的 JDK 版本例如 JDK 17 或 JDK 21。本文示例以JDK 21为例。三、先理解 liboqs 与 liboqs-java 的关系在正式构建之前需要先理解几个组件之间的关系。Spring Boot / Java 业务代码 | | 调用 Java API v liboqs-java.jar | | JNI 调用 v oqs-jni.dll | | 链接 v liboqs.a / liboqs | | 实际执行算法 v ML-KEM、ML-DSA 等 PQC 算法可以简单理解为组件作用liboqsC 语言实现的后量子密码学算法库liboqs-java对liboqs的 Java 封装oqs-jni.dllJava 与 native 层之间的 JNI 桥接库liboqs-java.jarJava / Spring Boot 项目最终要引入的 JAR 包因此正确的构建顺序是先构建 liboqs 再构建 liboqs-java 最后在 Java / Spring Boot 项目中引用生成的 JAR注意如果跳过liboqs的构建直接构建liboqs-java通常会遇到找不到oqs.h、找不到liboqs.a等问题。四、推荐项目目录结构由于需要从 GitHub 获取liboqs-java和liboqs两个项目源码建议将目录结构整理为如下形式D:\workspace\liboqs-java-main ├── pom.xml ├── README.md ├── examples │ ├── KEMExample.java │ ├── SigExample.java │ └── RandExample.java ├── src ├── liboqs │ ├── CMakeLists.txt │ ├── src │ └── build │ ├── include │ │ └── oqs │ │ └── oqs.h │ └── lib │ └── liboqs.a └── target └── liboqs-java.jar如下图所示其中最关键的是以下几个文件liboqs\build\include\oqs\oqs.h liboqs\build\lib\liboqs.a target\liboqs-java.jar只要这些文件都成功生成说明主构建流程基本已经走通。五、准备构建工具需要提前安装以下工具工具作用MinGW-w64提供gcc、g用于编译 C 代码和 JNI 代码CMake生成并驱动liboqs构建JDK编译 Java 代码并提供 JNI 头文件Maven构建liboqs-java并打包 JARGit拉取源码非必需也可以手动下载 ZIP建议将所有工具都安装到纯英文路径下不要放在包含中文或空格的目录中。例如D:\c_tools\mingw64 D:\java\jdk-21 D:\javaTools\apache-maven-3.9.x D:\workspace建议native 构建工具对路径比较敏感中文路径、空格路径有时会导致一些较难排查的问题。为了减少环境问题建议统一使用英文路径。六、安装 MinGW-w64可以使用 MinGW-w64 官方推荐的发行版。下载入口如下https://www.mingw-w64.org/进入官网后找到Downloads再找到MinGW-W64-builds。点击后会跳转到 GitHub选择需要的版本下载即可下载完成后解压后续需要将mingw64\bin添加到环境变量中。安装完成后可以在终端中执行gcc-v测试是否安装成功能看到 GCC 的版本信息就说明 MinGW-w64 已经可以正常使用。同时确认以下文件存在D:\c_tools\mingw64\bin\gcc.exe D:\c_tools\mingw64\bin\g.exe D:\c_tools\mingw64\bin\mingw32-make.exe后续 CMake 会通过这些工具来编译liboqs和 JNI 代码。七、安装 CMake可以使用winget安装winget install Kitware.CMake也可以从 CMake 官网下载 Windows x64 Installerhttps://cmake.org/download/下载后直接运行安装程序即可。安装时建议勾选Add CMake to the system PATH for current user如下图所示安装完成后重新打开终端执行cmake--version如果能够正常输出版本信息说明 CMake 已经安装成功。八、安装 JDKJDK 可以选择 Eclipse Temurin 或 Oracle JDK。下载地址https://adoptium.net/ https://www.oracle.com/java/technologies/downloads/JDK 的安装教程较多本文不再展开。本文示例使用JDK 21假设安装路径为D:\java\jdk-21需要确认以下文件存在D:\java\jdk-21\bin\java.exe D:\java\jdk-21\bin\javac.exe D:\java\jdk-21\include\jni.h其中jni.h非常重要。注意构建liboqs-java时会编译 JNI 代码。如果安装的是 JRE 而不是 JDK就会缺少jni.h从而导致构建失败。九、安装 Maven从 Maven 官网下载 binary zip 包https://maven.apache.org/download.cgi下载后解压到任意英文路径例如D:\javaTools\apache-maven-3.9.x确认以下文件存在D:\javaTools\apache-maven-3.9.x\bin\mvn.cmd十、配置环境变量Windows 下构建 native 项目时环境变量是最容易出问题的一步。建议配置以下用户变量变量名示例值JAVA_HOMED:\java\jdk-21MAVEN_HOMED:\javaTools\apache-maven-3.9.xMinGW_HOMED:\c_tools\mingw64然后将以下目录加入PathD:\c_tools\mingw64\bin D:\java\jdk-21\bin D:\javaTools\apache-maven-3.9.x\bin重要配置完成后一定要关闭当前已经打开的 PowerShell、cmd 或 IDE 终端然后重新打开一个新的终端。已经打开的终端不会自动刷新新的环境变量。十一、检查构建环境重新打开 PowerShell依次执行gcc--version g--version cmake--version java-version javac-version mvn-version每一条命令都应该正常输出版本信息。如果某一条命令提示不是内部或外部命令或者is not recognized as an internal or external command说明对应工具没有正确加入Path。此时不要继续构建应先检查环境变量配置。十二、获取源码进入自己的工作目录cd D:\workspace克隆liboqs-javagit clone https://github.com/open-quantum-safe/liboqs-java.git liboqs-java-main进入项目目录cd liboqs-java-main再将liboqs克隆到当前项目内部目录名建议保持为liboqsgit clone https://github.com/open-quantum-safe/liboqs.git liboqs完成后检查目录是否正确Test-Path.\pom.xmlTest-Path.\liboqs\CMakeLists.txt如果两条命令都返回True说明源码位置没有放错。如果不使用 Git也可以直接从 GitHub 下载 ZIP。需要注意的是建议将解压后的目录重命名liboqs-java项目目录命名为liboqs-java-mainliboqs-main目录重命名为liboqs将liboqs放到liboqs-java-main目录下目录示意如下十三、构建 liboqs首先进入liboqs目录cd D:\workspace\liboqs-java-main\liboqs如果之前构建失败过建议先删除旧的build目录Remove-Item-Recurse-Force build-ErrorAction SilentlyContinue然后执行 CMake 配置命令cmake-GMinGW Makefiles-DCMAKE_C_COMPILERgcc -DCMAKE_ASM_COMPILERgcc -DBUILD_SHARED_LIBSOFF -S.-B build这里几个参数比较关键参数说明-G MinGW Makefiles使用 MinGW 构建方式-DCMAKE_C_COMPILERgcc指定 C 编译器-DCMAKE_ASM_COMPILERgcc指定汇编编译器避免 ASM 编译器找不到-DBUILD_SHARED_LIBSOFF构建静态库liboqs.a-S .指定源码目录为当前目录-B build指定构建目录为build如果配置成功最后会看到类似输出-- Configuring done -- Generating done -- Build files have been written to: .../liboqs/build接着开始编译cmake--build build-j4其中-j4表示使用 4 个线程并行构建。可以根据机器配置调整参数适用情况-j2内存较小或机器配置一般-j4常规推荐-j8CPU 核心较多、内存充足liboqs的构建时间可能会比较长请耐心等待。构建完成后如下图所示构建完成后检查产物Test-Path.\build\lib\liboqs.aTest-Path.\build\include\oqs\oqs.h如果两条命令都返回True说明liboqs已经构建完成。十四、构建 liboqs-java.jar回到liboqs-java项目根目录cd D:\workspace\liboqs-java-main执行 Maven 打包命令mvn package-Pwindows-Dmaven.test.skiptrue这里需要特别注意 PowerShell 下的写法。-Dmaven.test.skiptrue建议加上双引号否则 PowerShell 有时会把它解析错导致 Maven 报类似错误Unknown lifecycle phase .test.skiptrue如果一切正常最后会看到[INFO] BUILD SUCCESS检查 JAR 是否生成dir.\target\liboqs-java.jar也可以直接在target目录中看到构建好的liboqs-java.jar。进一步确认 JAR 中是否包含 JNI 动态库jar tf.\target\liboqs-java.jar|findstr oqs-jni正常情况下会看到oqs-jni.dll到这里target\liboqs-java.jar就是后续 Spring Boot 项目需要引入的 JAR 包。十五、运行官方 KEM 示例先编译示例代码javac-cptarget\liboqs-java.jar examples\KEMExample.java如果没有输出错误说明编译成功。然后运行示例java-cptarget\liboqs-java.jar;examples\KEMExample注意Windows 下 classpath 的分隔符是分号;这一点和 Linux / macOS 不同。Linux / macOS 中通常使用冒号:。如果运行成功输出中会看到类似内容Supported KEMs: ... Enabled KEMs: ... KEM Details: Name: ML-KEM-512 ... Shared secrets coincide? true重点关注最后这一行Shared secrets coincide? true这说明双方通过 KEM 算法协商出的共享密钥一致liboqs-java已经能够正常调用 native 层算法。也可以继续测试签名示例javac-cptarget\liboqs-java.jar examples\SigExample.java java-cptarget\liboqs-java.jar;examples\SigExample十六、在 Spring Boot 项目中引入 liboqs-java.jar构建完成后就可以把liboqs-java.jar放到自己的 Spring Boot 项目中使用。假设 Spring Boot 项目结构如下pqc-demo ├── lib │ └── liboqs-java.jar ├── pom.xml └── src └── main └── java将刚才生成的 JARD:\workspace\liboqs-java-main\target\liboqs-java.jar复制到 Spring Boot 项目的pqc-demo\lib\liboqs-java.jar16.1 方式一使用 system 依赖在 Spring Boot 项目的pom.xml中加入dependencygroupIdorg.openquantumsafe/groupIdartifactIdliboqs-java/artifactIdversion3.0/versionscopesystem/scopesystemPath${project.basedir}/lib/liboqs-java.jar/systemPath/dependency其中version可以根据实际构建的liboqs-java版本进行调整。最稳妥的方式是查看liboqs-java-main/pom.xml中的版本号。这种方式适合本地测试配置简单直接。不过需要注意system依赖并不是 Maven 推荐的长期方案。如果项目需要团队协作、CI/CD 构建或部署到其他环境更推荐使用下一种方式。16.2 方式二安装到本地 Maven 仓库进入liboqs-java.jar所在目录执行mvn install:install-file-Dfileliboqs-java.jar-DgroupIdorg.openquantumsafe-DartifactIdliboqs-java-Dversion3.0-Dpackagingjar安装完成后Spring Boot 项目中就可以按普通 Maven 依赖方式引入dependencygroupIdorg.openquantumsafe/groupIdartifactIdliboqs-java/artifactIdversion3.0/version/dependency如果是团队项目也可以将该 JAR 发布到 Nexus、Artifactory 或公司内部 Maven 仓库中。推荐本地临时测试可以使用system依赖正式项目更建议安装到 Maven 仓库或发布到私有 Maven 仓库。十七、在 Spring Boot 中调用 ML-KEM下面写一个简单的 Service用于演示如何在 Spring Boot 中调用 KEM 算法。示例算法使用ML-KEM-512Service 代码如下packagecom.example.pqcdemo.service;importorg.openquantumsafe.KeyEncapsulation;importorg.springframework.stereotype.Service;importjava.util.Arrays;ServicepublicclassPqcKemService{publicbooleantestMlKem512()throwsException{KeyEncapsulationclientnull;KeyEncapsulationservernull;try{clientnewKeyEncapsulation(ML-KEM-512);servernewKeyEncapsulation(ML-KEM-512);// 客户端生成密钥对并获取公钥byte[]publicKeyclient.generate_keypair();// 服务端使用客户端公钥封装共享密钥byte[]ciphertextserver.encap_secret(publicKey);byte[]serverSharedSecretserver.get_shared_secret();// 客户端使用密文解封装共享密钥byte[]clientSharedSecretclient.decap_secret(ciphertext);// 判断两端共享密钥是否一致returnArrays.equals(clientSharedSecret,serverSharedSecret);}finally{if(client!null){client.dispose_KEM();}if(server!null){server.dispose_KEM();}}}}再写一个 Controller 方便测试packagecom.example.pqcdemo.controller;importcom.example.pqcdemo.service.PqcKemService;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;RestControllerpublicclassPqcController{privatefinalPqcKemServicepqcKemService;publicPqcController(PqcKemServicepqcKemService){this.pqcKemServicepqcKemService;}GetMapping(/pqc/ml-kem-512/test)publicStringtestMlKem512()throwsException{booleanresultpqcKemService.testMlKem512();returnML-KEM-512 shared secret match: result;}}启动 Spring Boot 后访问http://localhost:8080/pqc/ml-kem-512/test如果返回ML-KEM-512 shared secret match: true说明 Spring Boot 已经成功调用liboqs-java中的 PQC 算法。十八、查看当前可用的 KEM 算法如果不确定当前构建出来的库启用了哪些 KEM 算法可以写一个接口打印出来。packagecom.example.pqcdemo.controller;importorg.openquantumsafe.KEMs;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.List;RestControllerpublicclassPqcAlgorithmController{GetMapping(/pqc/kems)publicListStringlistEnabledKems(){returnKEMs.get_enabled_KEMs();}}访问http://localhost:8080/pqc/kems即可看到当前 native 库中实际启用的 KEM 算法列表。需要区分两个概念名称含义Supported KEMs库认识哪些算法名称Enabled KEMs当前构建产物中真正启用了哪些算法实际项目中应该以Enabled KEMs为准。十九、Spring Boot 打包时需要注意的问题如果只是本地运行一般直接引入liboqs-java.jar就可以。但如果要将项目打成 Spring Boot 可执行 JAR需要注意依赖是否真的被打进最终包中。如果使用的是system依赖可以在spring-boot-maven-plugin中增加如下配置buildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationincludeSystemScopetrue/includeSystemScope/configuration/plugin/plugins/build不过更推荐的方式仍然是将 liboqs-java.jar 安装到本地 Maven 仓库 或者发布到公司内部 Maven 私服 然后按普通 Maven 依赖方式引入这样 Maven、IDE、CI/CD 和部署环境都会更容易处理。二十、常见问题记录20.1 gcc 找不到报错示例gcc is not recognized The C compiler identification is unknown通常是因为 MinGW 的bin目录没有加入Path。检查命令gcc--version如果不能正常输出版本信息需要确认下面路径是否已经加入环境变量D:\c_tools\mingw64\bin修改环境变量后需要重新打开终端。20.2 CMake 找不到 ASM 编译器报错示例No CMAKE_ASM_COMPILER could be found配置liboqs时加上-DCMAKE_ASM_COMPILERgcc完整命令如下cmake-GMinGW Makefiles-DCMAKE_C_COMPILERgcc -DCMAKE_ASM_COMPILERgcc -DBUILD_SHARED_LIBSOFF -S.-B build20.3 找不到 oqs/oqs.h报错示例fatal error: oqs/oqs.h: No such file or directory这通常说明liboqs没有构建成功或者liboqs-java没有找到正确的 include 目录。先检查Test-Path.\liboqs\build\include\oqs\oqs.h如果返回False需要先回到liboqs目录重新构建。20.4 找不到 liboqs.a检查文件是否存在Test-Path.\liboqs\build\lib\liboqs.a如果返回False说明liboqs构建没有完成。重新执行cd D:\workspace\liboqs-java-main\liboqs cmake--build build-j420.5 找不到 jni.h报错示例fatal error: jni.h: No such file or directory通常是因为JAVA_HOME指向了 JRE或者没有正确配置 JDK。检查命令Test-Path$env:JAVA_HOME\include\jni.h正常情况下应该返回True如果不是需要重新设置JAVA_HOME确保它指向 JDK 根目录而不是 JRE 目录。20.6 PowerShell 中 Maven 参数解析错误报错示例Unknown lifecycle phase .test.skiptrue在 PowerShell 中建议将 Maven 参数用双引号包起来mvn package-Pwindows-Dmaven.test.skiptrue20.7 Spring Boot 运行时报 native 库加载失败如果出现 native library 加载失败的问题先确认 JAR 中是否包含oqs-jni.dlljar tf liboqs-java.jar|findstr oqs-jni正常情况下应该能看到oqs-jni.dll如果 JAR 中没有该文件说明liboqs-java构建过程不完整需要重新构建。如果 JAR 中已经包含oqs-jni.dll但 Spring Boot 运行仍然失败可以先使用普通 Java main 方法运行官方KEMExample。这样可以判断问题到底是liboqs-java 本身构建失败还是Spring Boot 打包或运行时 classpath 配置问题二十一、小结整个流程看起来步骤较多但真正关键的地方主要有以下几点MinGW、CMake、JDK、Maven 必须都能在命令行中正常使用必须先构建liboqs构建liboqs-java时需要能够找到oqs.h和liboqs.a最终生成的liboqs-java.jar中需要包含oqs-jni.dllSpring Boot 引入时要确保 JAR 被正确加入运行时 classpath如果官方示例KEMExample能够成功运行并输出Shared secrets coincide? true就说明liboqs-java已经能够正常调用 native 层的 PQC 算法。后续在 Spring Boot 中调用 ML-KEM、ML-DSA 等后量子密码算法本质上就只是普通 Java API 调用的问题了。二十二、参考资料最新MinGW-w64 的下载与安装CMake 安装指南Open Quantum Safe - liboqsOpen Quantum Safe - liboqs-java