This guide provides complete instructions for integrating the Thales Luna 7 HSM with Ripple Custody. It covers both form factors of the Luna 7 A-series — the Luna Network HSM 7 appliance and the Luna PCIe HSM 7 (A700) card. Both are FIPS 140-2 Level 3 certified hardware security modules that provide hardware-based key protection for your notary and vault components.
Before you begin: This guide assumes you have completed Installation environment setup and are ready to configure your HSM for use with Ripple Custody.
This guide covers both form factors of the Thales Luna 7 A-series HSM. Both use an identical PKCS#11 cryptographic interface and Luna 7.x firmware — only the transport layer differs, so the Ripple Custody integration is the same for both.
| Attribute | Luna Network HSM 7 | Luna PCIe HSM 7 (A700) |
|---|---|---|
| Connection | NTLS (network transport layer security), NetClient=1 | Local PCI bus (card installed in the host server) |
| Crypto interface | PKCS#11 | PKCS#11 (identical) |
| Firmware | Luna 7.x | Luna 7.x (identical) |
| Form factor | Standalone network appliance | PCIe card in host server |
Shared configuration: Because the cryptographic interface and firmware are identical, the HSM policies, scalable key storage (SKS) setup, key-derivation behavior, and Ripple Custody configuration described in this guide apply to both form factors. The only differences are the steps that set up the network transport — network ACLs, NTLS/mTLS certificates, and port 1792 — which do not apply to the locally-installed PCIe card (A700).
The Ripple Custody luna KMS provider connects through the Luna client library (libCryptoki2.so) and relies on Thales BIP32/SLIP-10 vendor extensions (CKK_BIP32, CKM_BIP32_MASTER_DERIVE, CA_SIMInsert/CA_SIMExtract, and CA_Bip32ExportPublicKey), so the supported hardware is the Luna 7 generation, which exposes these extensions.
| Requirement | Detail |
|---|---|
| Supported models | Luna Network HSM 7: A700, A750, A790, S700, S750, S790. |
| Minimum firmware and client | SLIP-10 derivation (secp256k1, ed25519, P-256) requires HSM firmware 7.8.7 or later and Luna client 10.7.1 or later. |
| Certification | FIPS 140-2 and 140-3 Level 3. |
Ripple Custody uses Luna HSM in two critical components:
- Notary: Uses the master signing key in the HSM to authenticate governance operations
- Vault: Uses the master encryption key in the HSM to protect account private keys
Key generation flow:
- During account creation, the vault requests key generation from the HSM
- The HSM generates the private key internally using its secure random number generator
- The private key is encrypted using the HSM master key via PKCS#11
- The encrypted key (SKS blob) is stored in the Ripple Custody database
- The HSM master key and plaintext private keys never leave the HSM hardware
The diagram above shows the Network HSM topology, where the notary and vault reach the HSM over mTLS on port 1792. For the PCIe HSM (A700), the card is installed directly in the host server and accessed over the local PCI bus, so there is no network hop between the Ripple Custody components and the HSM.
Before starting, ensure you have:
From Thales Luna HSM:
- One of the following Luna 7 A-series HSMs:
- Thales Luna Network HSM 7 appliance (physical or virtual), or
- Thales Luna PCIe HSM 7 (A700) card installed in the host server
- Firmware version:
- 7.7.1 or higher for BIP32 derivation
- 7.8.7 or higher for SLIP10 derivation (recommended)
- Application software 7.8.5-300 (for SLIP10)
- Network HSM only: network connectivity on port 1792 (typical). The PCIe HSM (A700) is accessed locally over the PCI bus and does not use network transport.
- Limited Crypto Officer (LCO) role configured on the assigned partition and mapped to the corresponding slot
- Slot number and partition PIN, which Ripple Custody uses to open a session on the partition
- Network HSM only: NTLS certificate bundle — client certificate, client private key, and HSM server certificate
From your infrastructure:
- Linux client machine for HSM administration (LunaCM client)
- Network access from Kubernetes cluster to HSM on port 1792
- Firewall rules allowing bidirectional traffic
From Ripple:
- Ripple Custody Helm charts (version 1.16+ for SLIP10)
- Access to the Ripple container registry (
metaco.azurecr.io)
CRITICAL: The following policies are destructive and will erase existing HSM data when enabled. Enable these policies BEFORE storing any production keys.
HSM-level policies (apply to entire HSM):
- Policy 6: Allow masking (required for SKS)
- Policy 12: Allow non-FIPS algorithms (required for vault operations)
Partition-level policies (apply to each partition):
- Policy 22: Allow activation
- Policy 23: Allow auto-activation
- Policy 41: Partition version
- Policy 43: Allow non-FIPS algorithms
The vault automatically detects HSM capabilities at startup and selects the appropriate derivation scheme:
| Scheme | Supported Curves | Supported Blockchains | Firmware Required |
|---|---|---|---|
| SLIP10 (preferred) | secp256k1, Ed25519 | All blockchains (Bitcoin, Ethereum, XRPL, Solana, Algorand, etc.) | 7.8.7+ |
| BIP32 (fallback) | secp256k1 only | Bitcoin, Ethereum, XRPL, Litecoin, Polygon | 7.7.1+ |
Automatic selection: The vault will automatically choose SLIP10 if the HSM firmware supports it (7.8.7+), otherwise it defaults to BIP32. No manual configuration is required.
By default, Ripple Custody vaults use hierarchical-deterministic (HD) key derivation (SLIP10). You can optionally configure a vault to use random keys instead, but this is not the recommended default.
Random key backups: The random key strategy has implications for backups. Unlike HD-derived keys, random keys cannot be regenerated from a single seed, so their backups must be managed manually and periodically reconducted. Use HD derivation (the default) unless you have a specific requirement for random keys.
- Thales Luna Network HSM 7 documentation
- BIP32 mechanism support
- Partition administration guide
- High-availability groups
This section covers the vendor-specific setup required to prepare your Luna HSM for use with Ripple Custody. Detailed step-by-step commands are available in the Thales Luna Network HSM 7 documentation.
Customer responsibility: Your infrastructure team performs HSM initialization. Ripple Custody only requires that the HSM be configured with the settings described below before proceeding to Ripple Custody configuration.
Complete the following using Thales documentation:
- Physical deployment: Rack, power, and network-connect the Luna HSM appliance
- Initial setup: Complete the setup wizard via serial console or web interface
- Network configuration: Assign a static IP address accessible from your Kubernetes cluster
- Firmware verification: Confirm firmware is 7.7.1+ (BIP32) or 7.8.7+ (SLIP10)
WARNING: Enabling these policies will destroy all existing keys and data on the HSM. Perform this step on a freshly initialized HSM or after backing up all existing keys.
HSM-level policies (required for Ripple Custody):
| Policy | Name | Required Value | Purpose |
|---|---|---|---|
| 6 | Allow masking | 1 (enabled) | Required for Scalable Key Storage (SKS) |
| 12 | Allow non-FIPS algorithms | 1 (enabled) | Required for vault operations |
Use hsm changePolicy and hsm showPolicies commands to configure and verify.
SKS allows you to store unlimited keys while maintaining hardware-level security. The SKS master key (SMK) remains in the HSM, while encrypted key blobs are stored externally in the Ripple Custody database.
Create one partition for Ripple Custody:
- Partitions must be type V1 for SKS support
- Assign a strong password for the partition
- One partition per application is the standard design (partitions are expensive)
Enable partition-level policies on the partition:
| Policy | Name | Required Value | Purpose |
|---|---|---|---|
| 22 | Allow activation | 1 (enabled) | Required for partition access |
| 23 | Allow auto-activation | 1 (enabled) | Required for automatic login |
| 41 | Partition version | 1 (enabled) | Required for SKS |
| 43 | Allow non-FIPS algorithms | 1 (enabled) | Required for blockchain operations |
Assign client access by registering the Kubernetes client with partition access using client assignPartition.
HA groups provide redundancy by synchronizing keys across multiple HSM partitions. If one HSM fails, the other continues to provide cryptographic services.
Requirements:
- At least 2 Luna HSM appliances (one partition per HSM for replication)
- Matching partition configurations on each HSM
Configuration:
- Use
lunacmon your Linux client to create HA groups usinghagroup createGroup - Add additional HSM partitions as members using
hagroup addMember - Verify HA configuration is saved to
/etc/Chrystoki.conf
Key Chrystoki.conf settings:
HAOnly = 1ensures PKCS#11 operations only use HA groupsVirtualTokenActiveRecovery = activeEnhancedenables automatic failover
See Thales HA configuration guide for detailed instructions.
PCIe HSM (A700): Skip this step. The card communicates with its host over the local PCI bus, so there is no network ACL, NTLS/mTLS certificate exchange, or port 1792 to configure. Instead, confirm the card is visible as a local slot using slot list in lunacm.
Network ACL: Add your Kubernetes cluster node IP range to the HSM's network ACL using network add.
mTLS Certificates: Luna HSM uses mutual TLS (mTLS) for secure communication.
- Generate client certificate on your Linux client using
vtl createCert - Register client with HSM using
client registerand assign partition access - Download HSM server certificate for client-side verification.
You will need three files for Ripple Custody configuration:
- Client certificate (
client.pem) - Client private key (
client.key) - HSM server certificate (
server.pem)
Before proceeding to Ripple Custody configuration, verify:
- Network connectivity: Port 1792 is reachable from Kubernetes nodes
- PKCS#11 connectivity:
vtl verifyshows your HA groups - Authentication: Can login to partitions with configured PINs
- Cryptographic operations: Basic operations execute without errors
Checkpoint: If vtl verify shows your HA groups and you can successfully login to partitions, your Luna HSM is properly configured and ready for Ripple Custody integration.
Now that your Luna HSM is initialized, configure Ripple Custody to use it for the notary and vault components.
PCIe HSM (A700): The network transport fields shown in the examples below — host, port, and the client/server certificate blocks — do not apply, because the card is accessed locally over the PCI bus rather than over NTLS. Configure the same kms_luna platform with your partition slot and pin. If you are unsure which fields your deployment requires for the PCIe form factor, contact Ripple.
You'll need to provide three certificate files in your Helm configuration:
- Client certificate (
<client-hostname>.pem): Authenticates Ripple Custody to the HSM - Client private key (
<client-hostname>Key.pem): Private key for client certificate - Server certificate (
server.pem): HSM's server certificate for verification
Convert certificates to base64 for Helm values:
# Client certificate
$ cat /usr/safenet/lunaclient/cert/client/<client-hostname>.pem | base64 -w 0 > client-cert.b64
# Client private key
$ cat /usr/safenet/lunaclient/cert/client/<client-hostname>Key.pem | base64 -w 0 > client-key.b64
# Server certificate
$ cat /usr/safenet/lunaclient/cert/server/server.pem | base64 -w 0 > server-cert.b64Edit your production.yaml Helm values file to configure the notary component:
# production.yaml
components:
notary:
enabled: true
# Platform selection
platform: kms_luna
# Luna HSM configuration
kms_luna:
host: "luna-hsm.example.com" # Luna HSM hostname or IP
port: "1792" # Luna HSM port (must be string)
slot: "0" # HA group slot number (0 for first HA group)
pin: "notary-partition-password" # Partition password
# Client certificate (for mTLS)
client:
certificate: |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKZ...
-----END CERTIFICATE-----
key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0...
-----END PRIVATE KEY-----
# Server certificate (Luna HSM)
server:
certificate: |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKZ...
-----END CERTIFICATE-----Security best practice: Do NOT store the partition PIN directly in production.yaml. Use Kubernetes Secrets or an external secrets manager (HashiCorp Vault, Conjur) to inject the PIN at runtime.
Using Kubernetes Secrets for PIN:
# Create secret for Notary PIN
kubectl create secret generic notary-luna-pin \
--namespace custody-core \
--from-literal=pin='notary-partition-password'
# Reference secret in production.yamlcomponents:
notary:
platform: kms_luna
kms_luna:
# ... other config ...
pinSecretRef: notary-luna-pin # Reference to Kubernetes secretConfigure the vault component to use Luna HSM for key encryption:
# production.yaml
harmonize:
vaults:
"00000000-0000-0000-0000-000000000000": # Default vault UUID
enabled: true
# Platform selection
platform: kms_luna
# Notary public key (obtained after Notary initialization - see Step 4)
notary_public_key: "ed25519:50692dfa472f013e2f87e5d210be40cefe178e33787be4688d5da0afe06ed149"
# Luna HSM configuration
kms_luna:
host: "luna-hsm.example.com"
port: "1792"
slot: "0" # Same partition as Notary (one partition per application)
pin: "partition-password"
client:
certificate: |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKZ...
-----END CERTIFICATE-----
key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0...
-----END PRIVATE KEY-----
server:
certificate: |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKZ...
-----END CERTIFICATE-----Using Kubernetes Secrets for vault PIN:
# Create secret for Vault PIN (same partition as Notary)
kubectl create secret generic vault-luna-pin \
--namespace custody-vault \
--from-literal=pin='partition-password'Here's a complete example showing both notary and vault configured with Luna HSM:
# production.yaml - Complete Luna HSM Configuration
# Global settings
harmonize:
repository:
base: "my-registry.example.com/harmonize"
urls:
base: "custody.example.com"
tls: true
# Notary configuration
components:
notary:
enabled: true
platform: kms_luna
kms_luna:
host: "luna-hsm.example.com"
port: "1792"
slot: "0"
pin: "${NOTARY_PIN}" # Injected from secrets manager
client:
certificate: |
-----BEGIN CERTIFICATE-----
${LUNA_CLIENT_CERT}
-----END CERTIFICATE-----
key: |
-----BEGIN PRIVATE KEY-----
${LUNA_CLIENT_KEY}
-----END PRIVATE KEY-----
server:
certificate: |
-----BEGIN CERTIFICATE-----
${LUNA_SERVER_CERT}
-----END CERTIFICATE-----
# Vault configuration (uses same partition as Notary)
harmonize:
vaults:
"00000000-0000-0000-0000-000000000000":
enabled: true
platform: kms_luna
notary_public_key: "ed25519:${NOTARY_PUBLIC_KEY}" # Set after Notary initialization
kms_luna:
host: "luna-hsm.example.com"
port: "1792"
slot: "0" # Same partition as Notary
pin: "${PARTITION_PIN}"
client:
certificate: |
-----BEGIN CERTIFICATE-----
${LUNA_CLIENT_CERT}
-----END CERTIFICATE-----
key: |
-----BEGIN PRIVATE KEY-----
${LUNA_CLIENT_KEY}
-----END PRIVATE KEY-----
server:
certificate: |
-----BEGIN CERTIFICATE-----
${LUNA_SERVER_CERT}
-----END CERTIFICATE-----For production deployments, store sensitive credentials (PKCS#11 PIN, certificates) in an external secrets manager rather than directly in Helm values or Kubernetes secrets.
Production best practice: Never store sensitive credentials in plaintext YAML files or Git repositories.
Recommended approaches for Luna HSM credentials:
| Approach | Description | Use Case |
|---|---|---|
| External Secrets Operator (ESO) | Sync secrets from HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault to Kubernetes | Enterprise environments with centralized secret management |
| HashiCorp Vault Agent Injector | Inject secrets directly into pods at runtime | Organizations already using Vault Agent |
| AWS Secrets Manager | Store and rotate secrets in AWS | AWS-native deployments |
For complete setup instructions, see Advanced secret management.
When using external secret management, reference the secret in your Helm values:
components:
notary:
platform: kms_luna
kms_luna:
existingSecret: "notary-luna-credentials" # ESO-managed secretAfter configuring your Helm values, follow these steps to deploy and verify the integration.
Before deploying Ripple Custody components, verify network connectivity to the Luna HSM:
# Test network connectivity from a Kubernetes node or test pod
nc -zv luna-hsm.example.com 1792
# Expected output:
# Connection to luna-hsm.example.com 1792 port [tcp/*] succeeded!
# Verify PKCS#11 connectivity using vtl (from Luna client machine)
vtl verify
# Expected output should show your HA groupsIMPORTANT: Verify HSM connectivity before deploying components. Troubleshooting connectivity issues after deployment is more difficult.
# Deploy Notary first (Vault needs Notary's public key)
helm upgrade --install harmonize ./harmonize-custody \
--namespace custody-core \
--create-namespace \
-f production.yaml \
--set components.vault.enabled=false \
--set components.indexers.enabled=false
# Wait for Notary to be ready
kubectl wait --for=condition=ready pod \
-l app=notary \
-n custody-core \
--timeout=300s
# Check KMS Connect sidecar logs to verify HSM connection
kubectl logs -n custody-core deployment/harmonize-notary -c kms-connect --tail=100
# Expected output should show:
# - Successful PKCS#11 connection to Luna HSM
# - HA group detection
# - Partition login successAfter notary is deployed and connected to the HSM, initialize it and retrieve the public key. For detailed API instructions, see the Installation and initialization guide.
# Check Notary logs for successful initialization
kubectl logs -n custody-core deployment/harmonize-notary -c notary-core --tail=50
# Retrieve Notary public key via the System Properties API
# See: API Reference > System Properties > Get System PropertiesSave the notary public key - you'll need it for the vault configuration.
Update production.yaml with the notary public key and deploy vault:
# Deploy Vault
helm upgrade --install harmonize ./harmonize-custody \
--namespace custody-core \
-f production.yaml
# Wait for Vault to be ready
kubectl wait --for=condition=ready pod \
-l app=vault \
-n custody-vault \
--timeout=300s
# Verify Vault HSM connectivity
kubectl logs -n custody-vault deployment/harmonize-vault -c kms-connect --tail=100Create a test blockchain account to verify the complete integration:
- Register the vault via the Web UI: Administration > Vaults > Create a vault
- Create a test account via the Web UI: Accounts > Create account
- Verify account creation succeeded with a valid blockchain address
This confirms:
- vault can communicate with Luna HSM
- Key derivation is working (BIP32/SLIP10)
- SKS blob encryption/storage is functional
For detailed instructions on account creation, see the Create an account guide.
| Error Message | Cause | Solution |
|---|---|---|
CKR_DEVICE_ERROR | HSM not reachable | Check network connectivity and firewall rules for port 1792 |
CKR_PIN_INCORRECT | Wrong partition password | Verify PIN in Kubernetes secret matches HSM partition password |
CKR_TOKEN_NOT_PRESENT | HA group not configured | Configure HA group and verify Chrystoki.conf |
CKR_SESSION_HANDLE_INVALID | Session timeout | Increase session timeout or check HSM load |
SSL handshake failed | Certificate mismatch | Regenerate certificates and verify mTLS configuration |
BIP32_DERIVE not supported | Firmware too old | Upgrade to firmware 7.7.1+ |
SLIP10_DERIVE not supported | Firmware too old | Upgrade to firmware 7.8.7+ |
For detailed troubleshooting, see the Thales Luna Network HSM 7 documentation.
For production-ready Luna HSM deployments, implement the following patterns. See Production best practices for detailed instructions that apply to all KMS platforms.
| Practice | Luna HSM Implementation |
|---|---|
| High Availability | Configure Luna HA groups with hagroup createGroup and add multiple HSM members |
| Namespace Segmentation | Separate Luna partitions per namespace/vault for isolation |
| Monitoring | Use lunacm commands (hsm show, partition show, hagroup show) plus Prometheus metrics |
| Certificate Rotation | Generate new certificates with vtl createCert, update Kubernetes secrets, perform rolling update |
| Backup | Use partition backup command, store backups securely, test quarterly |
| HA Sync | Regularly verify HA group synchronization with hagroup synchronize |
Luna HSM HA group configuration:
- Use
hagroup createGroupto create HA groups for notary and vault partitions - Configure
HAOnly = 1inChrystoki.confto ensure operations only use HA groups - Set
VirtualTokenActiveRecovery = activeEnhancedfor automatic failover
After successfully integrating Luna HSM with Ripple Custody:
Backup HSM keys: Implement backup procedures for SKS master keys.
- Back up SMK to a secondary Luna HSM
- Store backup HSM in secure, off-site location
- Document recovery procedures
Production hardening:
- Enable HSM audit logging
- Configure HSM monitoring and alerting
- Implement HSM access controls (role-based access)
- Schedule regular HSM firmware updates
Disaster recovery planning:
- Document HSM replacement procedures
- Test HA failover scenarios
- Create runbooks for common HSM issues
- Establish HSM vendor support contacts
Security audit:
- Review HSM policies and partition configurations
- Audit certificate expiration dates
- Verify network ACLs are restrictive
- Test backup and recovery procedures
Review Production best practices for namespace segmentation, HA patterns, and monitoring
For enhanced security, you can deploy the vault in an AWS Nitro enclave to connect your Luna HSM to Ripple Custody.
These steps require support assistance from Ripple to complete. For more information, contact your Ripple liaison.
To configure a Luna HSM with AWS Nitro enclave to work with Ripple Custody, you need:
From Ripple:
- An AWS enclave Terraform script
- The
encrypt-clitool
From your Ripple Custody environment:
- The notary messaging public key, retrieved with a call to the List system properties API operation.
Create your enclave contract, in a format similar to the following Podman Play YAML file:
# Enclave configuration (required) kind: Enclave apiVersion: v1 # # specify if enclaves requires disk storage via NBD requireVarDisk: false requireDataDisk: false # # base64 encoded disk encryption keys, min=32 byte. If empty keys are auto-generated on every boot! # Example: dd if=/dev/random bs=1 count=32 | base64 encryptionKeyVar: <your-encryption-key> encryptionKeyData: <your-encryption-key> # # auths: login credentials for private container registries (optional) auths: - registry: metaco.azurecr.io username: <your-username> password: <your-password> hostname: enclave-vault-1 --- # POD definition (required) # Pod configuration map (optional) kind: ConfigMap apiVersion: v1 metadata: name: config data: --- kind: Pod apiVersion: v1 metadata: name: vault-pod spec: volumes: - name: config configMap: name: config containers:
For help to define an appropriate pod structure for the current release, contact Ripple.
- Using
encrypt-cli, generate the enclave contract token. - Run the Terraform script with the contract token created in step 2 as an input parameter.
Congratulations! You have successfully integrated Thales Luna HSM with Ripple Custody. Your notary and vault components are now protected by FIPS 140-2 Level 3 certified hardware security.