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:
DEFAULT BIKE1-L1-CPA BIKE1-L3-CPA BIKE1-L1-FO BIKE1-L3-FO 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
Kyber512 Kyber768 Kyber1024 Kyber512-90s Kyber768-90s Kyber1024-90s LEDAcryptKEM-LT12 LEDAcryptKEM-LT32
LEDAcryptKEM-LT52 NewHope-512-CCA NewHope-1024-CCA NTRU-HPS-2048-509 NTRU-HPS-2048-677 NTRU-HPS-4096-821
NTRU-HRSS-701 LightSaber-KEM Saber-KEM FireSaber-KEM BabyBear BabyBearEphem MamaBear MamaBearEphem PapaBear
PapaBearEphem 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:
DEFAULT BIKE1-L1-CPA BIKE1-L3-CPA BIKE1-L1-FO BIKE1-L3-FO 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
Kyber512 Kyber768 Kyber1024 Kyber512-90s Kyber768-90s Kyber1024-90s LEDAcryptKEM-LT12 LEDAcryptKEM-LT32
LEDAcryptKEM-LT52 NewHope-512-CCA NewHope-1024-CCA NTRU-HPS-2048-509 NTRU-HPS-2048-677 NTRU-HPS-4096-821
NTRU-HRSS-701 LightSaber-KEM Saber-KEM FireSaber-KEM BabyBear BabyBearEphem MamaBear MamaBearEphem PapaBear
PapaBearEphem 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: FrodoKEM-640-AES
Version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89
Claimed NIST level: 1
Is IND-CCA: true
Length public key (bytes): 9616
Length secret key (bytes): 19888
Length ciphertext (bytes): 9720
Length shared secret (bytes): 16
Client public key:
14 E7 26 B9 28 F7 F8 23 ... 16 C3 D0 62 1C B3 D1 EB
It took 1 millisecs to generate the key pair.
It took 2 millisecs to encapsulate the secret.
It took 1 millisecs to decapsulate the secret.
Client shared secret:
B0 8A C0 62 69 68 44 D3 52 6A F9 9E 5A 42 26 16
Server shared secret:
B0 8A C0 62 69 68 44 D3 52 6A F9 9E 5A 42 26 16
Shared secrets coincide? true
$ javac -cp target/liboqs-java.jar examples/SigExample.java
$ java -cp target/liboqs-java.jar:examples/ SigExample
Supported signatures:
DEFAULT DILITHIUM_2 DILITHIUM_3 DILITHIUM_4 Falcon-512 Falcon-1024 MQDSS-31-48 MQDSS-31-64 Rainbow-Ia-Classic
Rainbow-Ia-Cyclic Rainbow-Ia-Cyclic-Compressed Rainbow-IIIc-Classic Rainbow-IIIc-Cyclic
Rainbow-IIIc-Cyclic-Compressed Rainbow-Vc-Classic Rainbow-Vc-Cyclic Rainbow-Vc-Cyclic-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_L3_FS picnic_L3_UR picnic_L5_FS picnic_L5_UR picnic2_L1_FS picnic2_L3_FS picnic2_L5_FS
qTesla-p-I qTesla-p-III
Enabled signatures:
DEFAULT DILITHIUM_2 DILITHIUM_3 DILITHIUM_4 Falcon-512 Falcon-1024 MQDSS-31-48 MQDSS-31-64 Rainbow-Ia-Classic
Rainbow-Ia-Cyclic Rainbow-Ia-Cyclic-Compressed Rainbow-IIIc-Classic Rainbow-IIIc-Cyclic
Rainbow-IIIc-Cyclic-Compressed Rainbow-Vc-Classic Rainbow-Vc-Cyclic Rainbow-Vc-Cyclic-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_L3_FS picnic_L3_UR picnic_L5_FS picnic_L5_UR picnic2_L1_FS picnic2_L3_FS picnic2_L5_FS
qTesla-p-I qTesla-p-III
Signature Details:
Name: DILITHIUM_2
Version: https://github.com/pq-crystals/dilithium/commit/c1b40fd599e71f65aa18be64dd6c3fc8e84b0c08
Claimed NIST level: 1
Is IND-CCA: true
Length public key (bytes): 1184
Length secret key (bytes): 2800
Maximum length signature (bytes): 2044
Signer public key:
0C 3A 73 48 09 14 18 8D ... 70 0B 3C 13 CF 43 F2 AD
It took 0 millisecs to generate the key pair.
It took 2 millisecs to sign the message.
It took 1 millisecs to verify.
Signature:
6D 06 5E C0 32 DB 70 A8 ... AF C9 F0 28 12 43 6C 04
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"
-
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.