This chapter contains information how to manage the crypto configuration of the Identity Server.
To add new certificates to the crypto configuration, you can have the admin node of the server have certificate files read from etc/init upon server startup. The accepted files are PEM- or DER-encoded X509-certificates, that are named with the appropriate file extension (i.e. .pem, .der, .cer or .crt). As certificates are always used with a particular purpose, an ordering is applied based on the directory that contains the particular certificate file. When a certificate is imported, the filename (without the extension) is used as its id.
etc/init
.pem
.der
.cer
.crt
The following directory structure is used:
etc/init/crypto/ssl-server-truststore
/facilities/crypto/ssl/server-truststore
etc/init/crypto/signature-verification
/facilities/crypto/signature-verification-keys
etc/init/crypto/signer-truststores
/facilities/crypto/signer-truststores
Example:
The X509-certificate stored as etc/init/crypto/ssl-server-truststore/www.example.com.der is imported in /facilities/crypto/ssl/server-truststore with an id www.example.com.
etc/init/crypto/ssl-server-truststore/www.example.com.der
www.example.com
Note
This mechanism only allows adding new or replacing existing certificates in the configuration. To delete a certificate from configuration, please see Server Configuration overview.
Important
The server needs to be started with the appropriate start-up arguments to consider reloading configuration files, please for more information please see Server Configuration overview.
As opposed to adding new certificates to the configuration, adding a keystore with a private key involves other actions than adding a certificate with just a public key, as a private key is usually transported with some layer of protection. There are two approaches for adding a new keystore to the configuration. The first method interacts with the configuration service, that validates and adds a given keystore into a running configuration. The other method is for preparing a keystore to be used in an XML-snippet that can be loaded by the server when it is configuring.
Both methods rely on starting with a private key that is stored in a base64-encoded PKCS12 or JKS file format.
You can use tools like openssl to convert between existing keystore formats, or to create new key pairs. If you need to create a new RSA key pair, for example, you can use the following commands to create a new PKCS12 keystore with a 2048 bits RSA key pair, that is base64-encoded:
$ openssl req -x509 -sha256 -newkey rsa:2048 -keyout curity.key -out curity.crt -days 365 $ openssl pkcs12 -export -name curity -in curity.crt -inkey curity.key -out curity.p12 $ openssl base64 -in curity.p12 -out curity.p12-b64
A keystore can be added through the CLI.
Before getting into the CLI, prepare the base64-encoded file with the keystore to eliminate chunked lines and make it a one-liner. You can do that using the tr command line tool to do this:
$ tr -d '\n' < curity.p12-b64
The output is something you want to copy into your clipboard for use in the CLI.
Next, get in to the CLI . Once you have connected, enter the following command to add the new signing key:
request facilities crypto add-signing-key-keystore id new-signing-key-alias
Replace new-signing-key-alias with the desired id of the new keystore.
new-signing-key-alias
The CLI will ask for a value for keystore; here you should paste the contents of the base64-encoded keystore (e.g. the contents of the curity.p12-b64 file). Also enter the password that protects the PKCS12 keystore. The interaction should look something like this:
keystore
curity.p12-b64
admin@my-host% request facilities crypto add-signing-key-keystore id new-signing-key-alias-from-cli Value for 'keystore' (<string, min: 1 chars>): MIILAAIBAzCCCsYGCSqGSIb3DQEHAaC....qA7KxkOQQIsHfJOFKfsQECAggA Value for 'password' (<string, min: 1 chars>): Password1 status true
(keystore contents abbreviated for readability).
For a list of all possible actions that can be used to manage (i.e. add/replace) keystores, type request facilities crypto in the CLI and then press tab for autocomplete. This will list actions with their descriptions.
request facilities crypto
tab
admin@my-host% request facilities crypto Possible completions: add-decryption-key-keystore - This action adds a new Server SSL key to the configuration add-encryption-key-keystore - This action adds a new Server SSL key to the configuration add-signature-verification-key - This action adds a new Signature verification key to the configuration add-signer-truststore - This action adds a new signer truststore to the configuration add-signing-key-keystore - This action adds a new signing key to the configuration add-ssl-client-keystore - This action adds a new SSL client key to the configuration add-ssl-client-truststore - This action adds a new Client SSL truststore to the configuration add-ssl-server-keystore - This action adds a new Server SSL key to the configuration add-ssl-server-truststore - This action adds a new Server SSL truststore to the configuration apply-csr-response - This action sets a certificate chain into a key store generate-csr - This action generates a CSR (Certificate Signing Request) from a keystore with a private key and a certificate generate-signing-key-keystore - This action creates and adds a new signing key to the configuration generate-ssl-server-keystore - This action creates and adds a new Server SSL key to the configuration
These actions can also be invoked using the RESTCONF API. See the Invoking YANG Actions Using RESTCONF section for more information on how to do that.
In case you are preparing an XML configuration file, you can use the conversion tools to process a PKCS12 keystore into the data that can be used to configure the crypto facilities of the Curity Identity Server. See the section on Converting KeyStores (keystore-entry) into correct PKCS12 format.
The output of the conversion, a base64-encoded string, can be used in an XML-snippet:
Listing 26 Sample signing key configuration configuration¶ <config xmlns="http://tail-f.com/ns/config/1.0"> <facilities xmlns="https://curity.se/ns/conf/base"> <crypto> <signing-keys> <signing-key> <id>default-signing-key</id> <keystore>MIILAAIBAzCCCsYGCSqGSIb3DQEHAaC....qA7KxkOQQIsHfJOFKfsQECAggA</keystore> </signing-key> </signing-keys> </crypto> </facilities> </config>
<config xmlns="http://tail-f.com/ns/config/1.0"> <facilities xmlns="https://curity.se/ns/conf/base"> <crypto> <signing-keys> <signing-key> <id>default-signing-key</id> <keystore>MIILAAIBAzCCCsYGCSqGSIb3DQEHAaC....qA7KxkOQQIsHfJOFKfsQECAggA</keystore> </signing-key> </signing-keys> </crypto> </facilities> </config>
This XML can be added to the configuration in $IDSVR_HOME/etc/init and reloaded using the normal procedure.
In Curity, private keys are stored in a pre-defined format in the configuration. To facilitate the conversion to this format, a convertks script is available in the bin directory of the Identity Server distribution.
convertks
bin
The resulting key can be configured in the crypto-section as ssl/server-keystore, ssl/client-keystore, signing-keys, encryption-keys and decryption-keys.
The convertks script helps with processing a base64-encoded keystore, pick one Private Key entry out of that keystore, and write it as sole Entry in a new KeyStore. The output of the script is a base64-encoded version of this KeyStore.
There are two main ways of using the script, either by providing the input keystore as argument, or by providing it as a file.
The convertks script can show all its options when you invoke it with:
$ convertks --help
Given a base64-encoded KeyStore (i.e. “MIInputKeystore”) that is protected with a KeyStore-password ‘KeyStorePassword’, containing an entry with an alias of ‘InputEntryAlias’ that is protected with password ‘InputEntryPassword’, the convertks script can be invoked with the following commandline:
$ convertks --in-password KeyStorePassword --in-alias InputEntryAlias --in-entry-password InputEntryPassword --in-keystore MIInputKeystore
Note: if entry-password is the same as password of the keystore, it can be omitted in the argument list.
entry-password
password
This will output the KeyStore in the correct format to the console. If the output needs to be written to a file instead, add the --out-file parameter with the appropriate filename. The script will be silent.
--out-file
Note that if any required argument is not provided, the script will prompt for it.
Instead of providing the keystore on the commandline itself, it can also be provided through stdin, i.e. with a command like:
$ cat "MIInputKeystore" | convertks --in-password KeyStorePassword --in-alias InputEntryAlias --in-entry-password InputEntryPassword
If the base64-encoded KeyStore is stored in a file, this procedure is the same as above, but the --in-keystore parameter that provides the KeyStore must be replaced with the --in-file argument that contains the name of the file. Given that the file is “current-keystore-base64.txt”, the convertks script can be invoked with the following commandline:
--in-keystore
--in-file
$ convertks --in-password KeyStorePassword --in-alias InputEntryAlias --in-entry-password InputEntryPassword --in-file current-keystore-base64.txt --out-file new-keystore-base64.txt
This will output the KeyStore in the correct format to the file new-keystore-base64.txt
If there is no --out-file argument provided, the new keystore will be shown in the console.
There are plenty of keystore formats that are used throughout, one of which is specified in the PKCS#1 specification in RFC 8017. A major drawback for PKCS#1 keystores is the fact that they can only contain one key, which makes it more difficult to manage, as the Curity Identity Server prefers to use keystores with private- and public keys (or certificates) combined.
When certificates are obtained from Let’s Encrypt using the getssl script, the resulting files are two PKCS#1 files.
As a consequence, to use PKCS#1 keys and certificates, they must be processed outside Curity so they can be configured using the Admin UI or other means. Converting the PKCS#1 key material into a Curity supported format can be done with tooling like for example openssl. This section will walk through the steps needed to perform the conversions to produce a singular keystore that can be used with Curity Identity Server.
openssl
Hint
When looking inside the contents of a PEM-encoded file, you can tell that it is a PKCS#1 formatted private key when the file starts with -----BEGIN RSA PRIVATE KEY-----. A PKCS#8 formatted file would start with -----BEGIN PRIVATE KEY-----.
-----BEGIN RSA PRIVATE KEY-----
-----BEGIN PRIVATE KEY-----
Given there are two files, a private key in one file (e.g. curity.example.com.key) and a certificate in another file (e.g. curity.example.com.crt), you can use the following commands to convert these into one file in the PKCS#8 format, that can be used directly with the Curity Identity Server to import:
curity.example.com.key
curity.example.com.crt
$ openssl pkcs8 -in "curity.example.com.key" -topk8 -out "curity.example.com.key.pkcs8" -nocrypt $ cat curity.example.com.key.pkcs8 curity.example.com.crt > curity.example.com.pkcs8
The commands above produce a file curity.example.com.key.pkcs8 that can be used in the same way that a PKCS#12 file can be used to configure Curity Identity Server using the instructions from Configuring private keystores.
curity.example.com.key.pkcs8
This section describes the setup of a Hardware Security Module (HSM) in the Curity Identity Server. Curity interfaces with an HSM using PKCS#11. This means that some kind of shared library is needed which provides this PKCS#11 capability. This is typically provided by the manufacturer of the HSM. Once an HSM is configured, keys can be used from the HSM. It is not required that all keys, public or private, reside on the HSM. It is possible to configure Curity to use some keys from its own configuration and others from the HSM. This can be especially helpful during testing, but can be useful even in production when it is desirable to configure the public keys in Curity rather than fetch them from the HSM (which may only be accessible over a network connection).
SSL, signature verification keys (public keys), signing keys, trust anchors, and client keys can all be configured to be stored on the HSM. When configuring a keystore, the admin just needs to specify that the key is located on the HSM. The admin node need not have access to the HSM; only run-time nodes that will use the keys housed in the HSM need access to the unit. This may be a subset of the run-time nodes depending on your deployment. There is currently no way to test the connectivity of the HSM from the admin node because it is assumed that this node won’t have access to an HSM.
In order for a key to be accessible to Curity, the HSM must contain not only a public key but also a certificate; without this, the key will not be found at run-time by Curity. The certificate can be self-signed, but it may also be signed by a trusted authority. The only algorithm supported at this time is RSA; elliptic curve and DSA keys cannot be used.
In order for each Curity run-time node to access keys on an HSM, they will need to login. This is done using a PIN or pass phrase. There are four ways to provide this PIN to Curity:
-i
IDSVR_HSM_PIN
If the -i flag is used with a PIN as an argument (as in the first or second option above), then the admin will not need to interactively provide one. When provided directly on the command line, the PIN will be included in the output of ps and other such tools; to avoid this, the second option of reading the PIN from a file can be used. With this option, the file can be a symlink or pipe as well. The third option of providing the PIN through an environment variable may also make it accessible to such tools. If the PIN is set interactively, it will only be resident in the node’s memory and not accessible from outside tools (like ps). This method requires interactive input from an admin on the console during startup, however.
Before any keystore can be configured as one residing in the HSM, the configuration for the unit must be defined. This is done by setting at least the path to the shared library that provides PKCS#11 support. This can be done using any of the management interfaces. For detailed information on the HSM-related settings, refer to the configuration reference.
To configure an HSM using the admin UI, navigate to the System ‣ General page. On this page, there is a section labeled Hardware Security Module. By default, this is toggled off, as shown in Fig. 20:
Hardware Security Module
Fig. 20 The HSM is toggled off (i.e., disabled) by default
Once it is toggled on, various settings can be configured. As shown in Fig. 21, the two that are required are some sort of identifier or name and the path (as it will be on any run-time node that uses the HSM) to the shared library that provides the PKCS#11 implementation.
Fig. 21 The HSM can be toggled on and then the required settings and some optional ones can be configured
Either the slot list index or slot ID must be configured as well. By default, the list index is selected with a value of 0, but this can be changed as needed. The values will depend on the PKCS#11 provider used with the HSM. For example, to get this information with OpenSC, the pkcs11-tool command can be used as shown in Listing 28:
0
$ pkcs11-tool -I Cryptoki version 2.20 Manufacturer OpenSC Project Library OpenSC smartcard framework (ver 0.17) Using slot 0 with a present token (0x0)
To make the HSM as compatible with Curity as possible, the Include Compatibility Attributes option should be toggled on. If this poses a problem, select attributes can be enabled using the Mechanisms option. This option allows certain PKCS#11 mechanics to be enabled or disabled as needed. Valid mechanisms can be found in the PKCS#11 reference guide; any unrecognized value will cause the unit to be inaccessible and a warning to be logged.
Include Compatibility Attributes
Mechanisms
The CLI can also be used to configure the HSM. For example, enter configuration mode and set it as shown in Listing 29:
admin@prod-curity1% set facilities crypto hardware-security-module library /usr/local/lib/opensc-pkcs11.so
To delete the HSM configuration, just issue the command delete facilities crypto hardware-security-module and commit the change.
delete facilities crypto hardware-security-module
To get more information from the underlying PKCS#11 provider, you can pass the --debug-hsm flag to the idsvr command. This will cause all PKCS#11 keystore-related and provider-based messages to be written to the server log. You can also specify -Djava.security.debug=sunpkcs11,pkcs11keystore,pkcs11 in the JVM options of a certain node. If this method is used, the extra provider-related debugging information will be output after the node is restarted. When using this tactic, it can be helpful to include provider in the comma-separated list of debug message sources together with sunpkcs11, pkcs11keystore, and pkcs11. To set these and provider via the command-line, do not use the the --debug-hsm parameter; instead, pass it via the JAVA_OPTS environment variable when starting the idsvr command (e.g., JAVA_OPTS=-Djava.security.debug=sunpkcs11,pkcs11keystore,pkcs11,provider idsvr).
--debug-hsm
provider
sunpkcs11
pkcs11keystore
pkcs11
JAVA_OPTS
JAVA_OPTS=-Djava.security.debug=sunpkcs11,pkcs11keystore,pkcs11,provider idsvr
Some HSM providers, like OpenSC, include a proxy library that logs all access to the PKCS#11 module. To use such an interceptor, configure the proxy library as the one that Curity should use. In the case of OpenSC, in particular, the library that is being proxied needs to be set via an environment variable. This can be done from the shell when starting the idsvr command (e.g., PKCS11SPY=/usr/local/lib/opensc-pkcs11.so idsvr). In the same way, other environment variables of OpenSC’s can be set before invoking idsvr; for instance, the environment variable, OPENSC_DEBUG, can be set to some debug level, like 9, which results in trace-level debug messages being printed to the server log.
PKCS11SPY=/usr/local/lib/opensc-pkcs11.so idsvr
OPENSC_DEBUG
9
The EdDSA algorithm is based on Edwards Curves, and its use with JOSE is standardized by RFC 8037. The Curity Identity Server fully supports the Ed25519 and Ed448 signature algorithms for digital signature creation and validation.
Ed25519
Ed448
Contrary to RSA and Elliptic Curve algorithms, EdDSA explicitly specifies the hashing algorithm to use when calculating signatures, hence the signature algorithm name for the two EdDSA algorithms (Ed25519 and Ed448) is the same for both, i.e. EdDSA. The actual signature algorithm that is used to create or verify signatures must be derived from the accompanying key.
EdDSA
{ alg: 'EdDSA', x5t: 'ZRNic4l1nEsFtyu0BDTL4sbF0eo' }
In the above JWT header, the x5t field points to the certificate that contains an EdDSA key. If that key is using the Ed25519 key algorithm, it should be validated using the Ed25519 signature algorithm.
x5t
Note that RFC 8037 profiles EdDSA for the PureEdDSA variants of Ed25519 and Ed448, and therefore does not use the Ed25519ph, Ed25519ctx` or Ed448ph variants.
Ed25519ph
Ed448ph