To copy a key from one hardware security module (HSM) to another, export the key from the source HSM and import it into the destination HSM. This topic covers how to copy symmetric and asymmetric keys between two HSMs.
Applicable HSM types
General Virtual Security Modules (GVSMs) validated by Federal Information Processing Standards (FIPS).
When to copy keys manually
Copy keys manually when the two HSMs do not belong to the same cluster and automatic key synchronization is not supported.
Keys within the same cluster are synchronized automatically. No manual copying is needed.
Prerequisites
Before you begin, ensure that you have:
The
hsm_proxyHSM client proxy running. See Getting started with Cloud Hardware Security Module for setup instructionsThe
key_mgmt_toolCLI installed. See key_mgmt_tool for more information
Log in to key_mgmt_tool
Before performing any operations, log in as a crypto user (CU):
$/opt/hsm/bin/key_mgmt_tool
Command: loginHSM -u CU -s <yourCuUserName> -p <yourCuUserPassword>Replace /opt/hsm/bin/key_mgmt_tool with the actual path, and replace <yourCuUserName> and <yourCuUserPassword> with your CU credentials.
How it works
The copy process uses key wrapping to move key material securely between HSMs:
In HSM B, generate an RSA key pair as the wrapping key and export its public key.
In HSM A, import the RSA public key from HSM B and use it to wrap (encrypt) the key you want to copy.
Transfer the wrapped key file to HSM B and unwrap it there using the RSA private key.
For asymmetric keys, you also export and import the public key separately.
Copy a symmetric key
This example copies an AES-256 symmetric key from HSM A to HSM B, using an RSA-2048 wrapping key with RSA-OAEP (SHA-256).
Step 1: In HSM B — create and export a wrapping key
Generate an RSA key pair to use as the wrapping key.
Parameter Description -mKey length in bits -ePublic exponent. Must be an odd number between 65537 and 2^31-1 -lKey label Command: genRSAKeyPair -m 2048 -e 65537 -l rsa_wrapping_keyExpected output:
Cfm3GenerateKeyPair returned: 0x00 : HSM Return: SUCCESS Cfm3GenerateKeyPair: public key handle: 33 private key handle: 32 Cluster Status: Node id 0 status: 0x00000000 : HSM Return: SUCCESSExport the RSA public key to a file.
Parameter Description -kHandle of the public key to export -outOutput file name Command: exportPubKey -k 33 -out rsa_wrapping_key.pubExpected output:
PEM formatted public key is written to rsa_wrapping_key.pub Cfm3ExportPubKey returned: 0x00 : HSM Return: SUCCESS
Transfer rsa_wrapping_key.pub to the HSM A environment.
Step 2: In HSM A — wrap the symmetric key
Generate the symmetric key. Skip this step if the key already exists.
Parameter Description -tKey type: 16= GENERIC_SECRET,21= 3DES,31= AES-sKey length in bytes. AES: 16, 24, or 32. 3DES: 24. GENERIC_SECRET: ≤ 800 -lKey label Command: genSymKey -t 31 -s 32 -l mySymmetricKeyExpected output:
Cfm3GenerateSymmetricKey returned: 0x00 : HSM Return: SUCCESS Symmetric Key Created. Key Handle: 29 Cluster Status: Node id 0 status: 0x00000000 : HSM Return: SUCCESSImport the RSA public key from HSM B as a session key.
Parameter Description -sessImports the key as a session key for temporary use only -lKey label -fPublic key file to import Command: importPubKey -sess -l rsa_pub_key -f rsa_wrapping_key.pubExpected output:
Cfm3CreatePublicKey returned: 0x00 : HSM Return: SUCCESS Public Key Handle: 28 Cluster Status: Node id 0 status: 0x00000000 : HSM Return: SUCCESSWrap the symmetric key using the imported RSA public key and save the result to a file.
Parameter Description -kHandle of the key to wrap -wHandle of the wrapping key -mWrapping method. 8= RSA_OAEP. See Wrapping method reference for all supported values.-tHash type. Required when -mis7or8.3= SHA-256. See Hash type reference for all supported values.-outOutput file name for the wrapped key Command: wrapKey -k 29 -w 28 -m 8 -t 3 -out symmetric_key_wrapped_with_rsa.wrapExpected output:
Cfm2WrapKey5 returned: 0x00 : HSM Return: SUCCESS Key Wrapped. Wrapped Key written to file "symmetric_key_wrapped_with_rsa.wrap" length 525
Transfer symmetric_key_wrapped_with_rsa.wrap to the HSM B environment.
Step 3: In HSM B — unwrap the symmetric key
Unwrap the wrapped key file using HSM B's RSA private key (handle 32 from step 1).
Command: unWrapKey -f symmetric_key_wrapped_with_rsa.wrap -w 32 -m 8 -t 3| Parameter | Description |
|---|---|
-f | Wrapped key file to import |
-w | Handle of the wrapping key (RSA private key) |
-m | Wrapping method. Must match the value used in wrapKey. |
-t | Hash type. Must match the value used in wrapKey. |
Expected output:
Cfm2UnWrapKey5 returned: 0x00 : HSM Return: SUCCESS
Key Unwrapped. Key Handle: 31
Cluster Status:
Node id 0 status: 0x00000000 : HSM Return: SUCCESSThe symmetric key is now available in HSM B with key handle 31. Mark or delete symmetric_key_wrapped_with_rsa.wrap to prevent accidental re-import.
Copy an asymmetric key
This example copies an EC secp256k1 key pair from HSM A to HSM B. The private key is wrapped using RSA-2048 and RSA-OAEP (SHA-256). The public key is exported separately.
Step 1: In HSM B — create and export a wrapping key
Run the same genRSAKeyPair and exportPubKey commands as in Step 1 of copying a symmetric key. The expected output is a public key handle of 33 and a private key handle of 32.
Transfer rsa_wrapping_key.pub to the HSM A environment.
Step 2: In HSM A — wrap the private key and export the public key
Generate the EC key pair. Skip this step if the key already exists.
Parameter Description -iECC curve identifier. Valid values: 1–16 -lKey label Command: genECCKeyPair -i 16 -l secp256k1_keyExpected output:
Cfm3GenerateKeyPair returned: 0x00 : HSM Return: SUCCESS Cfm3GenerateKeyPair: public key handle: 29 private key handle: 28 Cluster Status: Node id 0 status: 0x00000000 : HSM Return: SUCCESSImport the RSA public key from HSM B as a session key.
Command: importPubKey -sess -l rsa_pub_key -f rsa_wrapping_key.pubExpected output:
Public Key Handle: 31Wrap the EC private key using the imported RSA public key.
Command: wrapKey -k 28 -w 31 -m 8 -t 3 -out secp256k1_key_wrapped_with_rsa.wrapExpected output:
Cfm2WrapKey5 returned: 0x00 : HSM Return: SUCCESS Key Wrapped. Wrapped Key written to file "secp256k1_key_wrapped_with_rsa.wrap" length 515Export the EC public key to a file.
Command: exportPubKey -k 29 -out secp256k1_key.pubExpected output:
PEM formatted public key is written to secp256k1_key.pub Cfm3ExportPubKey returned: 0x00 : HSM Return: SUCCESS
Transfer secp256k1_key_wrapped_with_rsa.wrap and secp256k1_key.pub to the HSM B environment.
Step 3: In HSM B — unwrap the private key and import the public key
Unwrap the EC private key using HSM B's RSA private key.
Command: unWrapKey -f secp256k1_key_wrapped_with_rsa.wrap -w 32 -m 8 -t 3Expected output:
Cfm2UnWrapKey5 returned: 0x00 : HSM Return: SUCCESS Key Unwrapped. Key Handle: 27 Cluster Status: Node id 0 status: 0x00000000 : HSM Return: SUCCESSImport the EC public key.
Parameter Description -lKey label -fPublic key file to import Command: importPubKey -l secp256k1_key_pub_imported -f secp256k1_key.pubExpected output:
Cfm3CreatePublicKey returned: 0x00 : HSM Return: SUCCESS Public Key Handle: 26 Cluster Status: Node id 0 status: 0x00000000 : HSM Return: SUCCESS
The EC key pair is now available in HSM B: private key handle 27, public key handle 26. Mark or delete secp256k1_key_wrapped_with_rsa.wrap to prevent accidental re-import.
Wrapping method reference
The following wrapping methods are supported for the -m parameter in wrapKey and unWrapKey:
| Value | Method | Constraints |
|---|---|---|
0 | AES_CBC_PAD | Requires initial vector if -noheader is specified |
1 | AES_CBC | Requires initial vector if -noheader is specified |
4 | CLOUDHSM_AES_KEY_WRAP | — |
5 | NIST_AES_WRAP_NO_PAD | Key length must be a multiple of 8 bytes |
6 (default) | NIST_AES_WRAP_PAD | — |
7 | RSA_AES | Requires -t (hash type) |
8 | RSA_OAEP | Requires -t (hash type). Key length ≤ Mod_len − 2 × Hash_len − 2 bytes |
9 | NIST_TDEA_WRAP | Key length must be a multiple of 4 bytes |
10 | AES_GCM | — |
11 | CLOUDHSM_AES_GCM | — |
12 | RSA_PKCS | Key length ≤ Mod_len − 11 bytes |
Hash type reference
The -t parameter is required when -m is 7 (RSA_AES) or 8 (RSA_OAEP):
| Value | Hash algorithm |
|---|---|
2 (default) | SHA-1 |
3 | SHA-256 |
4 | SHA-384 |
5 | SHA-512 |
6 | SHA-224 |