Keys, Certificates and Trust Stores
On this page
Public Key Cryptography is based on a key pair, where one part has a private key and a corresponding public key. Because of the asymmetry, where one party has a private and the others a public key, public key algorithms are also classified as asymmetric algorithms (compared to symmetric algorithms where all parties share the same secret key). The key pair looks different based on the algorithm used, i.e. RSA public keys are not the same as ECDSA keys and not compatible in any way either.
There are various formats to represent and store keys such as PEM- or DER-encoded formats, PKCS#12, Java KeyStore or JSON Web Key. Some of these formats store the private and public key and are password protected, others only contain the public key.
Often, the public key is assigned some details, such as a name and owner, the corresponding algorithm and intended key usage or a life-time. One method to bind the public key to metadata is the certificate, where a third party assures that the metadata belongs to the key and is correct. It does so by putting its signature underneath (metaphorically speaking). This party is the issuer of the certificate, or the Certificate Authority (CA). To trust the metadata bound to a public key some need to trust the issuer of the certificate.
Certificates are used for signing and encrypting, authentication, and establishing trust. In general, there are two types of certificates: those where the server only knows the public key stored in a truststore, and those where the server also possesses the private key stored in a keystore. Certificates are also grouped by their function, i.e., if they are used to secure the transport layer via SSL/TLS or to sign and encrypt messages and tokens. Furthermore, the configuration categorizes certificates based on the role of the Curity Identity Server, i.e., if it receives or sends a protected message. Consequently, the Curity Identity Server handles the following list of certificates (and keys):
|Descriptive Name||Description||Configuration Item|
|Server SSL Keys||Certificates and keys used to protect endpoints with HTTPS|
|Server Trust Stores||Server certificates of (external) HTTPS endpoints that the Curity Identity Server trusts|
|Client SSL Keys||Certificates and private keys used for mutual TLS where the Curity Identity Server acts as the client|
|Client Trust Stores||Certificates presented by clients in Mutual TLS sessions that the Curity Identity Server trusts|
|Signing Keys||Certificates and private keys used for signing|
|Signature Verification Keys||Certificates and public keys used to verify signatures of tokens issued by other systems|
|Signing Key Trust Stores||Trusted root certificates used for signature verification for a specific purpose (for example a signed software statement)|
|Encryption Keys||Certificates and public keys that the Curity Identity Server uses for creating encrypted messages addressed to certain Relying Parties|
|Decryption Keys||Certificates and private keys used for decrypting|
Certificates and keys have their own place in the configuration and are found under
facilities/crypto. Each entry of a key, certificate, or store of trusted certificates is referenced by an ID. In this way, certificates and trust stores can easily be reused across the system.
Trusted certificates are normally root CA certificates that have a long expiration time. Changes to a CA infrastructure are, in general, announced in advance and performed carefully. There should be enough time to act and update the trust stores.
The lifetime of individual certificates is much shorter. Using a short expiration time for certificates is like a short lifetime for Access Tokens. If anything goes wrong, then there is a limited time frame for attacks. To prevent the user from logging in constantly when Access Tokens expire, Refresh Tokens are used to renew Access Tokens seamlessly. The same applies to certificate renewal. When a certificate is close to expiring, request a new one and configure it in an automated fashion, preferably without interruptions.
The Curity Identity Server automatically publishes its public keys such as the token verification key in JWK format in a JSON Web Key Set (JWKS). The link to the JWKS, the
jwks_uri, can be found in the OpenID metadata (if published) and is part of the anonymous endpoint, e.g.
https://idsvr.example.com/oauth/v2/oauth-anonymous/jkws. Clients and APIs can look up the
jwks_uri from the server's OpenID metadata, then download a key from the link and use it to verify any tokens. Which key to retrieve is specified by the key ID parameter
kid in the header of the JWT.
JWK and JWKS are also very useful formats for clients to share their keys with the Identity Server. When clients use
Client Assertion for authentication, that is a self-signed JWT instead of a certificate or secret, then the Curity Identity Server can check the clients'
jwks_uri for the keys to verify the clients' JWT with. In that way, clients can simply publish a new key and exchange the existing one without having to wait for the Identity Server to update. If done correctly, the Identity Server will pick the new key automatically from the
jwks_uri. This makes key rollover fast and easy.
Remember from above that trust stores contain other systems' public keys whereas key stores contain the private key (and public key) used by the Curity Identity Server. To add a new trust, ask the third party to share the public key with you and upload it. Supported methods are text or file of the formats mentioned at the beginning of this tutorial. When adding a new SSL trust, you can also enter the external host and add its server certificate without having to manually download it. For client trust stores, you can even select from a list of preconfigured certificates.
When adding a new (private) key, the procedure differs. For simplicity, this section explains how to add a new signing key to the Curity Identity Server. Follow the procedure accordingly to add another type of asymmetric key.
To add a new signing key to the Curity Identity Server, open the Facilities menu, navigate to the category Signing Keys and click on + New next to it. Enter a name. This name becomes the ID of the key that is used to reference the key in the configuration. Select
asymmetric from the dropdown for the key type.
There are now different choices to add a new asymmetric key in the Curity Identity Server:
- Import an existing key
- Create of a new key
- Use from HSM
When importing an existing key pair, you can upload a file. This file represents a keystore such as a PKCS#12 or a JAVA keystore. A PKCS#12 and Java KeyStore can contain several key pair entries.
Use a command line tool to list the content of a keystore to study the entries.
pkcs12 command in openssl. Do not output any certificates (
-nocerts) as only the keys are of interest in this context.
openssl pkcs12 -nocerts -in keystore.p12
OpenSSL will ask for a password for the keystore and another one for each private key. The passwords for the private keys are used to encrypt the output. This ensures that the keys are not revealed in clear text. The result looks similar to the following where the alias of the key is the
Bag Attributes friendlyName: key-alias-1 localKeyID: 31 1F A9 19 36 BC EB A4 5D 64 B8 CD E9 5C 2B 7D AC BD D3 B8 Key Attributes: <No Attributes> -----BEGIN ENCRYPTED PRIVATE KEY----- ... -----END ENCRYPTED PRIVATE KEY----- Bag Attributes friendlyName: key-alias-2 localKeyID: 54 69 6D 65 20 31 36 35 32 39 35 33 33 37 39 32 37 38 Key Attributes: <No Attributes> -----BEGIN ENCRYPTED PRIVATE KEY----- ... -----END ENCRYPTED PRIVATE KEY----- Bag Attributes friendlyName: key-alias-3 localKeyID: 54 69 6D 65 20 31 36 35 32 39 35 33 35 30 32 37 31 38 Key Attributes: <No Attributes> -----BEGIN ENCRYPTED PRIVATE KEY----- ... -----END ENCRYPTED PRIVATE KEY-----
-list to list the keys of a given keystore with Java's keytool.
keytool -list -keystore keystore.p12
The result will look similar to this. Every entry starts with the alias.
Enter keystore password: Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 3 entries key-alias-1, 24 May 2022, PrivateKeyEntry, Certificate fingerprint (SHA-256): 07:01:9D:29:C3:13:49:E8:88:8D:E3:27:50:1B:57:C1:01:00:86:B2:96:8F:E8:EB:82:CF:6B:F0:2A:35:95:55 key-alias-2, 19 May 2022, PrivateKeyEntry, Certificate fingerprint (SHA-256): 28:86:15:A4:6F:F9:58:9C:6D:78:63:50:E4:A1:8D:EF:72:DE:01:C1:8A:2F:CD:9C:D9:75:D9:18:2F:44:08:95 key-alias-3, 19 May 2022, PrivateKeyEntry, Certificate fingerprint (SHA-256): 4A:57:82:9B:DA:44:47:D9:1F:6C:DD:17:C6:28:E4:5F:CD:A0:AC:61:D3:6B:13:4D:08:10:EC:4F:4B:6E:DF:20
If the keystore is password protected (which it should be), then click on Enter Password and specify the password. If the selected keystore has several entries, click on Enter Alias and enter the id of the key that should be uploaded.
Click on Add and Commit to upload the key. It will now be visible in the Facilities menu.
The key is now ready to be used. For example, use it to change the signing key of a token issuer as shown in the Tutorial on how to use EdDSA.