---
title: "Java Cryptography Extension (JCE) Provider"
slug: "fortanix-dsm-clients-java-cryptography-extension-jce-provider"
updated: 2026-08-19T13:47:45Z
published: 2026-08-19T13:47:45Z
canonical: "support.fortanix.com/fortanix-dsm-clients-java-cryptography-extension-jce-provider"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://support.fortanix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Java Cryptography Extension (JCE) Provider

## 1.0 Introduction

This article provides an overview of the **Fortanix-Data-Security-Manager** **(DSM) Java Cryptography Extension (JCE) Provider**, including its installation, configuration, features, supported operations, and platform compatibility.

## 2.0 Download

Download the Fortanix DSM JCE Provider for all platforms [*here*](/v1/docs/jce).

## 3.0 Operating System (OS) Compatibility

*For information on the JCE Provider client OS compatibility matrix, refer to* [*Compatibility Matrix*](/v1/docs/clients-compatibility-matrix)*.*

## 4.0 Installation

### 4.1 System-wide Install

Perform the following steps:

1. Move the downloaded bundled provider jar file `sdkms-jce-provider-bundled-x.xx.xxxx.jar` to `${JAVA_HOME}/jre/lib/ext` directory.
2. Apply the Unlimited Strength Jurisdiction Policy Files by downloading the Policy file from the [*Oracle official documentation*](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html).

Extract the downloaded zip file, and copy the following files to the `${JAVA_HOME}/jre/lib/security` directory.
  - `local_policy.jar`
  - `US_export_policy.jar`
3. Add the provider to your code:

```bash
import com.fortanix.sdkms.jce.provider.SdkmsJCE;
SdkmsJCE provider = new SdkmsJCE();
Security.addProvider(provider);
```

Alternatively, the provider can be added in `${JAVA_HOME}/jre/lib/security/java.security` file, as the **last** provider in the list. This allows integration with non-program-based usage, for example, `keytool`, `jarsigner`, and so on. The following is an example `java.security` file:

```bash
security.provider.1=sun.security.provider.Sun 
security.provider.2=sun.security.rsa.SunRsaSign 
security.provider.3=sun.security.ec.SunEC 
security.provider.4=com.sun.net.ssl.internal.ssl.Provider 
security.provider.5=com.sun.crypto.provider.SunJCE 
security.provider.6=sun.security.jgss.SunProvider 
security.provider.7=com.sun.security.sasl.Provider 
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI 
security.provider.9=sun.security.smartcardio.SunPCSC 
security.provider.10=com.fortanix.sdkms.jce.provider.SdkmsJCE
```

### 4.2 Maven-Based Install

> [!NOTE]
> NOTE
> 
> This feature is available from Fortanix DSM version 3.19.1352 and later.

Maven projects define dependencies within the `pom.xml` file in source under the tag. This file is located in the base directory of the Maven project.

Perform the following steps:

1. Add the following dependency to the JCE Provider in the `pom.xml` file:

```bash
<dependency>
 <groupId>com.fortanix</groupId>
 <artifactId>sdkms-jce-provider</artifactId>
 <version>x.xx.xxxx</version>
</dependency>
```
2. Add the following provider to your code:

```bash
import com.fortanix.sdkms.jce.provider.SdkmsJCE;
SdkmsJCE provider = new SdkmsJCE();
Security.addProvider(provider);
```

## 5.0 Configuration

For the JCE Provider to connect to Fortanix DSM, provide the server URL and an API key of an application used for authentication.

These can be set as environment variables.

Example:

```bash
export FORTANIX_API_ENDPOINT=https://<fortanix_dsm_url>
export FORTANIX_API_KEY=<your API key>
export FORTANIX_ADD_KEY_OPS_OVERRIDE="EXPORT"
```

In this configuration, `FORTANIX_ADD_KEY_OPS_OVERRIDE` ensures that the `EXPORT` key operation is always included during key creation by the JCE provider.

> [!NOTE]
> NOTE
> 
> - The allowed key operations list will include `KeyOperations.EXPORT` along with other key operations.
> - If the cryptographic policy on the Fortanix DSM account disallows the `EXPORT` operation, the key creation request in JCE Provider will result in the error: `Some requested operations (EXPORT) is not allowed by policy`.

### 5.1 Certificated-Based Authentication (mTLS)

The application can also authenticate using a Client Certificate instead of an API key for a Mutual TLS (mTLS)-verified connection.

*For more information on certificate-based authentication, refer to* [*Authentication*](/v1/docs/users-guide-authentication).

If the client's private key and certificate are in PEM format (provided by your CA or openssl), convert them into Java KeyStore (JKS) format using the following command:

> [!NOTE]
> NOTE
> 
> Certificate import can fail if it includes unknown critical X.509 extensions. Fortanix DSM complies with [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2), which mandates rejection of certificates with unrecognized extensions marked as `critical`. To ensure compatibility, avoid marking custom or non-standard extensions as `critical`.

```bash
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -name "my-sdkms-app" -out client-sdkms.p12
```

> [!NOTE]
> NOTE
> 
> This command asks for a password to be set for the local KeyStore. Enter any password of your choice, for example, 'PASSWORD'.

Run the following command to provide the above-generated KeyStore as a JVM argument to your Java program:

```bash
java -Djavax.net.ssl.keyStoreType=pkcs12 -Djavax.net.ssl.keyStore=client-sdkms.p12 -Djavax.net.ssl.keyStorePassword=PASSWORD MyJCEProgram.java
```

Or programmatically set as system properties:

```bash
System.setProperty("javax.net.ssl.trustStoreType", "jks");
System.setProperty("javax.net.ssl.trustStore", <path to sdkms-truststore.jks file>);
System.setProperty("javax.net.ssl.trustStorePassword, "PASSWORD");
```

Java tools like `keytool`and `jarsigner` take JVM arguments as follows:

```bash
jarsigner -J-Djavax.net.ssl.keyStoreType=pkcs12 -J-Djavax.net.ssl.keyStore=client-sdkms.p12 -J-Djavax.net.ssl.keyStorePassword=PASSWORD ...
```

### 5.2 Custom CA Configuration

For on-premise Fortanix DSM installations, add the Organization CA to TrustStore for successful TLS communication with the API.

Perform the following steps:

1. Run the following command to create a Java TrustStore that saves the CA certificate (PEM format):

```bash
keytool -import -alias SDKMS_CA -file sdkms-root-ca.crt -keystore sdkms-truststore.jks -deststorepass PASSWORD
```
2. Run the following command to provide the TrustStore as a JVM argument to your Java program:

```bash
java -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStore=sdkms-truststore.jks - Djavax.net.ssl.trustStorePassword=PASSWORD MyJCEProgram.java
```

Or programmatically set as system properties:

```bash
System.setProperty("javax.net.ssl.trustStoreType", "jks");
System.setProperty("javax.net.ssl.trustStore", );
System.setProperty("javax.net.ssl.trustStorePassword, "PASSWORD");
```

Java tools like `keytool`and `jarsigner` take JVM arguments as follows:

```bash
jarsigner -J-Djavax.net.ssl.trustStoreType=jks -J-Djavax.net.ssl.trustStore=client-sdkms.p12 -J-Djavax.net.ssl.trustStorePassword=PASSWORD ...
```

## 6.0 Supported Algorithms

- Encrypt - Single Part
- Decrypt - Single Part

| **Crypto** | **Algorithm** | **Mode/Method** | **Key Size/Curve** | **Padding Support** | **Use** |
| --- | --- | --- | --- | --- | --- |
| Symmetric | AES | ECB | 128, 192, 256 bits | NOPADDING, PKCS5PADDING | Data Encryption or Decryption |
| CBC |
| CTR |
| CFB |
| GCM |
| FF1 | NOPADDING |
| FPE |
|  |  | Key Generation |
| DES | ECB | 56 bits | NOPADDING, PKCS5PADDING | Data Encryption or Decryption |
| CBC |
|  |  | Key Generation |
| DES3 | CBC ECB | 168 bits | NOPADDING, PKCS5PADDING | Data Encryption or Decryption |
| DESede | ECB | 168 bits | NOPADDING, PKCS5PADDING | Data Encryption or Decryption |
| CBC |
|  |  |  | Key Generation |
| HmacSHA1 |  |  |  | Mac Generate and Mac Verify Key Generation |
| HmacSHA256 |
| HmacSHA384 |
| HmacSHA512 |
| Asymmetric | RSA |  | 1024, 2048 bits | PKCS5PADDING,OAEPPADDING | Data Encryption or Decryption |
| 1024, 2048, 4096, 8192 bits |  | Asymmetric Key Pairs Generation |
| EC | SecP192K1 |  |  | Asymmetric Key Pairs Generation |
| SecP224K1 |
| NistP-192 |
| SecP256K1 |
| NistP-224 |
| NistP-256 |
| NistP-384 |
| NistP-512 |
| Ed25519 |
| RSA with SHA | SHA1withRSA |  |  | Digital Signature Sign or Verify |
| SHA256withRSA |
| SHA384withRSA |
| SHA512withRSA |
| EC with SHA | SHA1withECDSA |  |  | Digital Signature Sign or Verify |
| SHA256withECDSA |
| SHA384withECDSA |
| SHA512withECDSA |
| DSA with SHA | SHA1withDSA |  |  | Digital Signature Sign or Verify |
| SHA256withDSA |
| SHA384withDSA |
| SHA512withDSA |
| RSA-PSS | SHA1withRSAandMGF1 |  |  | Digital Signature Sign or Verify |
| SHA256withRSAandMGF1 |
| SHA384withRSAandMGF1 |
| SHA512withRSAandMGF1 |
| RSA-PKCS1V15 | SHA1withRSAandPKCS1V15 |  |  | Digital Signature Sign or Verify |
| SHA256withRSAandPKCS1V15 |
| SHA384withRSAandPKCS1V15 |
| SHA512withRSAandPKCS1V15 |

*For a complete list of supported algorithms, refer to* [*Algorithm Support*](/v1/docs/algorithm-support)*.*

## 7.0 Connection Pooling

Fortanix DSM version 3.21 and above supports a new feature called Connection Pooling.

Connection pooling allows restriction and reuse of connections with a maximum limit specified.

This allows setting some safe limits on each JCE application so that no single application can overwhelm the server.

### 7.1 With Connection Pooling

The environment variable `FORTANIX_CONN_MAX` is set to the maximum number of connections from that instance of the JCE application.

### 7.2 Without Connection Pooling

When the environment variable `FORTANIX_CONN_MAX` is not exported or is set to ``0`, the JCE Provider behaves without any connection pooling/limit. This is similar to JCE Provider behavior before version 3.21.

### 7.3 Scenarios

- `FORTANIX_CONN_MAX = 0`.
  - Existing behavior: The number of sockets is equal to the number of concurrent threads.
- `FORTANIX_CONN_MAX = X`, Concurrent threads less than X.
  - Behavior: Less than X sockets open at a time.
  - Observation: The sockets are also being reused.
- `FORTANIX_CONN_MAX = X`, Concurrent threads greater than X.
  - Behavior: Maximum X sockets open with reuse.
  - Observation: higher latency, which is expected since threads are now waiting for connections to get free.

### 7.4 Connection Pooling Keep-Alive

The environment variable `FORTANIX_CONN_KEEPALIVE` is a configurable property that is used to keep the duration of a live connection open for reuse in case of subsequent requests.

The default value is `5000` milliseconds (`5` seconds) in case it is not configured.

#### 7.4.1 Configuration

To configure keep-alive, declare it as a system environment variable. For example, `export FORTANIX_CONN_KEEPALIVE=4000`.

## 8.0 Client Side Failover

This feature in the Fortanix JCE Provider enables automatic retry of requests on alternative endpoints if the initial request does not complete within a specified timeout.

This enhances resilience and availability in distributed or clustered deployments.

### 8.1 Enable Client Side Failover

To enable this feature, set the following environment variable:

```bash
FORTANIX_DSM_ENABLE_CLIENT_SIDE_FAILOVER=true
```

In addition, configure the following environment variables to define failover behavior:

#### 8.1.1 Endpoint Configuration

The JCE Provider application needs to be aware of all the available endpoints for request retries. Endpoint resolution behavior is controlled by the environment variable `FORTANIX_DSM_NAME_RESOLUTION_STRATEGY`, which determines how failover endpoints are derived from `FORTANIX_API_ENDPOINT`.

- **Static Resolution:** Set `FORTANIX_DSM_NAME_RESOLUTION_STRATEGY=static`. In this case, `FORTANIX_API_ENDPOINT` must contain multiple comma-separated endpoint URLs.

Example:

```bash
FORTANIX_DSM_NAME_RESOLUTION_STRATEGY=static
FORTANIX_API_ENDPOINT="https://cluster1.dsm.com,https://cluster2.dsm.com"
```
- **Dynamic Resolution:** Set `FORTANIX_DSM_NAME_RESOLUTION_STRATEGY=dynamic`. In this case, `FORTANIX_API_ENDPOINT` should be a single endpoint. The application uses the system DNS resolver to resolve this endpoint into multiple IPs or hostnames.

Example:

```bash
FORTANIX_DSM_NAME_RESOLUTION_STRATEGY=dynamic
FORTANIX_API_ENDPOINT="https://cluster.dsm.com"
```

In this case, `https://cluster.dsm.com` must resolve to multiple valid hostnames.

> [!NOTE]
> NOTE
> 
> All resolved hostnames must be present in the TLS certificates presented by the corresponding servers.

#### 8.1.2 Retry Configuration

- Set the retry interval in milliseconds using the following environment variable:

```bash
FORTANIX_DSM_REQUEST_RETRY_INTERVAL=<milliseconds>
```

This defines how long the client waits before retrying the request on a different endpoint.
- Set the maximum number of retries per request using the following environment variable:

```bash
FORTANIX_DSM_MAX_REQUEST_RETRIES=<maximum retry number>
```

If this value exceeds the number of currently healthy endpoints, the number of healthy endpoints is used instead. All endpoints are considered healthy initially. An endpoint is removed from the healthy list if a non-API exception occurs (For example, connection failure, SSL handshake failure).

#### 8.1.3 Health Check Configuration

Optionally, you can enable periodic health checks for all endpoints using the following environment variable:

```bash
FORTANIX_DSM_HEALTH_CHECK_INTERVAL=<milliseconds>
```

Health checks will only be performed if the value of `FORTANIX_DSM_HEALTH_CHECK_INTERVAL` is greater than 0.

A `GET /sys/v1/health` API call is made to each endpoint according to the resolution strategy. Endpoints that respond successfully are added back to the healthy list.

> [!NOTE]
> NOTE
> 
> - Only the following cryptographic operations support automatic retries: `sign`, `verify`, `encrypt`, `decrypt`, `wrapkey`, `digest`, and `mac`.
> - Operations not listed above are executed on a single endpoint determined by the resolution strategy.
>   - For static resolution, the first endpoint in `FORTANIX_API_ENDPOINT` is used.
>   - For dynamic resolution, the single endpoint specified in `FORTANIX_API_ENDPOINT` is used.
> - When a request is retried on a different endpoint, the original request is not canceled. The JCE Provider application awaits responses from all outstanding requests and uses the response from the first one that completes.
> 
> Example: If `FORTANIX_DSM_REQUEST_RETRY_INTERVAL` elapses before the first request (`request1`) completes, the request is retried on the next endpoint (`request2`). If `request1` finishes before `request2`, its response is used and returned.

## 9.0 Logging

With the Fortanix DSM 3.21 release, by default, the logging option is disabled.

Export the following environment variables to enable it.

- To enable debug logs, set the environment variable:

```bash
export FORTANIX_LOG_DEBUG=true
```
- To enable only API logs, set the environment variable:

```bash
export FORTANIX_LOG_API=true
```
- To set a file location for local logs, set the environment variable:

```bash
export FORTANIX_LOG_FOLDER="/path/to/logfile-folder"
```

This creates a log file `/path/to/logfile-folder/sdkms-jce.log`.

## 10.0 Local Digest

Local Digest is now set as the default behavior in the Fortanix DSM JCE Provider from the Fortanix DSM 4.10 release onwards. By default, Fortanix DSM makes API calls to DSM for performing message digest operations, but from the 4.10 release onwards, it will not make the API calls and will perform the message digest operations locally without the user’s intervention through the SUN provider’s implementation. This reduces the overhead of the digest API calls to Fortanix DSM while performing sign and verify operations.

To enable or disable the local digest, use the environment variable `FORTANIX_USE_LOCAL_DIGEST`.

Set the environment variable to `false` to perform the digest operations through the DSM API calls.

## 11.0 Keytool and KeyStores

The `keytool` utility can now use the Fortanix DSM JCE provider for the management of key pairs and certificates which are backed by the Fortanix DSM service.

KeyStore is used to store the generated keys and certificates in Fortanix DSM.

Fortanix DSM JCE supports two types of KeyStores:

- SDKMS-local
- SDKMS

### 11.1 SDKMS-local

This KeyStore can be used by clients who expect more-or-less JKS (the default KeyStore) semantics. All metadata will be stored locally and imported to Fortanix DSM when `keystore.store` is called.

To use `keytool` with the KeyStore SDKMS-local, provide the following :

- `storetype` must be provided as `SDKMS-local`
- `providerName` must be `sdkms-jce`

Different `keytool` operations that can be performed using the local KeyStore are as follows (*Refer to* [*Section 11.1.1: Usage*](/v1/docs/clients-java-cryptography-extension-jce-provider#1111-usage) *with* `keytool` *for setup*):

#### 11.1.1 Usage

Run the following command to perform key and certificate operations using the Fortanix DSM keystore using the `keytool` utility:

```bash
keytool <operations> -storetype SDKMS-local -providerName sdkms-jce -storepass passwd -keypass passwd
```

- Generate Asymmetric keys

```bash
keytool -genkeypair -alias alias -keyalg RSA -keystore keystore_file -keysize 1024 -providerName sdkms-jce -storetype SDKMS-local -storepass passwd -keypass passwd -dname "CN=fortanix,OU=fortanix,O=fortanix,L=Mountain View,ST=California,C=US"
```
- Import Certificate

```bash
keytool -importcert -trustcacerts -alias alias -file certificate-path -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local -storepass passwd -noprompt -trustcacerts
```
- Import Keystore

```bash
keytool -importkeystore -srcstoretype SDKMS-local -deststoretype SDKMS-local -srcalias alias -srcProviderName sdkms-jce -destProviderName sdkms-jce -srckeystore source_keystore_file -destkeystore dest_keystore_file -srcstorepass passwd -deststorepass passwd -srckeypass passwd -destkeypass passwd
```
- Generate AES Symmetric Keys

```bash
keytool -genseckey -alias alias -keyalg AES -keysize 256 -storepass passwd -keypass passwd -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local
```
- Import Password as Secret Keys

```bash
keytool -importpassword -alias alias -storepass passwd -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local
```
- List

```bash
keytool -list -v -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local -storepass passwd
```
- Delete

```bash
keytool -delete -alias alias -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local -storepass passwd
```

### 11.2 SDKMS

This KeyStore can be used when a user needs to interact with Fortanix DSM directly. No metadata is stored locally. The Fortanix DSM groups are an abstraction for different KeyStores for a user, hence a `groupId` will be used while storing and retrieving the keys for this KeyStore type.

To use `keytool` with `keystore` type `SDKMS`, provide the following :

- `storetype` must be `SDKMS`.
- `providerName` must be `sdkms-jce`.
- key and store password must be provided as `groupId` to store the corresponding key in that group.

Unsupported scenarios in KeyStore type `SDKMS`:

- AES transient keys are supported to be imported in a different group than the group used to create the key.
- RSA, EC, DES, and DES3 keys are persistent keys and cannot be updated to different `groupId`.
- Importing a KeyStore is not supported as all the keys cannot be updated to a different `groupId`.

Different `keytool` operations that can be performed using the local KeyStore are as follows (*Refer to* [*Section 11.2.1: Usage*](/v1/docs/clients-java-cryptography-extension-jce-provider#1121-usage) *with* `keytool` *for setup*) :

#### 11.2.1 Usage

Run the following command to perform key and certificate operations using the Fortanix DSM keystore with group-based authentication using the `keytool` utility:

```bash
keytool <operation> -storetype SDKMS -providerName sdkms-jce -keypass <groupId> -storepass <groupId>`
```

- Import Certificate

```bash
keytool -importcert -trustcacerts -alias alias -file certificate-path -keystore keystore_file -providerName sdkms-jce -storetype SDKMS -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050 -noprompt -trustcacerts
```
- Generate AES Symmetric Keys

```plaintext
keytool -genseckey -alias alias -keyalg AES -keysize 256 -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050 -keypass 2ff36949-ee70-4145-bd57-7de1ada5c050 -keystore keystore_file -providerName sdkms-jce -storetype SDKMS
```
- Import Password as Secret Key

```bash
keytool -importpassword -alias alias -storepass groupId -keystore keystore_file -providerName sdkms-jce -storetype SDKMS
```
- List the above generated AES Key

```bash
keytool -list -v -keystore keystore_file -providerName sdkms-jce -storetype SDKMS -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050
```
- Delete the above AES Key

```bash
keytool -delete -alias alias -keystore keystore_file -providerName sdkms-jce -storetype SDKMS -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050
```

## 12.0 Jarsigner

To generate an entity's signature for a file, the entity must first have a public/private key pair associated with it and one or more certificates that authenticate its public key.

The `jarsigner` command uses key and certificate information from a keystore to generate digital signatures for JAR files.

*For more information, refer to the* [*Oracle official documentation*](https://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html)*.*

### 12.1 Syntax

```bash
jarsigner -keystore <keystore_file> -storepass <storepassword> <filenameTosigned> <alias>    
```

### 12.2 Examples

```bash
jarsigner -keystore $KEYSTORE_PATH -storepass $JCE_SIGNING_PASSWD $JARFILE $ALIAS
```

```bash
jarsigner -keystore $KEYSTORE -providerName $PROVIDER_NAME -sigalg SHA256withRSA -storetype $TYPE -storepass $PASSWD $RESOURCES_PATH"/JCETest-0.0.1.jar" jcetest
```

```bash
jarsigner -verify $RESOURCES_PATH"/JCETest-0.0.1.jar" -providerName $PROVIDER_NAME -sigalg SHA256withRSA
```

### 12.3 Environment Setup

Perform the following steps:

1. Run the following commands to set the environment variables `FORTANIX_API_ENDPOINT` and `FORTANIX_API_KEY`:

```bash
export FORTANIX_API_ENDPOINT=https://<FORTANIX_DSM_URL>
export FORTANIX_API_KEY=<API Key>
```

Add the `sdkms-jce-provider` JAR inside the folder `$JAVA_HOME/jre/lib/ext/` .
2. Run the following `keytool` command to generate a private key and its public certificate:

This command will generate the file `keystore1` locally and a private key named `jcetest` in Fortanix DSM.

You must provide the Fortanix DSM Group ID as the `storepass` option.

```bash
keytool -genkey -alias jcetest -keyalg RSA -keystore keystore1 -keysize 1024 -providername sdkms-jce -storetype SDKMS -storepass d7e89ac7-f0dc-49d1-9196-75aaf6afc47c
```
3. Run the following command to sign the JAR:

```bash
jarsigner -keystore keystore1 -providerName sdkms-jce -sigalg SHA256withRSA -storetype SDKMS -storepass d7e89ac7-f0dc-49d1-9196-75aaf6afc47c a.jar jcetest
```

### 12.4 Jarsigner Using Existing Keys

To sign the JAR using existing keys, import the existing private key along with its certificate chain into Fortanix DSM using the `sdkms-cli` tool, and then use the private key alias for signing the JAR.

## 13.0 Java Examples

### 13.1 Generate RSA Keys

```bash
//Generate RSA Keys:
SdkmsJCE provider = SdkmsJCE.getInstance();
String algorithm = AlgorithmParameters.RSA;
KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm, provider);
SecurityObjectParameterSpec parameterSpec = new SecurityObjectParameterSpec(false);
kpg.initialize(keySize);
kpg.initialize(parameterSpec, null);
KeyPair keyPair = kpg.genKeyPair();
```

### 13.2 RSA Sign and Verify

```bash
...
String algorithm = AlgorithmParameters.RSA;
KeyPair rsaKeyPair = keyGenerator.generateKeyPair();
Signature sig = Signature.getInstance(algorithm, provider);
sig.initSign(rsaKeyPair.getPrivate());

//sign
byte[] data = "test".getBytes("UTF8");
Signature sig = Signature.getInstance(“SHA256withRSA”, provider);
sig.initSign(keyPair.getPrivate());
sig.update(data);
byte[] signatureBytes = sig.sign();

//verify
sig.initVerify(keyPair.getPublic());
sig.update(data);
assertEquals(true, sig.verify(signatureBytes));
```

### 13.3 Generate AES Keys

```bash
SdkmsJCE provider = SdkmsJCE.getInstance();
String algorithm = AlgorithmParameters.AES;
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(algorithm, provider);
keyGenerator.initialize(256);
SecretKey aesKey = keyGenerator.generateKey();
```

### 13.4 AES Cipher Encryption and Decryption

```bash
...
String algorithm = AlgorithmParameters.AES;
String mode = CipherMode.ECB.toString();
String padding = ProviderConstants.PKCS5PADDING

SecretKey secretKey = keyGenerator.generateKey();

Cipher cipher = Cipher.getInstance(algorithm, provider);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);

String PLAIN = "testData";
// encryption
byte[] cipherBytes = cipher.doFinal(PLAIN.getBytes());

// decryption
cipher.init(Cipher.DECRYPT_MODE, key, params);
byte[] plainBytes = cipher.doFinal(cipherBytes);

// verify
assertEquals(new String(plainBytes), PLAIN);
```

### 13.5 AES Cipher Encryption and Decryption Using Existing Keys in DSM

Instantiate an `SobjectDescriptor` with either key name or key ID.

```bash
@ApiModel(
    description = "This uniquely identifies a persisted or transient sobject. Exactly one of `kid`, `name`, and `transient_key` must be present. "
)
public class SobjectDescriptor {
    @JsonProperty("kid")
    private String kid = null;
    @JsonProperty("name")
    private String name = null;
    @JsonProperty("transient_key")
    private String transientKey = null;
```

Instantiate `SdkmsAESKey` object using the `Sobjectdescriptor`.

```bash
public SdkmsAESKey(SobjectDescriptor descriptor) {
    super(descriptor);
}
```

Or, if you have the key ID, use the following constructor without instantiating the `SobjectDescriptor`.

```bash
public SdkmsAESKey(String keyId, Integer keySize, String transientKey) {
    this(new SobjectDescriptor().kid(keyId).transientKey(transientKey));
    this.keySize = keySize;
}
```

After the key object (let's say `key` ) has been instantiated, it can be supplied for encryption as shown below:

```bash
cipher.init(Cipher.ENCRYPT_MODE, key, params);

// Encrypted content 
byte[] cipherBytes = cipher.doFinal(PLAIN.getBytes());
// decrypt the same content 
cipher.init(Cipher.DECRYPT_MODE, key, params);
byte[] plainBytes = cipher.doFinal(cipherBytes);
```

### 13.6 AES Cipher Encryption and Decryption Multipart

```bash
private void testAesGcmCcmPkcs5(Integer keySize, CryptMode mode, boolean multiPart, byte[] blob) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, IOException {
    String algorithm = String.format("AES_%d/%s/%s", keySize, mode.toString(), ProviderConstants.PKCS5PADDING);
    Cipher cipher = Cipher.getInstance(algorithm, provider);
    SecretKey secretKey = generateAESKey(keySize);
    AlgorithmParameters params = cipher.getParameters();

    int chunkSize = 1024; // 1KB

    ByteArrayOutputStream cipherStream = new ByteArrayOutputStream();
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, params);
    cipher.updateAAD("TestAAD".getBytes());
    if (!multiPart) {
        cipherStream.write(cipher.update(blob));
    }
    else {
        int offset = 0;
        int size  = chunkSize;
        int remaining = blob.length - size;
        cipherStream.write(cipher.update(blob, offset, size));
        while(remaining > 0) {
            offset = size;
            int nextChunk  = Math.min(remaining, chunkSize);
            cipherStream.write(cipher.update(blob, offset, nextChunk));
            size += nextChunk;
            remaining = blob.length - size;
        }
    }
    cipherStream.write(cipher.doFinal());
    byte[] cipherBytes = cipherStream.toByteArray();

    ByteArrayOutputStream plainStream = new ByteArrayOutputStream();
    cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
    cipher.updateAAD("TestAAD".getBytes());
    if (!multiPart) {
        plainStream.write(cipher.doFinal(cipherBytes));
    }
    else {
        int offset = 0;
        int size  = chunkSize;
        int remaining = cipherBytes.length - size;
        plainStream.write(cipher.update(cipherBytes, offset, size));
        while(remaining > chunkSize) {
            offset = size;
            plainStream.write(cipher.update(cipherBytes, offset, chunkSize));
            size += chunkSize;
            remaining = cipherBytes.length - size;
        }
        // while decrypting, the final chunk need to be passed to doFinal for extracting the tag.
        plainStream.write(cipher.doFinal(cipherBytes, size, remaining));
    }

    // after going through encryption and decryption we should get same plain text back
    assertEquals(plainStream.toString(), new String(blob));
}
```

### 13.7 Storing RSA Key in KeyStore

```bash
KeyStore keyStore = KeyStore.getInstance("SDKMS", provider); // here can you either use SDKMS or sdkms-local as provider 

keyStore.load(null, null);
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", provider);
gen.initialize(2048);
KeyPair keyPair = gen.generateKeyPair();
keyStore.load(null, null);
keyStore.setKeyEntry(alias, keyPair.getPrivate(), SDKMS_GROUPID.toCharArray(), null);
```

### 13.8 Storing Secret Key in KeyStore

```bash
KeyGenerator gen = KeyGenerator.getInstance("AES", provider);
gen.init(128);
Key key = gen.generateKey();
keyStore.load(null, null);
keyStore.setKeyEntry(alias, key, SDKMS_GROUPID.toCharArray(), null);
```

### 13.9 Storing Certificate in KeyStore

```bash
...
 CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
 InputStream certificateInputStream = new FileInputStream("certificate.crt");
 Certificate certificate = certificateFactory.generateCertificate(certificateInputStream);
 keyStore.setCertificateEntry("certName", cert);
```

### 13.10 Listing Alias of KeyStore

```bash
...
Enumeration keys = keyStore.aliases();
while (keys.hasMoreElements()) {
    keys.nextElement(); 
}
```

### 13.11 Deleting an Alias from KeyStore

```bash
...
keyStore.deleteEntry(alias);
```

### 13.12 Creating KeyStore for SSL/TLS

```bash
FileInputStream keyInputStream = new FileInputStream(PRIVATE_KEY_PATH);
byte[] keyBytes = new byte[keyInputStream.available()];
keyInputStream.read(keyBytes);

keyInputStream.close();

String privateKey = new String(keyBytes, "UTF-8");
privateKey = privateKey.replaceAll("(-+BEGIN PRIVATE KEY-+\\r?\\n|-+END PRIVATE KEY-+\\r?\\n?)", "");

BASE64Decoder decoder = new BASE64Decoder();
keyBytes = decoder.decodeBuffer(privateKey);

PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA", provider);
PrivateKey pk = kf.generatePrivate(privKeySpec);

CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
FileInputStream certInputStream = new FileInputStream(CERTIFICATE_PATH);
Certificate cert = certFactory.generateCertificate(certInputStream);
Certificate[] chain = new Certificate[1];

KeyStore keyStore = KeyStore.getInstance("SDKMS-local", provider);
keyStore.load(null,null);
keyStore.setKeyEntry(TLS_CLIENT_KEY_NAME, pk, null, chain);

OutputStream stream = new FileOutputStream(TLS_KEYSTOR_PATH);
keyStore.store(stream, null);
```

### 13.13 Setting SSL/TLS context

```bash
KeyStore keyStore = KeyStore.getInstance("SDKMS-local", provider);
InputStream inputStream = new FileInputStream(TLS_KEYSTORE_PATH);
keyStore.load(inputStream,null);
Enumeration<String> aliases = keyStore.aliases();
final String alias = aliases.nextElement();

// set ssl context
SSLContext sslContext = SSLContexts.custom()
    .loadKeyMaterial(keyStore, null, new PrivateKeyStrategy() {
        public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) {
            return alias;
        }
    }).loadTrustMaterial(null, new TrustStrategy() {
        public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            return true;
        }
    })
    .build();

SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
    new String[]{"TLSv1.2", "TLSv1.1"},
    null,
    SSLConnectionSocketFactory.getDefaultHostnameVerifier());

CloseableHttpClient client = HttpClients.custom()
    .setSSLSocketFactory(sslConnectionSocketFactory)
    .build();
HttpGet httpget = new HttpGet(TLS_ENDPOINT);
CloseableHttpResponse response = client.execute(httpget);
HttpEntity entity = response.getEntity();
```

### 13.14 Import DSA Keys

```bash
import com.fortanix.sdkms.jce.provider; 
import java.security.*; 
import java.security.spec.DSAGenParameterSpec;
```

### 13.15 Generate DSA Keys

```bash
int keySize = 2048; 
int subGroupSize = 224; 
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA", provider); 
DSAGenParameterSpec dsaGenParameterSpec = new DSAGenParameterSpec(keySize, subGroupSize); 
SecurityObjectParameterSpec parameterSpec = new SecurityObjectParameterSpec(dsaGenParameterSpec, false); 
kpg.initialize(parameterSpec, null); 
KeyPair keyPair = kpg.genKeyPair();
```

### 13.16 DSA Sign

```bash
byte[] data = "test".getBytes("UTF8");
Signature sig = Signature.getInstance("SHA1withDSA", provider);
sig.initSign(keyPair.getPrivate());
sig.update(data);
byte[] signatureBytes = sig.sign();
```

### 13.17 DSA Verify

```bash
sig.initVerify(keyPair.getPublic());
sig.update(data);

assertNotNull(sig);
assertEquals(true, sig.verify(signatureBytes));
```

### 13.18 Format Preserving Encryption (FPE)

The following is the sample code for generating tokenization objects.

```bash
FpeOptionsBasic basic = new FpeOptionsBasic();
basic.minLength(5).maxLength(5).radix(10);
int size = 256;
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES",provider);
FpeParameterSpec fpeParameterSpec = new FpeParameterSpec(basic);
SecurityObjectParameterSpec parameterSpec = new SecurityObjectParameterSpec(fpeParameterSpec,false);
keyGenerator.init(size);
keyGenerator.init(parameterSpec);
SecretKey key = keyGenerator.generateKey();
```

The following is the sample code for encryption and decryption using tokenization. A tokenization object of a custom type is created.

```bash
int size = 256;
String mode= FPE;
String padding=NOPADDING;
String algorithm = String.format("AES_256/FPE/NOPADDING", keySize, mode, padding);
Cipher cipher = Cipher.getInstance(algorithm, provider);
SobjectDescriptor sobjDesc = new SobjectDescriptor().name("key_name");
KeyObject keyObj = SdkmsKeyService.getKeyObject(sobjDesc);
SdkmsAESKey key = new SdkmsAESKey(keyObj);
AlgorithmParameters params = cipher.getParameters();
cipher.init(Cipher.ENCRYPT_MODE, key, params);
String PLAIN = "123456789000";
// Encrypted content
byte[] cipherBytes = cipher.doFinal(PLAIN.getBytes());
// decrypt the same content
cipher.init(Cipher.DECRYPT_MODE, key, params);
byte[] plainBytes = cipher.doFinal(cipherBytes);;
```

Fortanix Data Security Manager (DSM) is the world’s first cloud service secured with Intel® SGX. With Fortanix DSM, you can securely generate, store, and use cryptographic keys and certificates, as well as other secrets such as passwords, API keys, tokens, or any blob of data. Your business-critical applications and containers can integrate with Fortanix DSM using legacy cryptographic interfaces (PKCS#11, CNG, and JCE) or using the native Fortanix DSM RESTful interface.

## Related

- [SDKs for REST API](/fortanix-dsm-clients-sdks-for-rest-api.md)
- [Fortanix DSM with Microsoft CNG Provider and SignTool](/using-fortanix-dsm-with-microsoft-cng-provider-and-signtool.md)
- [Exporting Fortanix DSM Keys to Cloud Providers for BYOK - Alibaba](/exporting-dsm-keys-to-cloud-providers-for-byok-alibaba.md)
