Skip to main content

Hardware Security Module support for JSON Web Key sets

The PKCS#11 Cryptographic Token Interface Standard, also known as Cryptoki, is one of the Public Key Cryptography Standards developed by RSA Security. PKCS#11 defines the interface between an application and a cryptographic device.

note

If a key isn't found in the Hardware Security Module, the regular Software Key Manager with AES-GCM software encryption will be used as a fallback. Adding or updating keys always uses the Software Key Manager as it isn't possible to add keys to a Hardware Security Module.

PKCS#11 is used as a low-level interface to perform cryptographic operations without the need for the application to directly interface a device through its driver. PKCS#11 represents cryptographic devices using a common model referred to simply as a token. An application can therefore perform cryptographic operations on any device or token, using the same independent command set.

Hardware Security Module configuration

Ory Hydra can be configured using environment variables as well as a configuration file. For more information on configuration options, visit the configuration reference

HSM_ENABLED=true
HSM_LIBRARY=/path/to/hsm-vendor/library.so
HSM_TOKEN_LABEL=hydra
HSM_SLOT=0
HSM_PIN=1234
HSM_KEY_SET_PREFIX=app1.

Token that's denoted by environment variables HSM_TOKEN_LABEL or HSM_SLOT must preexist and optionally contain RSA (or ECDSA for JWT) key pairs with labels hydra.openid.id-token and hydra.jwt.access-token depending on configuration. If keys with these labels don't exist, they will be generated upon startup. If both HSM_TOKEN_LABEL and HSM_SLOT are set, HSM_TOKEN_LABEL takes precedence over HSM_SLOT. In this case first slot that contains this label is used. HSM_LIBRARY must point to vendor-specific PKCS#11 library or SoftHSM library if you want to test HSM support.

HSM_KEY_SET_PREFIX can be used in case of multiple Ory Hydra instances need to store keys on the same HSM partition. For example if HSM_KEY_SET_PREFIX=app1. then key set hydra.openid.id-token would be generated/requested/deleted on HSM with CKA_LABEL=app1.hydra.openid.id-token.

PKCS#11 attribute mappings to JSON Web Key Set attributes

When key pair is generated or requested from HSM, the CKA_LABEL attribute is used as JSON Web Key Set name, CKA_ID attribute as kid. Key usage is determined by private key attributes, where CKA_SIGN and CKA_DECRYPT are mapped to sig and enc respectively and set as key use attribute. Furthermore, CKA_ID's of key pair private/public handles must be identical. Attribute alg is determined from CKA_KEY_TYPE and CKA_ECDSA_PARAMS.

Supported key algorithms

Ory Hydra supports generating 4096 bit RSA, ECDSA keys with curves secp256r1 or secp521r1. As of now PKCS#11 v2.4 doesn't support EdDSA keys using curve Ed25519. However, PKCS#11 v3.0 contains support for EdDSA and therefore can be supported in upcoming versions. Symmetric key algorithms aren't supported because it would imply, that shared HSM is used between server and authenticating client.

Generating key pairs

Initializing token

Different policies can apply for tokens, therefore HSM configuration expects, that token where to find or generate keys already exists. Depending on HSM vendor, tools initializing tokens and generating keys vary. To demonstrate key pair generation we first initialize token using pkcs11-tool (see how to setup SoftHSM and OpenSC)

pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot 0 --init-token --so-pin 0000 --pin 1234 --init-pin --label hydra

Using slot 0 with a present token (0x2763db07)
Token successfully initialized
User PIN successfully initialized

Corresponding Ory Hydra configuration to access this token would be

HSM_ENABLED=true
HSM_LIBRARY=/usr/lib/softhsm/libsofthsm2.so
HSM_TOKEN_LABEL=hydra
HSM_SLOT=0
HSM_PIN=1234

Generating key pair

Generating RSA keypair for JSON Web Key hydra.openid.id-token

pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so \
--pin 1234 --token-label hydra \
--keypairgen --key-type rsa:4096 --usage-sign \
--label hydra.openid.id-token --id 746573742d6b65792d6964

Key pair generated:
Private Key Object; RSA
label: hydra.openid.id-token
ID: 746573742d6b65792d6964
Usage: sign
Public Key Object; RSA 4096 bits
label: hydra.openid.id-token
ID: 746573742d6b65792d6964
Usage: verify
ParameterDescription
--modulePoints to vendor specific PKCS#11 library or SoftHSM library when testing.
--pin 1234Pin that was used in token initialization to perform token operations.
--token-label hydraPerforms key generation on first slot with label hydra. Use --slot option instead if you want to specify specific slot.
--label hydra.openid.id-tokenSets key pair label attribute CKA_LABEL and is used as JSON Web Key Set name.
--id 746573742d6b65792d6964Sets key pair id attribute CKA_ID and is used as JSON Web Key Set kid. It must be set as a big-endian hexadecimal integer value. StringToHex("test-key-id") == 746573742d6b65792d6964
--keypairgenPerform key pair generation on token
--key-type rsa:4096Type and length of the key to generate. Supported values are rsa:4096, EC:secp256r1 or EC:secp521r1. Sets CKA_KEY_TYPE,CKA_ECDSA_PARAMS attributes and is used to determine JSON Web Key Set alg attribute.
--usage-sign or --usage-decryptSets private key attribute CKA_SIGN or CKA_DECRYPT respectively. Used to determine JSON Web Key Set use attribute.

Key type mappings
Key typeJWT signing algorithm
rsa:4096RS256
EC:secp256r1ES256
EC:secp521r1ES512

Testing with SoftHSM

SoftHSM is an implementation of a cryptographic store accessible through a PKCS #11 interface. You can use it to explore PKCS#11 without having a Hardware Security Module. It's being developed as a part of the OpenDNSSEC project.

Follow these instructions to build SoftHSM from source.

Install SoftHSM/OpenSC on Mac OSX

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 2> /dev/null
brew install softhsm
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 2> /dev/null
brew install opensc

Install SoftHSM/OpenSC on Ubuntu

sudo apt update
sudo apt install softhsm opensc

Install SoftHSM/OpenSC on Windows

Follow these instructions to install SoftHSM and OpenSC on windows.

Run Ory Hydra with HSM using Docker

Alternatively you can use quickstart docker container that setups SoftHSM/OpenSC, builds and runs Ory Hydra with HSM configuration enabled. You need to have the latest Docker and Docker Compose version installed. To run quickstart HSM change into the directory with the Hydra source code and run the following command:

docker-compose -f quickstart-hsm.yml up --build

Following is logged on startup if Hardware Security Module is successfully configured:

docker logs ory-hydra-example--hydra
time="2021-07-07T12:51:23Z" level=info msg="Hardware Security Module is configured."
time="2021-07-07T12:51:23Z" level=info msg="JSON Web Key Set 'hydra.openid.id-token' doesn't exist yet, generating new key pair..."

Run Tests with HSM enabled using Docker

make quicktest-hsm

AWS CloudHSM

The following are tips to help run Ory Hydra with AWS CloudHSM, please also refer to the official documentation.

Fetch the name of the token/slot in CloudHSM by using the pkcs11-tool with this command: pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so --list-slots.
CloudHSM only exposes a single slot/token to applications and connetions are load balanced across hsm-instances in the cluster.

HSM settings in Hydra:

hsm:
enabled: true
library: /opt/cloudhsm/lib/libcloudhsm_pkcs11.so
token_label: "hsm1"
pin: "{{ HSM_PIN }}"

AWS changed the default value of cavium for token_label to hsm1.

To generate a compatible key pair run the following command:

pkcs11-tool \
--module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so \
--pin <PIN> \
--token-label <LABEL> \
--keypairgen \
--key-type rsa:4096 \
--label hydra.openid.id-token \
--id <ID> \
--login \
--usage-sign \
--private \
--sensitive

The --private and --sensitive flags are important, include them to prevent errors.