> ## 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.

# Configure tokenization profiles

> Create FXCL client-side and CryptoHub-backed tokenization profiles, bind AES keys, and tokenize structured values with Java.

FXCL tokenization profiles bind format-preserving encryption parameters to a CryptoHub key store. The profile controls the algorithm, character set, preserved characters, verification length, and execution location.

## What you'll build

This guide configures:

* A client-side FF3-1 profile with a retrievable AES key
* A CryptoHub-backed FF1 profile with a non-retrievable, HSM-trusted AES key
* Tokenize and detokenize calls that preserve the first four characters

## Before you begin

Complete [Install and authenticate FXCL](./install-and-authenticate).

For client-side tokenization, the application endpoint must be approved to receive a retrievable key.

For CryptoHub-backed tokenization, the Anchor HSM must have the required tokenization capability and license. The identity must also be able to manage token profiles and execute `TOKA` and `TOKG`. Confirm both token operations with a bounded synthetic round trip. Successful key-store or profile management does not prove token-operation access.

<Note>
  Server-side FF1 requires the **Format-Preserving Encryption** and **Format-Preserving Encryption FF1** features on the Anchor HSM.
</Note>

## Create a client-side tokenization profile

Create a retrievable AES-256 data-encryption key store:

```java theme={null}
KeyStoreInfo localInfo = new KeyStoreInfo();
localInfo.setName("customer-token-local");
localInfo.setKeyAlgo(KeyAlgo.AES);
localInfo.setKeyBits(256);
localInfo.setKeyUsage(KeyUsage.DEK);
localInfo.setRetrievable(true);
localInfo.setRotationPeriod("90 Days");

KeyStoreManager storeManager = new KeyStoreManager(server);
KeyStore localStore = storeManager.createStore(localInfo);
```

Configure an FF3-1 decimal profile that preserves the first four characters:

```java theme={null}
import com.futurex.fxcl.fpe.FpeAlgo;
import com.futurex.fxcl.fpe.FpeCharset;
import com.futurex.fxcl.fpe.FpeNamespace;
import com.futurex.fxcl.fpe.TokenizeParams;
import com.futurex.fxcl.kmes.token.TokenProfile;
import com.futurex.fxcl.kmes.token.TokenProfileManager;

TokenizeParams localParams = new TokenizeParams();
localParams.setAlgo(FpeAlgo.FF3_1);
localParams.setNamespace(new FpeNamespace(
    FpeCharset.Decimal.getValue() |
    FpeCharset.Underscore.getValue()
));
localParams.setPreserveLeading(4);

TokenProfile localProfile = new TokenProfile();
localProfile.setName("customer-token-local");
localProfile.setClientSide(true);
localProfile.setKeyStore(localStore.getInfo().getName());
localProfile.setVerifyLength(0);
localProfile.setParams(localParams);

TokenProfileManager profileManager = new TokenProfileManager(server);
profileManager.createProfile(localProfile);
```

`setClientSide(true)` identifies a local profile. The profile's key store must be retrievable.

## Tokenize and detokenize locally

```java theme={null}
import com.futurex.fxcl.fpe.Tokenize;

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

String clearValue = "0123456789";

Cipher tokenize = Tokenize.newCipher(
    Cipher.ENCRYPT_MODE,
    localStore.getKey(),
    localProfile.getParams()
);
String token = new String(
    tokenize.doFinal(clearValue.getBytes(StandardCharsets.US_ASCII)),
    StandardCharsets.US_ASCII
);

Cipher detokenize = Tokenize.newCipher(
    Cipher.DECRYPT_MODE,
    localStore.getKey(),
    localProfile.getParams()
);
String recovered = new String(
    detokenize.doFinal(token.getBytes(StandardCharsets.US_ASCII)),
    StandardCharsets.US_ASCII
);

if (token.equals(clearValue) ||
    token.length() != clearValue.length() ||
    !token.substring(0, 4).equals(clearValue.substring(0, 4)) ||
    !recovered.equals(clearValue)) {
    throw new IllegalStateException("Tokenization verification failed");
}
```

A successful operation preserves the value length and the configured leading characters. Detokenization must recover the original value exactly.

## Create a CryptoHub-backed profile

Create a non-retrievable key store:

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

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

Configure the server-side profile and bind the active key explicitly:

```java theme={null}
TokenizeParams remoteParams = new TokenizeParams();
remoteParams.setAlgo(FpeAlgo.FF1);
remoteParams.setNamespace(new FpeNamespace(
    FpeCharset.Decimal.getValue() |
    FpeCharset.Underscore.getValue()
));
remoteParams.setPreserveLeading(4);

TokenProfile remoteProfile = new TokenProfile();
remoteProfile.setName("customer-token-remote");
remoteProfile.setClientSide(false);
remoteProfile.setKeyStore(remoteStore.getInfo().getName());
remoteProfile.setKey(remoteStore.getKeyInfo().getName());
remoteProfile.setVerifyLength(0);
remoteProfile.setParams(remoteParams);

profileManager.createProfile(remoteProfile);
```

<Note>
  Set the profile's key store and active key with `setKeyStore()` and `setKey()`. A profile that sets only the key store can fail at runtime with `FAILED TO RETRIEVE ENCRYPTION KEY` because it has no valid active encryption key binding.
</Note>

FF1 requires an HSM-trusted key. Creating an FF1 profile against a retrievable client-side store is rejected.

## Tokenize and detokenize on CryptoHub

```java theme={null}
import com.futurex.fxcl.kmes.token.RemoteTokenize;
import com.futurex.fxcl.kmes.token.RemoteTokenizeParams;

RemoteTokenizeParams tokenizeOperation = new RemoteTokenizeParams(
    server,
    remoteProfile.getName()
);

Cipher remoteTokenize = RemoteTokenize.newCipher(
    Cipher.ENCRYPT_MODE,
    tokenizeOperation
);
String remoteToken = new String(
    remoteTokenize.doFinal(clearValue.getBytes(StandardCharsets.US_ASCII)),
    StandardCharsets.US_ASCII
);

RemoteTokenizeParams detokenizeOperation = new RemoteTokenizeParams(
    server,
    remoteProfile.getName()
);
Cipher remoteDetokenize = RemoteTokenize.newCipher(
    Cipher.DECRYPT_MODE,
    detokenizeOperation
);
String remoteRecovered = new String(
    remoteDetokenize.doFinal(remoteToken.getBytes(StandardCharsets.US_ASCII)),
    StandardCharsets.US_ASCII
);
```

Create a new profile-only `RemoteTokenizeParams` object for detokenization. Do not reuse the object that completed tokenization or pass its `getKey()` value to the detokenization constructor. In FXCL 1.9.5, parameter reuse can return an empty detokenization response. The operation must return a same-length token and recover the original value.

## Delete test profiles and stores

Delete profiles before their key stores:

```java theme={null}
profileManager.deleteProfile("customer-token-local");
profileManager.deleteProfile("customer-token-remote");
storeManager.deleteStore("customer-token-local");
storeManager.deleteStore("customer-token-remote");
```

Do not delete a production profile or key store until all dependent tokens completed the approved retention or migration process.

## Verify it works

For client-side tokenization, require all of these results:

* The profile can be created and retrieved.
* The token differs from the clear value.
* The token length matches the clear-value length.
* Preserved characters remain unchanged.
* Detokenization recovers the original value.

For CryptoHub-backed tokenization, require the same data checks. Also confirm that the Anchor has both required FPE features and that the operation does not return a license or key-retrieval error.

## Troubleshooting

| Signal                              | Cause                                                                                 | Action                                                                                                       |
| ----------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `FAILED TO RETRIEVE ENCRYPTION KEY` | The profile has no valid active key binding, or the key was deleted.                  | Set `TokenProfile.key` to the active key name and confirm the key still exists.                              |
| `FF1 REQUIRES HSM TRUSTED KEYS`     | The FF1 profile targets a retrievable store.                                          | Use a non-retrievable HSM-trusted store for FF1.                                                             |
| `INVALID KEY GROUP`                 | The selected store type does not satisfy the profile execution model.                 | Use a retrievable store for the client-side profile and a non-retrievable store for the server-side profile. |
| `HSM LICENSE MISSING`               | The Anchor does not have the tokenization capability or license.                      | Enable the approved HSM tokenization license on a suitable Anchor, then repeat the operation.                |
| `Detokenization response is empty`  | The application reused the `RemoteTokenizeParams` object that completed tokenization. | Create a new profile-only `RemoteTokenizeParams` object for detokenization.                                  |
| `VERIFICATION NOT SUPPORTED`        | The call requests verification, but the profile has a verification length of zero.    | Configure a nonzero verification length or do not request verification.                                      |

## Version and scope

Client-side FF3-1 and CryptoHub-backed FF1 tokenization were validated with FXCL 1.9.5 and CryptoHub 7.2.0.7. The validated server-side configuration used a non-retrievable AES-256 key store and an Anchor with the FPE and FPE FF1 features enabled.


## Related topics

- [Configure Intune configuration profiles](/Integrations/KMES_Series_3/Endpoint_management/Microsoft_Intune/Configure_Intune_configuration_profiles.md)
- [Configure Excrypt Touch](/Integrations/KMES_Series_3/Secure_printing/Encrypted_File_Transport/Configure_Excrypt_Touch.md)
- [Configure offline Root CA functionality](/Integrations/KMES_Series_3/Certificate_Authority/Futurex_Offline_Root_CA/Configure_offline_Root_CA_functionality.md)
- [Configure OpenVPN Connect to utilize the Futurex PKCS #11 hardware token](/Integrations/CryptoHub/VPN/OpenVPN_Connect/Configure_OpenVPN_Connect_to_utilize_the_Futurex_PKCS_11_hardware_token.md)
- [Configure the JAVA_HOME environment variable](/Integrations/HSM/Key_management/Java_Keytool/Configure_the_JAVA_HOME_environment_variable.md)
