Overview
CRYSTALS-Dilithium is a lattice-based digital signature scheme whose security is based on the hardness of finding short vectors in lattices. The CRYSTALS-Dilithium Digital Signature Algorithm is a member of the CRYSTALS (Cryptographic Suite for Algebraic Lattices) suite of algorithms [2].
Support for CRYSTALS-Dilithium is now supported for IBM Semeru Java versions 11 and 17 on the IBMJCECCA security provider [3]. IBMJCECCA currently offers the following implementations:
- CRYSTALS-Dilithium (6,5) Round 2
- CRYSTALS-Dilithium (8,7) Round 2
- CRYSTALS-Dilithium (6,5) Round 3
- CRYSTALS-Dilithium (8,7) Round 3
The strength of a CRYSTALS-Dilithium key is represented by the size of its matrix of polynomials. For example, CRYSTALS-Dilithium (6,5) has a matrix size of 6x5. The larger the matrix size, the stronger the key. CRYSTALS-Dilithium keys can only be used for Digital Signature Generation and Verification [2].
This tutorial will demonstrate how to integrate CRYSTALS-Dilithium into a Java application. Before you continue reading, please ensure your environment is properly configured by reading QSC on Java: Configuring your IBM Z system to use Quantum-safe algorithms.
Step 1: Create Dilithium key pair
The first step is to create a Dilithium key pair using the KeyPairGenerator
and DilithiumKeyParameterSpec
classes.
The DilithiumKeyParameterSpec
class accepts the following values based on the desired implementation outlined in the Overview section:
dilithium65r2
dilithium87r2
dilithium65r3
dilithium87r3
KeyPairGenerator kpg =
KeyPairGenerator.getInstance("CRYSTALS-Dilithium", "IBMJCECCA");
DilithiumKeyParameterSpec kps =
new DilithiumKeyParameterSpec("dilithium87r3");
kpg.initialize(kps, null);
KeyPair keyPair = kpg.generateKeyPair();
Step 2: Get public and private keys
Now that we have the key pair, we can separate the keys into their own variables.
DilithiumPrivateKey privKey = (DilithiumPrivateKey) keyPair.getPrivate();
DilithiumPublicKey pubKey = (DilithiumPublicKey) keyPair.getPublic();
Step 3: Create Signature object
If you're already experienced with the JCE framework, the remainder of the steps may look familiar with other Signature algorithms. Use the Signature
class and specify CRYSTALS-Dilithium
and IBMJCECCA
.
Signature sign = Signature.getInstance("CRYSTALS-Dilithium", "IBMJCECCA");
Step 4: Initialize Signature for signing
Use the Dilithium private key to initialize the Signature object.
sign.initSign(privKey);
Step 5: Add bytes to Signature
Pass the data to be signend to the update()
method of the Signature
object.
byte[] bytes = "IBM - Let's create".getBytes();
sign.update(bytes);
Step 6: Perform signature
Finally, use the sign()
method to get the signature bytes of the updated data.
byte[] sigBytes = sign.sign();
Step 7: Initialize the Signature for verification
Now, we can initialize the Signature object to verify the signature bytes in the next step.
sign.initVerify(pubKey);
sign.update(bytes);
Step 8: Verify
Verify the signature.
boolean verified = sign.verify(sigBytes);
if (verified) {
System.out.println("Signature verified");
} else {
System.out.println("Signature could NOT be verified");
}
Example
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import com.ibm.crypto.hdwrCCA.provider.DilithiumKeyParameterSpec;
import com.ibm.crypto.hdwrCCA.provider.DilithiumPrivateKey;
import com.ibm.crypto.hdwrCCA.provider.DilithiumPublicKey;
public class DilithiumExample {
public static void main(String[] args) throws Exception {
// STEP 1: Create Dilithium key pair
KeyPairGenerator kpg =
KeyPairGenerator.getInstance("CRYSTALS-Dilithium", "IBMJCECCA");
DilithiumKeyParameterSpec kps =
new DilithiumKeyParameterSpec("dilithium87r3");
kpg.initialize(kps, null);
KeyPair keyPair = kpg.generateKeyPair();
// STEP 2: Get public and private keys
DilithiumPrivateKey privKey = (DilithiumPrivateKey) keyPair.getPrivate();
DilithiumPublicKey pubKey = (DilithiumPublicKey) keyPair.getPublic();
// STEP 3: Create Signature object
Signature sign = Signature.getInstance("CRYSTALS-Dilithium", "IBMJCECCA");
// STEP 4: Initialize Signature for signing
sign.initSign(privKey);
// STEP 5: Add bytes to Signature
byte[] bytes = "IBM - Let's create".getBytes();
sign.update(bytes);
// STEP 6: Perform signature
byte[] sigBytes = sign.sign();
// STEP 7: Initialize the Signature for verification
sign.initVerify(pubKey);
sign.update(bytes);
// STEP 8: Verify
boolean verified = sign.verify(sigBytes);
if (verified) {
System.out.println("Signature verified");
} else {
System.out.println("Signature could NOT be verified");
}
}
}
Output
The previous Example should produce the following output:
Signature verified
Conclusion
In this tutorial, we learned how to use the CRYSTALS-Dilithium QSC algorithm with IBMJCECCA to create keys and use a Signature to sign & verify bytes. Thanks for reading!
If you have additional questions, please email me at Gregory.Cernera@ibm.com.
References
- QSC on Java: Configuring your IBM Z system to use Quantum-safe algorithms
- CRYSTALS-Dilithium Digital Signature Algorithm
- Semeru for zOS, V11.0.22.0 and V17.0.10.0 GA!
How to obtain an IBM Semeru JDK
The IBM Java SAF APIs are included in the IBM Semeru Runtime Certified Edition for z/OS download. Please follow the links below to download the IBM Semeru JDK onto your own machines.
How to obtain IBM Semeru Runtime Certified Edition for z/OS?
IBM Semeru Runtime Certified Edition for z/OS is available for zero license charge through Shopz SMP/E, or you can download the non-SMP/E here. The subscription and service number is 5655-I48.
Supporting Links:
IBM Semeru Runtime Certified Edition for z/OS product page
For additional information on installation, troubleshooting and support please visit IBM Documentation.