---
title: Hardware secret stores
description: "This topic demonstrates how to use a PKCS #11 device, such as a hardware security module (HSM), to store the keys used to secure communications. IDM supports retrieval of secrets from HSMs either locally or over the network."
component: pingidm
version: 8.1
page_id: pingidm:security-guide:secret-stores-hardware
canonical_url: https://docs.pingidentity.com/pingidm/8.1/security-guide/secret-stores-hardware.html
keywords: ["Security", "Secret Stores", "Keystores", "Truststores", "Encryption", "Keys", "Hardware Security Modules (HSM)", "Secrets", "Mappings", "PKCS #11"]
section_ids:
  hsm-conf: HSM configuration
  hsm-default-keys: HSM default encryption keys
  openidm-hsm-conf: Configure IDM to support an HSM provider
---

# Hardware secret stores

This topic demonstrates how to use a PKCS #11 device, such as a hardware security module (HSM), to store the keys used to secure communications. IDM supports retrieval of secrets from HSMs either locally or over the network.

|   |                                                                                                                                                                                                                                                             |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | On Windows systems using the 64-bit JDK, the Sun PKCS #11 provider is available *only* from JDK version 1.8b49. If you want to use a PKCS #11 device on Windows, use the 32-bit version of the JDK, or upgrade your 64-bit JDK to version 1.8b49 or higher. |

## HSM configuration

This section assumes that you have access to an HSM device (or a software emulation of an HSM device, such as SoftHSM) and that the HSM provider has been configured and initialized.

The command-line examples in this section use SoftHSM for testing purposes. Before you start, set the correct environment variable for the SoftHSM configuration, for example:

```bash
export SOFTHSM2_CONF=/path/to/softhsm/2.0.0/etc/softhsm2.conf
```

Also initialize slot `0` on the provider, with a command similar to the following:

```bash
softhsm2-util --init-token --slot 0 --label "My token 1"
```

This token initialization requests two PINs—an SO PIN and a user PIN. You can use the SO PIN to reinitialize the token. The user PIN is provided to IDM so that it can interact with the token. Remember the values of these PINs because you will use them later in this section.

The PKCS #11 standard uses a configuration file to interact with the HSM device. The following example shows a basic configuration file for SoftHSM:

```properties
name = softHSM
library = /path/to/softhsm/2.0.0/lib/softhsm/libsofthsm2.so
slot = 1
attributes(generate, *, *) = {
   CKA_TOKEN = true
}
attributes(generate, CKO_CERTIFICATE, *) = {
   CKA_PRIVATE = false
}
attributes(generate, CKO_PUBLIC_KEY, *) = {
   CKA_PRIVATE = false
}
attributes(*, CKO_SECRET_KEY, *) = {
   CKA_PRIVATE = false
   CKA_EXTRACTABLE = true
}
```

Your HSM configuration file *must* include at least the following settings:

* `name`

  A suffix to identify the HSM provider. This example uses the `softHSM` provider.

* `library`

  The path to the PKCS #11 library.

* `slot`

  The slot number to use, specified as a string. Make sure that the slot you specify here has been initialized on the HSM device.

The `attributes` specify additional PKCS #11 attributes that are set by the HSM. For a complete list of these attributes, refer to the [PKCS #11 Reference](https://docs.oracle.com/en/java/javase/21/security/pkcs11-reference-guide.html).

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | If you are using the JWT Session Module, you *must* set `CKA_EXTRACTABLE = true` for secret keys in your HSM configuration file. For example:```properties
attributes(*, CKO_SECRET_KEY, *) = {
   CKA_PRIVATE = false
   CKA_EXTRACTABLE = true
}
```The HSM provider must allow secret keys to be extractable because the authentication service serializes the JWT Session Module key and passes it to the authentication framework as a base 64-encoded string. |

## HSM default encryption keys

When IDM first starts up, it generates a number of encryption keys required to encrypt specific data. If you are using an HSM provider, you must generate these keys manually. The secret keys must use an HMAC algorithm.

|   |                                                                                                |
| - | ---------------------------------------------------------------------------------------------- |
|   | This procedure assumes that your HSM configuration file is located at `/path/to/hsm/hsm.conf`. |

1. The `openidm-sym-default` key is the default symmetric key required to encrypt the configuration. The following command generates that key in the HSM provider. The `-providerArg` must point to the HSM configuration file described in [HSM configuration](#hsm-conf).

   ```
   keytool \
   -genseckey \
   -alias openidm-sym-default \
   -keyalg HmacSHA256 \
   -keysize 256 \
   -keystore NONE \
   -storetype PKCS11 \
   -providerClass sun.security.pkcs11.SunPKCS11 \
   -providerArg /path/to/hsm/hsm.conf
   Enter keystore password:
   ```

   Enter the password of your HSM device. If you are using SoftHSM, enter your user PIN as the keystore password.

2. The `openidm-selfservice-key` is used to encrypt certain managed user passwords and other sensitive data. Generate the `openidm-selfservice-key` key:

   ```
   keytool \
   -genseckey \
   -alias openidm-selfservice-key \
   -keyalg HmacSHA256 \
   -keysize 256 \
   -keystore NONE \
   -storetype PKCS11 \
   -providerClass sun.security.pkcs11.SunPKCS11 \
   -providerArg /path/to/hsm/hsm.conf
   Enter keystore password: user PIN
   ```

   Enter the password of your HSM device. If you are using SoftHSM, enter your user PIN as the keystore password.

3. The `openidm-jwtsessionhmac-key` is used by the [JWT session module](../auth-guide/authentication.html#jwt-session-module) to encrypt JWT session cookies. Generate the JWT session module key:

   ```
   keytool \
   -genseckey \
   -alias openidm-jwtsessionhmac-key \
   -keyalg HmacSHA256 \
   -keysize 256 \
   -keystore NONE \
   -storetype PKCS11 \
   -providerClass sun.security.pkcs11.SunPKCS11 \
   -providerArg /path/to/hsm/hsm.conf
   Enter keystore password: user PIN
   ```

4. The `openidm-localhost` certificate is used to support SSL/TLS. Generate the certificate:

   ```
   keytool \
   -genkey \
   -alias openidm-localhost \
   -keyalg RSA \
   -keysize 2048 \
   -keystore NONE \
   -storetype PKCS11 \
   -providerClass sun.security.pkcs11.SunPKCS11 \
   -providerArg /path/to/hsm/hsm.conf
   Enter keystore password: user PIN
   What is your first and last name?
     [Unknown]:  localhost
   What is the name of your organizational unit?
     [Unknown]:
   What is the name of your organization?
     [Unknown]:  OpenIDM Self-Signed Certificate
   What is the name of your City or Locality?
     [Unknown]:
   What is the name of your State or Province?
     [Unknown]:
   What is the two-letter country code for this unit?
     [Unknown]:
   Is CN=localhost, OU=Unknown, O=OpenIDM Self-Signed Certificate, L=Unknown, ST=Unknown, C=Unknown correct?
     [no]:  yes
   ```

5. The `selfservice` certificate secures requests from the end-user UI. Generate the certificate:

   ```
   keytool \
   -genkey \
   -alias selfservice \
   -keyalg RSA \
   -keysize 2048 \
   -keystore NONE \
   -storetype PKCS11 \
   -providerClass sun.security.pkcs11.SunPKCS11 \
   -providerArg /path/to/hsm/hsm.conf
   Enter keystore password: user PIN
   What is your first and last name?
     [Unknown]:  localhost
   What is the name of your organizational unit?
     [Unknown]:
   What is the name of your organization?
     [Unknown]:  OpenIDM Self Service Certificate
   What is the name of your City or Locality?
     [Unknown]:
   What is the name of your State or Province?
     [Unknown]:
   What is the two-letter country code for this unit?
     [Unknown]:
   Is CN=localhost,O=OpenIDM Self Service Certificate,OU=None,L=None,ST=None,C=None?
     [no]:  yes
   ```

   |   |                                                                                                                           |
   | - | ------------------------------------------------------------------------------------------------------------------------- |
   |   | The end-user UI is not bundled with PingIDM. Learn more in [Install the end-user UI](../setup-guide/idm-enduser-ui.html). |

6. If you are *not* using the HSM provider for the truststore, you must add the certificates generated in the previous two steps to the default IDM truststore.

   If you *are* using the HSM provider for the truststore, you can skip this step.

   To add the `openidm-localhost` certificate to the IDM truststore, export the certificate from the HSM provider, then import it into the truststore:

   ```
   keytool \
   -export \
   -alias openidm-localhost \
   -file exportedCert \
   -keystore NONE \
   -storetype PKCS11 \
   -providerClass sun.security.pkcs11.SunPKCS11 \
   -providerArg /path/to/hsm/hsm.conf
   Enter keystore password: user PIN
   Certificate stored in file exportedCert keytool \
   -import \
   -alias openidm-localhost \
   -file exportedCert \
   -keystore /path/to/openidm/security/truststore
   Enter keystore password: changeit
   Owner: CN=localhost, OU=Unknown, O=OpenIDM Self-Signed Certificate, L=...
   Issuer: CN=localhost, OU=Unknown, O=OpenIDM Self-Signed Certificate, L=...
   Serial number: 5d2554bd
   Valid from: Fri Aug 19 13:11:54 SAST 2016 until: Thu Nov 17 13:11:54 SAST 2016
   Certificate fingerprints:
   	 MD5:  F1:9B:72:7F:7B:79:58:29:75:85:82:EC:79:D8:F9:8D
   	 SHA1: F0:E6:51:75:AA:CB:14:3D:C5:E2:EB:E5:7C:87:C9:15:43:19:AF:36
   	 SHA256: 27:A5:B7:0E:94:9A:32:48:0C:22:0F:BB:7E:3C:22:2A:64:B5:45:24:14:70:...
   	 Signature algorithm name: SHA256withRSA
   	 Version: 3

   Extensions:

   #1: ObjectId: 2.5.29.14 Criticality=false
   SubjectKeyIdentifier [
   KeyIdentifier [
   0000: 7B 5A 26 53 61 44 C2 5A   76 E4 38 A8 52 6F F2 89  .Z&SaD.Zv.8.Ro..
   0010: 20 04 52 EE                                         .R.
   ]
   ]
   Trust this certificate? [no]:  yes
   Certificate was added to keystore
   ```

   The default truststore password is changeit.

## Configure IDM to support an HSM provider

To enable IDM to use an HSM provider, make the following configuration changes:

1. In your secret store configuration (`conf/secrets.json` ), change the `mainKeyStore` and `mainTrustStore` to reference the HSM. For example:

   ```json
   {
     "stores": [
       {
         "name": "mainKeyStore",
         "class": "org.forgerock.openidm.secrets.config.HsmBasedStore",
         "config": {
           "storetype": "&{openidm.keystore.type|PKCS11}",
           "providerName": "&{openidm.keystore.provider|SunPKCS11-softHSM}",
           "storePassword": "&{openidm.keystore.password|changeit}",
           "mappings": [
             {
               "secretId" : "idm.default",
               "types": [ "ENCRYPT", "DECRYPT" ],
               "aliases": [ "&{openidm.config.crypto.alias|openidm-sym-default}" ]
             },
             {
               "secretId" : "idm.config.encryption",
               "types": [ "ENCRYPT", "DECRYPT" ],
               "aliases": [ "&{openidm.config.crypto.alias|openidm-sym-default}" ]
             },
             {
               "secretId" : "idm.password.encryption",
               "types": [ "ENCRYPT", "DECRYPT" ],
               "aliases": [ "&{openidm.config.crypto.alias|openidm-sym-default}" ]
             },
             {
               "secretId" : "idm.jwt.session.module.encryption",
               "types": [ "ENCRYPT", "DECRYPT" ],
               "aliases": [ "&{openidm.https.keystore.cert.alias|openidm-localhost}" ]
             },
             {
               "secretId" : "idm.jwt.session.module.signing",
               "types": [ "SIGN", "VERIFY" ],
               "aliases": [ "&{openidm.config.crypto.jwtsession.hmackey.alias|openidm-jwtsessionhmac-key}" ]
             },
             {
               "secretId" : "idm.selfservice.signing",
               "types": [ "SIGN", "VERIFY" ],
               "aliases": [ "selfservice" ]
             },
             {
               "secretId" : "idm.selfservice.encryption",
               "types": [ "ENCRYPT", "DECRYPT" ],
               "aliases": [ "&{openidm.config.crypto.selfservice.sharedkey.alias|openidm-selfservice-key}" ]
             }
           ]
         }
       },
       {
         "name": "mainTrustStore",
         "class": "org.forgerock.openidm.secrets.config.HsmBasedStore",
         "config": {
           "storetype": "&{openidm.keystore.type|PKCS11}",
           "providerName": "&{openidm.keystore.provider|SunPKCS11-softHSM}",
           "storePassword": "&{openidm.keystore.password|changeit}",
           "mappings": [
           ]
         }
       }
     ],
     "populateDefaults": false
   }
   ```

   |   |                                                                                                                           |
   | - | ------------------------------------------------------------------------------------------------------------------------- |
   |   | The `"populateDefaults": false` turns off the default key generation. This setting is *required* for an HSM key provider. |

2. In the IDM Java security file (`conf/java.security` ), Specify the location of your PKCS #11 configuration file. For example:

   ```properties
   security.provider.14=SunPKCS11 /path/to/pkc11/config/pkcs11.conf
   ```

   Templates for the `pkcs11.conf` file are included in your PKCS package.

   You should now be able to start IDM with the keys in the HSM provider.
