Windows x64 构建 liboqs-java教程

一、本文目标

本文将完整演示如何在 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 算法

可以简单理解为:

组件 作用

liboqs C 语言实现的后量子密码学算法库

liboqs-java 对 liboqs 的 Java 封装

oqs-jni.dll Java 与 native 层之间的 JNI 桥接库

liboqs-java.jar Java / 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

如下图所示:

image

其中最关键的是以下几个文件:

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 并打包 JAR

Git 拉取源码,非必需,也可以手动下载 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。

image

点击后会跳转到 GitHub:

image

选择需要的版本下载即可:

image

下载完成后解压,后续需要将 mingw64\bin 添加到环境变量中。

image

安装完成后,可以在终端中执行:

gcc -v

测试是否安装成功:

image

能看到 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 Installer:

https://cmake.org/download/

image

下载后直接运行安装程序即可。

安装时建议勾选:

Add CMake to the system PATH for current user

如下图所示:

image

安装完成后,重新打开终端,执行:

cmake --version

如果能够正常输出版本信息,说明 CMake 已经安装成功。

image

八、安装 JDK

JDK 可以选择 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

image

下载后解压到任意英文路径,例如:

D:\javaTools\apache-maven-3.9.x

image

确认以下文件存在:

D:\javaTools\apache-maven-3.9.x\bin\mvn.cmd

十、配置环境变量

Windows 下构建 native 项目时,环境变量是最容易出问题的一步。

建议配置以下用户变量:

变量名 示例值

JAVA_HOME D:\java\jdk-21

MAVEN_HOME D:\javaTools\apache-maven-3.9.x

MinGW_HOME D:\c_tools\mingw64

然后将以下目录加入 Path:

D:\c_tools\mingw64\bin

D:\java\jdk-21\bin

D:\javaTools\apache-maven-3.9.x\bin

image

重要:

配置完成后,一定要关闭当前已经打开的 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-java:

git clone https://github.com/open-quantum-safe/liboqs-java.git liboqs-java-main

进入项目目录:

cd liboqs-java-main

再将 liboqs 克隆到当前项目内部,目录名建议保持为 liboqs:

git 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-main

liboqs-main 目录重命名为 liboqs

将 liboqs 放到 liboqs-java-main 目录下

目录示意如下:

image

十三、构建 liboqs

首先进入 liboqs 目录:

cd D:\workspace\liboqs-java-main\liboqs

如果之前构建失败过,建议先删除旧的 build 目录:

Remove-Item -Recurse -Force build -ErrorAction SilentlyContinue

然后执行 CMake 配置命令:

cmake -G "MinGW Makefiles" -DCMAKE_C_COMPILER=gcc

-DCMAKE_ASM_COMPILER=gcc -DBUILD_SHARED_LIBS=OFF

-S . `

-B build

53a66dd270fc1c3679b9c81d2fffe0a9

这里几个参数比较关键:

参数 说明

-G "MinGW Makefiles" 使用 MinGW 构建方式

-DCMAKE_C_COMPILER=gcc 指定 C 编译器

-DCMAKE_ASM_COMPILER=gcc 指定汇编编译器,避免 ASM 编译器找不到

-DBUILD_SHARED_LIBS=OFF 构建静态库 liboqs.a

-S . 指定源码目录为当前目录

-B build 指定构建目录为 build

如果配置成功,最后会看到类似输出:

-- Configuring done

-- Generating done

-- Build files have been written to: .../liboqs/build

5009656d6ff22d5bc280e1fcceedb684

接着开始编译:

cmake --build build -j4

image

其中 -j4 表示使用 4 个线程并行构建。

可以根据机器配置调整:

参数 适用情况

-j2 内存较小或机器配置一般

-j4 常规推荐

-j8 CPU 核心较多、内存充足

liboqs 的构建时间可能会比较长,请耐心等待。

构建完成后如下图所示:

image

构建完成后检查产物:

Test-Path .\build\lib\liboqs.a

Test-Path .\build\include\oqs\oqs.h

image

如果两条命令都返回:

True

说明 liboqs 已经构建完成。

十四、构建 liboqs-java.jar

回到 liboqs-java 项目根目录:

cd D:\workspace\liboqs-java-main

执行 Maven 打包命令:

mvn package -Pwindows "-Dmaven.test.skip=true"

image

这里需要特别注意 PowerShell 下的写法。

-Dmaven.test.skip=true 建议加上双引号,否则 PowerShell 有时会把它解析错,导致 Maven 报类似错误:

Unknown lifecycle phase ".test.skip=true"

如果一切正常,最后会看到:

INFO BUILD SUCCESS

image

检查 JAR 是否生成:

dir .\target\liboqs-java.jar

也可以直接在 target 目录中看到构建好的 liboqs-java.jar。

image

进一步确认 JAR 中是否包含 JNI 动态库:

jar tf .\target\liboqs-java.jar | findstr oqs-jni

正常情况下会看到:

oqs-jni.dll

image

到这里,target\liboqs-java.jar 就是后续 Spring Boot 项目需要引入的 JAR 包。

十五、运行官方 KEM 示例

先编译示例代码:

javac -cp target\liboqs-java.jar examples\KEMExample.java

如果没有输出错误,说明编译成功。

然后运行示例:

java -cp "target\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

image

重点关注最后这一行:

Shared secrets coincide? true

这说明双方通过 KEM 算法协商出的共享密钥一致,liboqs-java 已经能够正常调用 native 层算法。

也可以继续测试签名示例:

javac -cp target\liboqs-java.jar examples\SigExample.java

java -cp "target\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

将刚才生成的 JAR:

D:\workspace\liboqs-java-main\target\liboqs-java.jar

复制到 Spring Boot 项目的:

pqc-demo\lib\liboqs-java.jar

16.1 方式一:使用 system 依赖

在 Spring Boot 项目的 pom.xml 中加入:
org.openquantumsafe liboqs-java 3.0 system ${project.basedir}/lib/liboqs-java.jar 其中 version 可以根据实际构建的 liboqs-java 版本进行调整。

最稳妥的方式是查看 liboqs-java-main/pom.xml 中的版本号。

这种方式适合本地测试,配置简单直接。

不过需要注意,system 依赖并不是 Maven 推荐的长期方案。如果项目需要团队协作、CI/CD 构建或部署到其他环境,更推荐使用下一种方式。

16.2 方式二:安装到本地 Maven 仓库

进入 liboqs-java.jar 所在目录,执行:

mvn install:install-file "-Dfile=liboqs-java.jar"

"-DgroupId=org.openquantumsafe" "-DartifactId=liboqs-java"

"-Dversion=3.0" `

"-Dpackaging=jar"

安装完成后,Spring Boot 项目中就可以按普通 Maven 依赖方式引入:
org.openquantumsafe liboqs-java 3.0 如果是团队项目,也可以将该 JAR 发布到 Nexus、Artifactory 或公司内部 Maven 仓库中。

推荐:

本地临时测试可以使用 system 依赖;

正式项目更建议安装到 Maven 仓库或发布到私有 Maven 仓库。

十七、在 Spring Boot 中调用 ML-KEM

下面写一个简单的 Service,用于演示如何在 Spring Boot 中调用 KEM 算法。

示例算法使用:

ML-KEM-512

Service 代码如下:

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 算法。

十八、查看当前可用的 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 List<String> listEnabledKems() {
    return KEMs.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 中增加如下配置:
org.springframework.boot spring-boot-maven-plugin true 不过更推荐的方式仍然是:

将 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_COMPILER=gcc

完整命令如下:

cmake -G "MinGW Makefiles" -DCMAKE_C_COMPILER=gcc

-DCMAKE_ASM_COMPILER=gcc -DBUILD_SHARED_LIBS=OFF

-S . `

-B build

20.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 -j4

20.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.skip=true"

在 PowerShell 中,建议将 Maven 参数用双引号包起来:

mvn package -Pwindows "-Dmaven.test.skip=true"

20.7 Spring Boot 运行时报 native 库加载失败

如果出现 native library 加载失败的问题,先确认 JAR 中是否包含 oqs-jni.dll:

jar 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.dll

Spring Boot 引入时要确保 JAR 被正确加入运行时 classpath

如果官方示例 KEMExample 能够成功运行,并输出:

Shared secrets coincide? true

相关推荐
一路向北North1 小时前
Spring Security OAuth2.0(20):完善环境配置
java·后端·spring
Java面试题总结1 小时前
IntelliJ IDEA 从卡顿到起飞,只用改这些。。。
java·ide·intellij-idea
兰令水1 小时前
hot100【acm版】【2026.7.11/12打卡-java版本】
java·开发语言·数据结构·算法·职场和发展
Misnearch2 小时前
nacos配置管理改造
java·spring cloud·nacos
XWalnut2 小时前
LeetCode刷题 day29
java·算法·leetcode
4154112 小时前
MyBatis-Plus + PostGIS 实战(1.1):Geometry 字段在 Swagger 中的优雅展示
java·mybatis·postgis
VIP_CQCRE2 小时前
用 Ace Data Cloud 快速接入 AI 视频生成:HappyHorse Videos API 实战指南
人工智能·python·api·ai视频生成·acedatacloud
极客先躯2 小时前
高级java每日一道面试题-2026年04月05日-实战篇[Docker]-如何排查容器 OOM 的问题?
java·运维·docker·容器·内存溢出·高级面试
带娃的IT创业者2 小时前
监控并非安全:当隐私成为技术的祭品
java·开发语言·安全·数据安全·监控·隐私保护·加密技术