Windows x64 构建 liboqs-java教程
indows 下构建 liboqs-java实现 PQC 算法的调用liboqs-java本身不是一个纯 Java 库它底层依赖liboqs这个 C 语言实现的后量子密码学库。也就是说我们最终虽然是在 Java / Spring Boot 项目里调用 PQC 算法但真正执行算法逻辑的是 native 层。本文连请标明出处本教程的目标如下在 Windows 上编译liboqs构建出可用的liboqs-java.jar运行官方示例验证构建是否成功在 Spring Boot 项目中引入该 JAR通过 Java 代码调用 ML-KEM 等后量子密码算法环境与工具Windows 10 / Windows 11 MinGW-w64 CMake JDK Maven1. 先理解 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 项目最终要引入的 JAR 包所以构建顺序一定是先构建liboqs再构建liboqs-java最后在 Java / Spring Boot 项目中引用生成的 JAR如果跳过第一步直接构建liboqs-java通常会遇到找不到oqs.h、找不到liboqs.a之类的问题。2. 构建时候的项目目录结构因为需要在github上获取liboqs与libqos-java两个项目源码构建时候建议最终的目录结构如下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只要这几个文件都生成了说明主流程基本走通了。3. 准备构建工具需要提前安装下面几个工具。工具用途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 构建工具对路径比较敏感中文路径或空格路径有时会带来一些很难排查的问题。4. 安装 MinGW-w64可以使用 WinLibs 提供的 MinGW-w64 发行版。下载地址https://winlibs.com/选择 Windows x86_64 版本即可。下载后解压到类似下面的目录D:\c_tools\mingw64确认下面几个文件存在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 代码。5. 安装 CMake可以使用 winget 安装winget install Kitware.CMake也可以从官网下载 Windows x64 Installerhttps://cmake.org/download/安装时建议勾选Add CMake to the system PATH安装完成后重新打开一个 PowerShell执行cmake --version能看到版本号就说明 CMake 已经可以正常使用。6. 安装 JDKJDK 可以使用 Eclipse Temurin 或 Oracle JDK。下载地址https://adoptium.net/ https://www.oracle.com/java/technologies/downloads/本文示例使用 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就会缺少这个头文件。7. 安装 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.cmd8. 配置环境变量这是 Windows 下最容易出问题的一步。建议配置以下用户变量变量名示例值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 终端然后重新打开一个新的终端。环境变量不会自动刷新到已经打开的终端窗口里。9. 检查构建环境重新打开 PowerShell依次执行下面几条命令gcc --version g --version cmake --version java -version javac -version mvn -version每一条都应该正常输出版本信息。如果某一条提示“不是内部或外部命令”先不要继续构建回去检查Path是否配置正确。10. 获取源码进入自己的工作目录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.xml Test-Path .\liboqs\CMakeLists.txt两条命令都返回True说明源码位置没有放错。如果不想使用 Git也可以直接从 GitHub 下载 ZIP。需要注意的是需要将解压出来的目录名称进行更换。liboqs-java对应的项目目录命名liboqs-java-mainliboqs对应的目录liboqs-main目录重命名为liboqs并放到liboqs-java-main目录下。11. 构建 liboqs先进入liboqs目录cd D:\workspace\liboqs-java-main\liboqs如果之前构建失败过建议先删除旧的build目录Remove-Item -Recurse -Force build -ErrorAction SilentlyContinue然后执行 CMake 配置cmake -G MinGW 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 个线程并行构建。如果机器配置较好可以改成-j8如果内存比较紧张可以改成-j2。构建完成后检查产物Test-Path .\build\lib\liboqs.a Test-Path .\build\include\oqs\oqs.h两条命令都返回True说明liboqs已经构建完成。12. 构建 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也可以确认 JAR 中是否包含 JNI 动态库jar tf .\target\liboqs-java.jar | findstr oqs-jni正常情况下会看到oqs-jni.dll这一步成功后target\liboqs-java.jar就是后面 Spring Boot 项目需要引入的包。13. 运行官方 KEM 示例先编译示例代码javac -cp target\liboqs-java.jar examples\KEMExample.java如果没有输出错误说明编译成功。然后运行java -cp target\liboqs-java.jar;examples\ KEMExampleWindows 下 classpath 的分隔符是分号;这一点和 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 -cp target\liboqs-java.jar examples\SigExample.java java -cp target\liboqs-java.jar;examples\ SigExample14. 在 Spring Boot 项目中引入 liboqs-java.jar构建完成后就可以把liboqs-java.jar放到自己的 Spring Boot 项目里使用。假设 Spring Boot 项目结构如下pqc-demo ├── lib │ └── liboqs-java.jar ├── pom.xml └── src └── main └── java把刚才生成的文件复制过去D:\workspace\liboqs-java-main\target\liboqs-java.jar放到pqc-demo\lib\liboqs-java.jar14.1 方式一直接使用 system 依赖在pom.xml中加入dependency groupIdorg.openquantumsafe/groupId artifactIdliboqs-java/artifactId version3.0/version scopesystem/scope systemPath${project.basedir}/lib/liboqs-java.jar/systemPath /dependency这里的version可以根据你实际构建的liboqs-java版本调整。最稳妥的方式是看一下liboqs-java-main/pom.xml中的版本号。这种方式适合本地测试简单直接。不过system依赖不是 Maven 推荐的长期方案。如果项目需要给团队其他人使用或者要放到 CI/CD 里构建更建议使用下面这种方式。14.2 方式二安装到本地 Maven 仓库在liboqs-java.jar所在目录执行mvn install:install-file -Dfileliboqs-java.jar -DgroupIdorg.openquantumsafe -DartifactIdliboqs-java -Dversion3.0 -Dpackagingjar安装完成后Spring Boot 项目里就可以正常写 Maven 依赖dependency groupIdorg.openquantumsafe/groupId artifactIdliboqs-java/artifactId version3.0/version /dependency如果是团队项目也可以把这个 JAR 发布到 Nexus、Artifactory 或公司内部 Maven 仓库中。15. Spring Boot 中调用 ML-KEM下面写一个简单的 Service用来演示如何在 Spring Boot 中调用 KEM 算法。示例使用ML-KEM-512。package com.example.pqcdemo.service; import org.openquantumsafe.KeyEncapsulation; import org.springframework.stereotype.Service; import java.util.Arrays; Service public class PqcKemService { public boolean testMlKem512() throws Exception { KeyEncapsulation client null; KeyEncapsulation server null; try { client new KeyEncapsulation(ML-KEM-512); server new KeyEncapsulation(ML-KEM-512); // 客户端生成公钥 byte[] publicKey client.generate_keypair(); // 服务端使用客户端公钥封装共享密钥 byte[] ciphertext server.encap_secret(publicKey); byte[] serverSharedSecret server.get_shared_secret(); // 客户端使用密文解封装共享密钥 byte[] clientSharedSecret client.decap_secret(ciphertext); // 判断两端共享密钥是否一致 return Arrays.equals(clientSharedSecret, serverSharedSecret); } finally { if (client ! null) { client.dispose_KEM(); } if (server ! null) { server.dispose_KEM(); } } } }再写一个 Controller 方便测试package com.example.pqcdemo.controller; import com.example.pqcdemo.service.PqcKemService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; RestController public class PqcController { private final PqcKemService pqcKemService; public PqcController(PqcKemService pqcKemService) { this.pqcKemService pqcKemService; } GetMapping(/pqc/ml-kem-512/test) public String testMlKem512() throws Exception { boolean result pqcKemService.testMlKem512(); return ML-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 算法。16. 查看当前可用的 KEM 算法如果不确定当前构建出来的库启用了哪些 KEM 算法可以写一个接口打印出来package com.example.pqcdemo.controller; import org.openquantumsafe.KEMs; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; RestController public class PqcAlgorithmController { GetMapping(/pqc/kems) public ListString listEnabledKems() { return KEMs.get_enabled_KEMs(); } }访问http://localhost:8080/pqc/kems可以看到当前 native 库中实际启用的 KEM 列表。需要注意Supported KEMs表示库认识哪些算法名称Enabled KEMs表示当前构建产物里真正启用了哪些算法实际项目中应该以Enabled KEMs为准。17. Spring Boot 打包时需要注意的问题如果你只是本地运行一般直接引入liboqs-java.jar就可以。但如果要打成 Spring Boot 可执行 JAR需要注意依赖是否真的被打进最终包里。如果使用system依赖可以在spring-boot-maven-plugin中增加配置build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration includeSystemScopetrue/includeSystemScope /configuration /plugin /plugins /build不过更推荐的方式还是把liboqs-java.jar安装到本地 Maven 仓库或者发布到私有 Maven 仓库然后按普通依赖方式引入。这样 Maven、IDE、CI/CD 都更容易处理。18. 常见问题记录18.1 gcc 找不到报错示例gcc is not recognized The C compiler identification is unknown一般是 MinGW 的bin目录没有加入Path。检查gcc --version如果不正常确认下面路径是否已经加入环境变量D:\c_tools\mingw64\bin修改后需要重新打开终端。18.2 CMake 找不到 ASM 编译器报错示例No CMAKE_ASM_COMPILER could be found配置liboqs时加上-DCMAKE_ASM_COMPILERgcc也就是完整命令使用cmake -G MinGW Makefiles -DCMAKE_C_COMPILERgcc -DCMAKE_ASM_COMPILERgcc -DBUILD_SHARED_LIBSOFF -S . -B build18.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目录重新构建。18.4 找不到 liboqs.a检查文件是否存在Test-Path .\liboqs\build\lib\liboqs.a如果不存在说明liboqs构建没有完成重新执行cd D:\workspace\liboqs-java-main\liboqs cmake --build build -j418.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 根目录。18.6 PowerShell 中 Maven 参数解析错误报错示例Unknown lifecycle phase .test.skiptrue把 Maven 参数用双引号包起来mvn package -Pwindows -Dmaven.test.skiptrue18.7 Spring Boot 运行时报 native 库相关错误如果出现类似 native library 加载失败的问题先确认jar tf liboqs-java.jar | findstr oqs-jni能看到oqs-jni.dll如果 JAR 中没有这个文件说明liboqs-java构建过程不完整需要重新构建。如果 JAR 中有oqs-jni.dll但 Spring Boot 运行仍然失败可以先在普通 Java main 方法中运行官方KEMExample确认是不是 Spring Boot 打包方式导致的问题。19. 一组完整构建命令如果工具和环境变量都已经配置好可以直接按下面流程执行。把路径换成自己的实际路径$PROJECT D:\workspace\liboqs-java-main cd $PROJECT\liboqs Remove-Item -Recurse -Force build -ErrorAction SilentlyContinue cmake -G MinGW Makefiles -DCMAKE_C_COMPILERgcc -DCMAKE_ASM_COMPILERgcc -DBUILD_SHARED_LIBSOFF -S . -B build cmake --build build -j4 cd $PROJECT mvn package -Pwindows -Dmaven.test.skiptrue javac -cp target\liboqs-java.jar examples\KEMExample.java java -cp target\liboqs-java.jar;examples\ KEMExample看到Shared secrets coincide? true就说明构建成功。21. 小结整个流程看起来步骤不少但真正关键的地方其实只有几个MinGW、CMake、JDK、Maven 必须都能在命令行正常使用liboqs要先构建成功liboqs-java构建时要能找到oqs.h和liboqs.a最终生成的liboqs-java.jar中要包含oqs-jni.dllSpring Boot 引入时要确保 JAR 被正确加入运行时 classpath如果官方示例KEMExample能跑通并且输出