liboqs-java offers a Java wrapper providing quantum-resistant cryptographic algorithms via liboqs.
The Open Quantum Safe (OQS) project has the goal of developing and prototyping quantum-resistant cryptography.
liboqs is an open source C library for quantum-resistant cryptographic algorithms. See more about liboqs at https://github.com/open-quantum-safe/liboqs, including a list of supported algorithms.
liboqs-java is an open source Java wrapper for the liboqs C library that provides:
- a common API for post-quantum key encapsulation mechanisms and digital signature schemes
- a collection of open source implementations of post-quantum cryptography algorithms
The OQS project also provides prototype integrations into application-level protocols to enable testing of quantum-resistant cryptography.
More information on OQS can be found on https://openquantumsafe.org.
This solution implements a Java wrapper for the C OQS library. It contains the following directories:
-
src/main/c/
: Native C JNI wrapper code that interfaces with liboqs. -
src/main/java/org/openquantumsafe/
: Java wrappers for the liboqs C library. -
src/test/java/org/openquantumsafe/
: Unit tests. -
examples/
: Key encapsulation, digital signatures and rand examples.
liboqs-java
defines four main classes: KeyEncapsulation
and Signature
, providing post-quantum key encapsulation and signature mechanisms, respectively, and KEMs
and Sigs
, containing only static member functions that provide information related to the available key encapsulation mechanisms or signature mechanism, respectively.
KeyEncapsulation
and/or Signature
must be instantiated with a string identifying one of mechanisms supported by liboqs; these can be enumerated using the KEMs.get_enabled_KEMs()
and Sigs.get_enabled_sigs()
methods.
Support for alternative RNGs is provided via the randombytes
functions.
The examples in the examples directory are self-explanatory and provide more details about the wrapper's API.
liboqs
and liboqs-java
are designed for prototyping and evaluating quantum-resistant cryptography. Security of proposed quantum-resistant algorithms may rapidly change as research advances, and may ultimately be completely insecure against either classical or quantum computers.
We believe that the NIST Post-Quantum Cryptography standardization project is currently the best avenue to identifying potentially quantum-resistant algorithms. liboqs
does not intend to "pick winners", and we strongly recommend that applications and protocols rely on the outcomes of the NIST standardization project when deploying post-quantum cryptography.
We acknowledge that some parties may want to begin deploying post-quantum cryptography prior to the conclusion of the NIST standardization project. We strongly recommend that any attempts to do make use of so-called hybrid cryptography, in which post-quantum public-key algorithms are used alongside traditional public key algorithms (like RSA or elliptic curves) so that the solution is at least no less secure than existing traditional cryptography.
liboqs-java
is provided "as is", without warranty of any kind. See LICENSE for the full disclaimer.
Builds have been tested on Linux (Ubuntu 18.04 LTS, 19.10, and 20.04) and macOS Mojave with OpenJDK 8, 9, 11.
To build the Java OQS wrapper you need a Java Development Kit (JDK), such as OpenJDK >= 8 and Apache Maven.
To build liboqs-java
first download or clone this java wrapper into a liboqs-java
folder, e.g.,
git clone -b master https://github.com/open-quantum-safe/liboqs-java.git
First, you must build the main
branch of liboqs according to the liboqs building instructions with shared library support enabled (add -DBUILD_SHARED_LIBS=ON
to the cmake
command), followed (optionally) by a sudo ninja install
to ensure that the compiled library is visible system-wide (by default it installs under /usr/local/include
and /usr/local/lib
on Linux/macOS).
git clone -b main https://github.com/open-quantum-safe/liboqs.git
cd liboqs
mkdir build && cd build
cmake -GNinja -DBUILD_SHARED_LIBS=ON ..
ninja
sudo ninja install
To build the liboqs-java
wrapper type for different operating systems add the -P <OS>
flag, where <OS> = {linux, macosx}
.
For instance, to build liboqs-java
for MacOS, type:
$ mvn package -P macosx -Dliboqs.include.dir="/usr/local/include" -Dliboqs.lib.dir="/usr/local/lib"
The above command will compile the C and Java files and also run the unit tests.
To build without running the default unit tests you can use the -Dmaven.test.skip=true
command line option as follows:
$ mvn package -P macosx -Dliboqs.include.dir="/usr/local/include" -Dliboqs.lib.dir="/usr/local/lib" -Dmaven.test.skip=true
The default profile for building is linux
, so when building on Linux the -P <OS>
command line option may be omitted.
You may also omit the -Dliboqs.include.dir
and -Dliboqs.lib.dir
options in case you installed liboqs in /usr/local
(true if you ran sudo ninja install
after building liboqs).
Both the above commands will create a target
directory with the build files, as well as a src/main/resources
directory that will contain the liboqs-jni.so
native library. Finally, a liboqs-java.jar
will be created inside the target
directory that will contain all the class files as well as the liboqs-jni.so
native library.
The examples include:
-
Key Encapsulation example:
-
Digital Signatures example:
-
Rand example: Print random bytes from
- NIST-KAT
- OpenSSL
- System (default)
To compile and run the KEM example, type:
$ javac -cp target/liboqs-java.jar examples/KEMExample.java
$ java -cp target/liboqs-java.jar:examples/ KEMExample
Supported KEMs:
BIKE-L1 BIKE-L3 Classic-McEliece-348864 Classic-McEliece-348864f Classic-McEliece-460896 Classic-McEliece-460896f Classic-McEliece-6688128 Classic-McEliece-6688128f Classic-McEliece-6960119 Classic-McEliece-6960119f Classic-McEliece-8192128 Classic-McEliece-8192128f HQC-128 HQC-192 HQC-256 Kyber512 Kyber768 Kyber1024 Kyber512-90s Kyber768-90s Kyber1024-90s NTRU-HPS-2048-509 NTRU-HPS-2048-677 NTRU-HPS-4096-821 NTRU-HRSS-701 ntrulpr653 ntrulpr761 ntrulpr857 sntrup653 sntrup761 sntrup857 LightSaber-KEM Saber-KEM FireSaber-KEM FrodoKEM-640-AES FrodoKEM-640-SHAKE FrodoKEM-976-AES FrodoKEM-976-SHAKE FrodoKEM-1344-AES FrodoKEM-1344-SHAKE SIDH-p434 SIDH-p503 SIDH-p610 SIDH-p751 SIDH-p434-compressed SIDH-p503-compressed SIDH-p610-compressed SIDH-p751-compressed SIKE-p434 SIKE-p503 SIKE-p610 SIKE-p751 SIKE-p434-compressed SIKE-p503-compressed SIKE-p610-compressed SIKE-p751-compressed
Enabled KEMs:
BIKE-L1 BIKE-L3 Classic-McEliece-348864 Classic-McEliece-348864f Classic-McEliece-460896 Classic-McEliece-460896f Classic-McEliece-6688128 Classic-McEliece-6688128f Classic-McEliece-6960119 Classic-McEliece-6960119f Classic-McEliece-8192128 Classic-McEliece-8192128f HQC-128 HQC-192 HQC-256 Kyber512 Kyber768 Kyber1024 Kyber512-90s Kyber768-90s Kyber1024-90s NTRU-HPS-2048-509 NTRU-HPS-2048-677 NTRU-HPS-4096-821 NTRU-HRSS-701 ntrulpr653 ntrulpr761 ntrulpr857 sntrup653 sntrup761 sntrup857 LightSaber-KEM Saber-KEM FireSaber-KEM FrodoKEM-640-AES FrodoKEM-640-SHAKE FrodoKEM-976-AES FrodoKEM-976-SHAKE FrodoKEM-1344-AES FrodoKEM-1344-SHAKE SIDH-p434 SIDH-p503 SIDH-p610 SIDH-p751 SIDH-p434-compressed SIDH-p503-compressed SIDH-p610-compressed SIDH-p751-compressed SIKE-p434 SIKE-p503 SIKE-p610 SIKE-p751 SIKE-p434-compressed SIKE-p503-compressed SIKE-p610-compressed SIKE-p751-compressed
KEM Details:
Name: Kyber512
Version: https://github.com/pq-crystals/kyber/commit/74cad307858b61e434490c75f812cb9b9ef7279b
Claimed NIST level: 1
Is IND-CCA: true
Length public key (bytes): 800
Length secret key (bytes): 1632
Length ciphertext (bytes): 768
Length shared secret (bytes): 32
Client public key:
C8 58 3B 21 02 A0 4D B0 ... 95 57 A7 E9 42 C0 45 C4
It took 1 millisecs to generate the key pair.
It took 0 millisecs to encapsulate the secret.
It took 0 millisecs to decapsulate the secret.
Client shared secret:
16 7F 9B 18 18 F9 F0 FE ... 70 F3 F6 4A C1 30 2C FF
Server shared secret:
16 7F 9B 18 18 F9 F0 FE ... 70 F3 F6 4A C1 30 2C FF
Shared secrets coincide? true
$ javac -cp target/liboqs-java.jar examples/SigExample.java
$ java -cp target/liboqs-java.jar:examples/ SigExample
Supported signatures:
Dilithium2 Dilithium3 Dilithium5 Dilithium2-AES Dilithium3-AES Dilithium5-AES Falcon-512 Falcon-1024 Rainbow-I-Classic Rainbow-I-Circumzenithal Rainbow-I-Compressed Rainbow-III-Classic Rainbow-III-Circumzenithal Rainbow-III-Compressed Rainbow-V-Classic Rainbow-V-Circumzenithal Rainbow-V-Compressed SPHINCS+-Haraka-128f-robust SPHINCS+-Haraka-128f-simple SPHINCS+-Haraka-128s-robust SPHINCS+-Haraka-128s-simple SPHINCS+-Haraka-192f-robust SPHINCS+-Haraka-192f-simple SPHINCS+-Haraka-192s-robust SPHINCS+-Haraka-192s-simple SPHINCS+-Haraka-256f-robust SPHINCS+-Haraka-256f-simple SPHINCS+-Haraka-256s-robust SPHINCS+-Haraka-256s-simple SPHINCS+-SHA256-128f-robust SPHINCS+-SHA256-128f-simple SPHINCS+-SHA256-128s-robust SPHINCS+-SHA256-128s-simple SPHINCS+-SHA256-192f-robust SPHINCS+-SHA256-192f-simple SPHINCS+-SHA256-192s-robust SPHINCS+-SHA256-192s-simple SPHINCS+-SHA256-256f-robust SPHINCS+-SHA256-256f-simple SPHINCS+-SHA256-256s-robust SPHINCS+-SHA256-256s-simple SPHINCS+-SHAKE256-128f-robust SPHINCS+-SHAKE256-128f-simple SPHINCS+-SHAKE256-128s-robust SPHINCS+-SHAKE256-128s-simple SPHINCS+-SHAKE256-192f-robust SPHINCS+-SHAKE256-192f-simple SPHINCS+-SHAKE256-192s-robust SPHINCS+-SHAKE256-192s-simple SPHINCS+-SHAKE256-256f-robust SPHINCS+-SHAKE256-256f-simple SPHINCS+-SHAKE256-256s-robust SPHINCS+-SHAKE256-256s-simple picnic_L1_FS picnic_L1_UR picnic_L1_full picnic_L3_FS picnic_L3_UR picnic_L3_full picnic_L5_FS picnic_L5_UR picnic_L5_full picnic3_L1 picnic3_L3 picnic3_L5
Enabled signatures:
Dilithium2 Dilithium3 Dilithium5 Dilithium2-AES Dilithium3-AES Dilithium5-AES Falcon-512 Falcon-1024 Rainbow-I-Classic Rainbow-I-Circumzenithal Rainbow-I-Compressed Rainbow-III-Classic Rainbow-III-Circumzenithal Rainbow-III-Compressed Rainbow-V-Classic Rainbow-V-Circumzenithal Rainbow-V-Compressed SPHINCS+-Haraka-128f-robust SPHINCS+-Haraka-128f-simple SPHINCS+-Haraka-128s-robust SPHINCS+-Haraka-128s-simple SPHINCS+-Haraka-192f-robust SPHINCS+-Haraka-192f-simple SPHINCS+-Haraka-192s-robust SPHINCS+-Haraka-192s-simple SPHINCS+-Haraka-256f-robust SPHINCS+-Haraka-256f-simple SPHINCS+-Haraka-256s-robust SPHINCS+-Haraka-256s-simple SPHINCS+-SHA256-128f-robust SPHINCS+-SHA256-128f-simple SPHINCS+-SHA256-128s-robust SPHINCS+-SHA256-128s-simple SPHINCS+-SHA256-192f-robust SPHINCS+-SHA256-192f-simple SPHINCS+-SHA256-192s-robust SPHINCS+-SHA256-192s-simple SPHINCS+-SHA256-256f-robust SPHINCS+-SHA256-256f-simple SPHINCS+-SHA256-256s-robust SPHINCS+-SHA256-256s-simple SPHINCS+-SHAKE256-128f-robust SPHINCS+-SHAKE256-128f-simple SPHINCS+-SHAKE256-128s-robust SPHINCS+-SHAKE256-128s-simple SPHINCS+-SHAKE256-192f-robust SPHINCS+-SHAKE256-192f-simple SPHINCS+-SHAKE256-192s-robust SPHINCS+-SHAKE256-192s-simple SPHINCS+-SHAKE256-256f-robust SPHINCS+-SHAKE256-256f-simple SPHINCS+-SHAKE256-256s-robust SPHINCS+-SHAKE256-256s-simple picnic_L1_FS picnic_L1_UR picnic_L1_full picnic_L3_FS picnic_L3_UR picnic_L3_full picnic_L5_FS picnic_L5_UR picnic_L5_full picnic3_L1 picnic3_L3 picnic3_L5
Signature Details:
Name: Dilithium2
Version: https://github.com/pq-crystals/dilithium/commit/d9c885d3f2e11c05529eeeb7d70d808c972b8409
Claimed NIST level: 2
Is IND-CCA: true
Length public key (bytes): 1312
Length secret key (bytes): 2528
Maximum length signature (bytes): 2420
Signer public key:
0E 47 54 30 E7 47 6D E6 ... 82 6E 4C C3 87 AA 6E FD
It took 0 millisecs to generate the key pair.
It took 1 millisecs to sign the message.
It took 0 millisecs to verify the signature.
Signature:
0C 2E 2D E2 81 C5 DC 10 ... 00 00 00 00 03 13 29 3B
Valid signature? true
$ javac -cp target/liboqs-java.jar examples/RandExample.java
$ java -cp target/liboqs-java.jar:examples/ RandExample
NIST-KAT: BF E7 5C 34 F9 1C 54 44 30 CD B1 61 5B FF 3D 92 31 17 38 BD 71 61 0C 22 CD F7 B8 23 D9 7C 27 F3
OpenSSL: 86 B6 46 9C 56 44 6B FB F8 B1 37 F0 86 4D 4D 74 0F FD 51 99 82 D6 89 02 40 B9 45 CF F9 3A 4D 70
System (default): 37 55 6F 4F 03 53 BB 71 E8 70 C2 3D DF 85 69 57 30 CE FA 11 EF 50 8A F5 AE 25 35 6F 91 CF EC 1D
-
Compiler errors
-
Cannot find
jni.h
:fatal error: jni.h: No such file or directory 2 | #include <jni.h> compilation terminated.
Try setting the
JAVA_HOME
environment variable. Then, tryls $JAVA_HOME
to check whether the directory is empty or has contents. If it is empty, setJAVA_HOME
to a correct JDK. -
Cannot find
oqs/oqs.h
fatal error: oqs.h: No such file or directory 5 | #include <oqs/oqs.h> compilation terminated.
Try providing the
-Dliboqs.include.dir
and-Dliboqs.lib.dir
command line options to maven as mentioned in the build instructions.
-
-
Runtime errors
-
If Java cannot find native library:
Exception in thread "main" java.lang.ExceptionInInitializerError at ... Caused by: java.lang.NullPointerException at org.openquantumsafe.Common.loadNativeLibrary(Common.java:51) at ...
try passing to the java library path the directory that contains the native library (e.g.,
java -Djava.library.path=src/main/resources/ -cp target/liboqs-java.jar:examples/ KEMExample
). -
If Java cannot find
liboqs
:Exception in thread "main" java.lang.UnsatisfiedLinkError: ./liboqs-java/build/liboqs-jni.so: liboqs.so.0: cannot open shared object file: No such file or directory
try setting the
LD_LIBRARY_PATH
environment variable with the installation location of theliboqs
shared library, i.e.,export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"
-
If a hotspot "irrecoverable stack overflow" error is shown:
An irrecoverable stack overflow has occurred. Please check if any of your loaded .so files has enabled executable stack (see man page execstack(8)) # # A fatal error has been detected by the Java Runtime Environment:
This could happen for algorithms that use a large stack size. Try adding the
-Xss
option to specify a different thread stack size. For example,-Xss5m
.
-
The Open Quantum Safe project is led by Douglas Stebila and Michele Mosca at the University of Waterloo.
Contributors to the liboqs-java wrapper include:
- Dimitris Mouris (@jimouris) (University of Delaware)
- Christian Paquin (@christianpaquin) (Microsoft Research)
liboqs-java
is licensed under the MIT License; see LICENSE for details.