---
title: "Keep your keys in an HSM or in your customer's own key service"
description: "Point keys at a PKCS#11 or KMIP hardware module, state a FIPS claim only a certificate supports, and let a customer hold the key that wraps their data."
section: "guides"
status: "Planned for 1.2"
spec: "hsm-keys"
canonical: "https://mainsdk.dev/docs/guides/use-hsm-keys"
updated: "2026-10-28"
---

# Keep your keys in an HSM or in your customer's own key service

> Point keys at a PKCS#11 or KMIP hardware module, state a FIPS claim only a certificate supports, and let a customer hold the key that wraps their data.

Status: Planned for 1.2 · Canonical: https://mainsdk.dev/docs/guides/use-hsm-keys · Updated: 2026-10-28

You will move the wrapping key of `keys` into a hardware security module, and let one customer revoke access to their data by disabling their own key. It takes about 30 minutes plus your HSM's setup time.

## You need

- A MainSDK app with `keys` configured (see [Erase a user with keys](https://mainsdk.dev/docs/guides/erase-a-user-with-keys)).
- A PKCS#11 module (a Thales Luna, Entrust nShield, Utimaco, AWS CloudHSM, Azure Managed HSM or GCP Cloud HSM client library, or SoftHSM for testing) or a KMIP server.

## 1. Point `keys` at the module

```yaml title="main.yaml"
keys:
  driver: pkcs11
  module: /opt/hsm/libpkcs11.so
  slot: 0
  pin: secret:HSM_PIN
  key: label:app-wrap
```

The PIN must be a `secret:` reference. Keys are created non-extractable, one per version, named `<label>.v1`, `<label>.v2`, so a rotation never makes old data unreadable. MainSDK has no PKCS#11 binding of its own: your deployment supplies a `Pkcs11Session` over the vendor library, and `pkcs11Kms` from `mainsdk/hsm` wraps it. For a KMIP server use `kmipKms` and `kmipTlsTransport` from `mainsdk/kmip`.

## 2. Check what the app will say

`npx mainsdk info --json` lists the key service, the module and a FIPS label only when `keys.fips` names a certificate. MainSDK never claims FIPS validation for a vendor on its own; the claim comes from your certificate number.

```yaml title="main.yaml"
keys:
  fips: { standard: "140-3", level: 3, certificate: "4567" }
```

## 3. Let a customer hold the key

`CustomerKeys` from `mainsdk/keys-customer` wraps one organisation's data with a key in their Google Cloud EKM or AWS XKS. It reads the key's state at least every five minutes. When the customer disables or revokes the key, reads of their data fail closed with `MAIN-KEYS-0025` and an audit event names the organisation and the key URI.

## Check it worked

Run `npx mainsdk check`. Then wrap and unwrap a value in a test against `softHsm` from `@mainsdk/testing`; a second unwrap after you destroy the key fails.
