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

# Manage keys and encrypt with Java

> Use the FXCL Java API to manage CryptoHub AES key stores and perform local or CryptoHub-backed encryption and decryption.

Use the FXCL Java API to manage CryptoHub key stores and choose between local application encryption and CryptoHub-backed encryption.

## What you'll build

You will:

* Create an AES-256 key store through Java.
* Encrypt and decrypt locally with a retrievable key.
* Encrypt and decrypt on CryptoHub with a non-retrievable key and DPM header.
* Rotate and delete a test key store.

## Before you begin

Complete [Install and authenticate FXCL](./install-and-authenticate). Confirm that Java can load both `/usr/share/java/fxcl-java.jar` and the native library in `/usr/lib`.

<Warning>
  The validated AES-CBC examples do not provide authenticated integrity by themselves. Add an approved integrity control for application data.
</Warning>

## Create a key store

```java theme={null}
import com.futurex.fxcl.crypto.KeyAlgo;
import com.futurex.fxcl.crypto.KeyUsage;
import com.futurex.fxcl.kmes.store.KeyStore;
import com.futurex.fxcl.kmes.store.KeyStoreInfo;
import com.futurex.fxcl.kmes.store.KeyStoreManager;

KeyStoreManager manager = new KeyStoreManager(server);

KeyStoreInfo info = new KeyStoreInfo();
info.setName("customer-data-encryption");
info.setKeyAlgo(KeyAlgo.AES);
info.setKeyBits(256);
info.setKeyUsage(KeyUsage.DEK);
info.setRetrievable(true);
info.setRotationPeriod("90 Days");

KeyStore store = manager.createStore(info);
```

`KeyUsage.DEK` creates a data-encryption key store. `setRetrievable(true)` permits local encryption.

## Encrypt and decrypt locally

```java theme={null}
import com.futurex.fxcl.crypto.BlockCipherMode;
import com.futurex.fxcl.crypto.Decrypt;
import com.futurex.fxcl.crypto.Encrypt;
import com.futurex.fxcl.crypto.Padding;
import com.futurex.fxcl.crypto.SymCipherParams;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

byte[] plaintext = "application data".getBytes(StandardCharsets.UTF_8);

SymCipherParams params = new SymCipherParams();
params.setMode(BlockCipherMode.CBC);
params.setPadding(Padding.PKCS7);

Cipher encrypt = Encrypt.newCipher(store.getKey(), params);
byte[] ciphertext = encrypt.doFinal(plaintext);

Cipher decrypt = Decrypt.newCipher(store.getKey(), params);
byte[] recovered = decrypt.doFinal(ciphertext);

if (!Arrays.equals(plaintext, recovered)) {
    throw new IllegalStateException("Decrypted data does not match");
}
```

The operation runs in the Java process. Protect the endpoint and application memory as part of the key boundary.

## Encrypt and decrypt on CryptoHub

Create a separate non-retrievable store:

```java theme={null}
KeyStoreInfo remoteInfo = new KeyStoreInfo();
remoteInfo.setName("customer-remote-encryption");
remoteInfo.setKeyAlgo(KeyAlgo.AES);
remoteInfo.setKeyBits(256);
remoteInfo.setKeyUsage(KeyUsage.DEK);
remoteInfo.setRetrievable(false);
remoteInfo.setRotationPeriod("90 Days");

KeyStore remoteStore = manager.createStore(remoteInfo);
```

Configure the remote operation and include a DPM header:

```java theme={null}
import com.futurex.fxcl.kmes.crypto.RemoteDecrypt;
import com.futurex.fxcl.kmes.crypto.RemoteEncrypt;
import com.futurex.fxcl.kmes.crypto.RemoteEncryptParams;

SymCipherParams cipherParams = new SymCipherParams();
cipherParams.setMode(BlockCipherMode.CBC);
cipherParams.setPadding(Padding.PKCS5);

RemoteEncryptParams remoteParams = new RemoteEncryptParams(server);
remoteParams.setCipherParams(cipherParams);
remoteParams.setUseHeader(true);
remoteParams.setUseRandomIV(true);

Cipher remoteEncrypt = RemoteEncrypt.newCipher(
    remoteStore.getKeyInfo(),
    remoteParams
);
byte[] remoteCiphertext = remoteEncrypt.doFinal(plaintext);

Cipher remoteDecrypt = RemoteDecrypt.newHeaderCipher(server);
byte[] remoteRecovered = remoteDecrypt.doFinal(remoteCiphertext);

if (!Arrays.equals(plaintext, remoteRecovered)) {
    throw new IllegalStateException("Remote decrypt did not match");
}
```

The DPM header identifies the key and cryptographic parameters required for decryption. Store the full header and ciphertext together.

## Rotate and delete the store

```java theme={null}
manager.rotateStore(store);
manager.deleteStore(store.getInfo().getName());
```

Close JNI-backed objects when the application no longer needs them:

```java theme={null}
store.close();
server.close();
```

Prefer try-with-resources for `KeyServer`, `Credential`, and `KeyStore`.

## Build and run

```bash theme={null}
javac -cp /usr/share/java/fxcl-java.jar App.java

java -Djava.library.path=/usr/lib \
  -cp .:/usr/share/java/fxcl-java.jar \
  App
```

## Verify it works

Require these results:

* The Java API authenticates the Host API session.
* A retrievable store completes the local round trip.
* A non-retrievable store completes the CryptoHub-backed round trip.
* DPM-header decryption recovers the original data.
* Rotation succeeds.
* The test stores are deleted.

Do not log API keys, passwords, clear keys, plaintext, ciphertext, or DPM header contents.

## Troubleshooting

| Signal                                         | Cause                                                                                | Action                                                                           |
| ---------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| `UnsatisfiedLinkError`                         | Java cannot locate the FXCL native library.                                          | Set `-Djava.library.path=/usr/lib` and confirm `libfxcl.so` is installed.        |
| Java login returns `LN=0`                      | The API key authenticated, but the role context needs finalization.                  | Send a separate `[AORKLO;LN1;]` request on the same connection.                  |
| Local `getKey` fails                           | The store is not retrievable or has no active key.                                   | Use a retrievable store for the local path.                                      |
| Remote encryption fails before processing data | The store is retrievable, the key usage is wrong, or the identity cannot run `RKED`. | Use a non-retrievable `DEK` store and verify the Host API command and partition. |

## Version and scope

This procedure was validated with FXCL 1.9.5, CryptoHub 7.2.0.7, Ubuntu 22.04, OpenSSL 3, and OpenJDK 17.


## Related topics

- [Java Keytool](/Integrations/HSM/Key_management/Java_Keytool/Java_Keytool.md)
- [Create an application partition for Java Keytool](/Integrations/HSM/Key_management/Java_Keytool/Configure_the_Vectera_Plus/Create_an_application_partition_for_Java_Keytool.md)
- [Create Java KeyStore](/Integrations/HSM/Key_management/Java_Keytool/Create_Java_KeyStore.md)
- [Configure the JAVA_HOME environment variable](/Integrations/HSM/Key_management/Java_Keytool/Configure_the_JAVA_HOME_environment_variable.md)
- [Create an application partition for Java Jarsigner](/Integrations/HSM/Code_signing/Java_Jarsigner/Configure_the_Vectera_Plus/Create_an_application_partition_for_Java_Jarsigner.md)
