Using an HSM with confidential identities
In Corda, all nodes are associated with a public key. However, when additional privacy is required, nodes can use confidential identities. A confidential identity is a new key pair, referred to as a confidential identity key, that can be communicated to other specific nodes, which then associate the new key pair with the node that generated them.
This system allows the confidential identity keys to be used to sign transactions, without the wider network being able to associate the key pair with the signing node. Confidential identity keys can be used either by using the KeyManagementService
APIs, where a CorDapp generates a fresh key pair, and communicates it to other nodes; or with the SwapIdentitiesFlow
and IdentitySyncFlow
.
Using confidential identities with an HSM
By using an HSM, the confidential identity keys can be stored in the node database in an encrypted form. There are two supported modes for combining HSMs and confidential identities on Corda Enterprise; wrapped and degraded wrapped. Both of these modes are more secure than using confidential identities without an HSM.
Wrapped mode
The wrapped mode is the most secure, but requires specific APIs from the HSM, and not all HSMs are supported. The wrapped mode functions as detailed below:
- The node generates a symmetric AES key inside the HSM. This key is known as the wrapping key.
- When a confidential identity key is required, it is generated by the HSM and encrypted using the private wrapping key. The confidential identity key pair is then returned to the node as a public key and an encrypted private key.
- The node stores the public and encrypted private key.
- When the node needs to use the confidential identity key to sign data, the node provides the encrypted private key to the HSM, the HSM decrypts the key using the wrapping key, signs the data, and returns the signed data to the node.
This method prevents the node from having access to the unencrypted private key at any point in the key creation or data signing process.
Degraded wrapped mode
The degraded wrapped mode is slightly less secure than the wrapped mode, but can be supported by a wider variety of HSMs. The degraded wrapped mode functions as detailed below:
- The node generates the symmetric AES wrapping key inside the HSM.
- When a confidential identity key is required, the node generates the key pair in local memory, which is then sent to the HSM for encryption.
- The HSM encrypts the confidential identity key with the wrapping key, and returns the encrypted key to the node.
- When the node needs to use the confidential identity key to sign data, the HSM decrypts the private key, which is passed back unencrypted and used by the node to sign the data in memory.
The degraded wrapped mode is considered less secure than the wrapped mode, as the private key material is exposed to the node’s memory at two points:
- The confidential identity key is created in the node’s memory before it is encrypted.
- Data signing takes place in the node’s memory using the unencrypted private key, rather than inside the HSM.
Using confidential identities with a filesystem keystore
Confidential identities can be used with a keystore in the node filesystem. The filesystem keystore takes the role of the HSM, however, the filesystem keystore is only compatible with the degraded wrapped mode.
Configuring nodes for confidential identities
Using an HSM with confidential identities is not enabled by default. To enable this, the node configuration file must include the freshIdentitiesConfiguration
field.
The freshIdentitiesConfiguration
field contains the following attributes:
Attribute | Type | Required | Description |
---|---|---|---|
mode | String | Yes | Defines the mode of operation, valid values are: WRAPPED or DEGRADED_WRAPPED . |
masterKeyAlias | String | No | Defines an alias for the wrapping key. The default value is wrapping-key-alias . |
cryptoServiceConfiguration | N/A | Yes | Contains the cryptoServiceName and cryptoServiceConf attributes. |
cryptoServiceName | String | Yes | Defines the type of HSM. Valid values can be found in the HSM documentation. |
cryptoServiceConf | String | Yes | Defines a path to the HSM configuration file to use, for details, see the HSM documentation. |
masterKeyAlias
parameter.A completed configuration file might appear as follows:
freshIdentitiesConfiguration: {
mode: "DEGRADED_WRAPPED",
cryptoServiceConfiguration: {
cryptoServiceName: "BC_SIMPLE"
},
masterKeyAlias: "master-key",
}
Support matrix
The following table contains the current support and the associated configuration values:
Master key storage | cryptoServiceName | cryptoServiceConf | mode |
---|---|---|---|
file-based keystore | BC_SIMPLE | not used | DEGRADED_WRAPPED |
Securosys PrimusX HSM | PRIMUS_X | path to the PrimusX configuration file | WRAPPED |
AWS CloudHSM | AWS_CLOUD | path to the AWS CloudHSM configuration file | WRAPPED |
nCipher | N_SHIELD | path to nshield.conf | NATIVE |
Azure Key Vault | path to AZURE_KEY_VAULT | az_keyvault.conf | NATIVE |
Additional notes
- For Securosys’ PrimusX HSM, this feature has been tested with an HSM running firmware version 2.7.4 and the version 1.8.2 of the PrimusX JCA provider.
- The wrapping key is generated during node registration. So, if you want to upgrade to this secure mode of using confidential identities after having used the previous one, you will have to re-run the node registration process, which will skip the steps that have been executed already and will just generate the wrapping key.
- The HSM needs to be configured appropriately to allow import and export operations for keys. Ideally, a separate partition in the HSM can be used for confidential identities to follow the principle of least privilege for any other partitions. Note that Corda still ensures that only the wrapped keys corresponding to confidential identities are allowed to be exported and only in wrapped form.
- Specifically for PrimusX HSM, you will also need to enable the JCE API for wrapping (
jce_process.active
set toenabled
) and ideally disable key invalidation (invalidate_keys
set todisabled
), so that ephemeral keys do not continue to consume memory after being used and explicitly cleaned up.
AWS CloudHSM
Configuration file example:
freshIdentitiesConfiguration {
mode="WRAPPED"
cryptoServiceConfiguration {
cryptoServiceName="AWS_CLOUD"
cryptoServiceConf="aws_cloud.conf"
}
masterKeyAlias="master-key"
}
The following parameters are used for confidential identities on AWS CloudHSM:
- AES Key Wrap Algorithm (RFC 3394) with PKCS#5 padding
- Persistent, non-extractable 256-bit AES key as a wrapping key (KEK)
- Non-persistent (valid for the current session only), extractable EC secp256r1 key pair as an ephemeral key
nCipher HSMs
To use confidential identities with an nCipher HSM, the following configuration block must be present in the node.conf
file:
freshIdentitiesConfiguration: {
mode: "NATIVE",
cryptoServiceConfiguration: {
cryptoServiceName: "N_SHIELD"
cryptoServiceConf: "nshield.conf"
cryptoServiceTimeout: 10000
},
}
The nCipher HSM configuration file must contain the following configuration:
keyStore: "certificates/keystore.nshield"
password: "my-password
Futurex HSMs
To use confidential identities with a Futurex HSM, the following configuration block must be present in the node.conf
file:
freshIdentitiesConfiguration: {
mode: "WRAPPED",
cryptoServiceConfiguration: {
cryptoServiceName: "FUTUREX",
cryptoServiceConf: "futurex.conf"
},
masterKeyAlias: "ci-master-key-1"
}
The Futurex HSM configuration file must contain the following configuration:
credentials: 123456
FXPKCS11_CFG
environment variable must be set as detailed in the Futurex documentation. The <WRAP-PRESERVE-USAGE>
tag must be set to NO
. This tag doesn’t affect the legal identity functions of the HSM. Currently Corda Enterprise only supports Futurex HSMs at Java version 8.271 or earlier.Azure Key Vault
To use an Azure Key Vault HSM, the following configuration block must be present in the node.conf
file:
freshIdentitiesConfiguration: {
mode: "NATIVE",
cryptoServiceConfiguration: {
cryptoServiceName: "AZURE_KEY_VAULT"
cryptoServiceConf: "az_keyvault.conf"
cryptoServiceTimeout: 10000
},
}
The Azure Key Vault configuration file must contain the following configuration:
path: keyvault_login.p12
tenantId: "my-alias"
password: "my-password"
keyVaultURL: "[https:/](https:/)/<mykeyvault>.vault.azure.net/"
clientId: "a3d72387-egfa-4bc2-9cba-b0b27c63540e"
protection: "SOFTWARE"
SOFTWARE
.Was this page helpful?
Thanks for your feedback!
Chat with us
Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.
Propose documentation improvements directly
Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.
We're sorry this page wasn't helpful. Let us know how we can make it better!
Chat with us
Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.
Create an issue
Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.
Propose documentation improvements directly
Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.