Using YubiHSM 2 with Java

Java applications that need to protect their cryptographic keys have several options to do so using YubiHSM 2:

  1. Use a java library such as yubihsm-java to directly interact with a YubiHSM 2 device. This enables all YubiHSM 2 features from a Java application similar to what the libyubihsm C API provides. However, this requires an application that is specifically targeting YubiHSM 2. This is typically not the case with most third-party software.

  2. Use the Java Cryptography Architecture (JCA) and the Java Cryptography Extension (JCE), which define provider-based cryptographic interfaces for Java applications. One such provider is the SunPKCS11 Provider that bridges between the Java JCA/JCE APIs and a native PKCS#11 library, such as the YubiHSM PKCS#11 Module. This enables any Java application that supports the PKCS#11 standard to use cryptographic keys stored in a YubiHSM 2, as long as it adheres to this standardized interface.

In the following, we will be using the SunPKCS11 Provider to interact with the YubiHSM 2.

Accessing cryptographic keys on the YubiHSM 2

Java applications store cryptographic keys and certificates in a KeyStore. KeyStores can be implemented using files, but in our case we will be using a YubiHSM 2 as a KeyStore through the SunPKCS11 Provider.

From the command-line, a tool called keytool is used to manage a KeyStore’s keys and certificates. The -list command argument to keytool will list all entries in a KeyStore. A number of command options are required when using YubiHSM 2 as a KeyStore:

  • To indicate our KeyStore is not file-based, use NONE as the -keystore command option.

  • Add command arguments -storetype PKCS11 to indicate we will be using a PKCS#11 KeyStore, and -providerClass sun.security.pkcs11.SunPKCS11 to select the SunPKCS11 provider, which should be installed with your Java Runtime.

  • Add -providerArg to specify a SunPKCS11 configuration file to use (see below).

  • Add -storepass to specify your authentication key and derivation password.

For instance, to list keys and certificates stored in a YubiHSM 2 using default credentials:

keytool -list -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg sun_yubihsm2_pkcs11.conf -storepass 0001password
Keystore type: PKCS11
Keystore provider: SunPKCS11-yubihsm-pkcs11

Your keystore contains 2 entries

MyKey1, PrivateKeyEntry,
Certificate fingerprint (SHA-256): FC:06:96:C0:6A:79:6F:80:D4:E2:0E:94:E7:68:97:B4:48:62:16:A3:14:F8:82:2C:1D:C9:D9:6A:69:4F:89:64
ejbca, PrivateKeyEntry,
Certificate fingerprint (SHA-256): B0:D4:10:84:74:AE:81:E5:00:56:BD:25:54:49:BE:1A:FB:E7:9D:F8:A8:00:3E:7B:4B:A9:29:9F:B6:C3:78:72

Assuming the default Authentication Key with ID 1 and password password, the PKCS#11 user PIN and hence the KeyStore password is 0001password. See the documentation on PKCS#11 with YubiHSM 2.

SunPKCS11 configuration

The SunPKCS11 provider needs a configuration file (sun_yubihsm2_pkcs11.conf in the example above) to define what native PKCS#11 module to use.

An example configuration file would have the following content:

name = yubihsm-pkcs11
library = /usr/local/lib/pkcs11/yubihsm_pkcs11.dylib
attributes(*, CKO_PRIVATE_KEY, CKK_RSA) = {
  CKA_SIGN=true
}

The library settings should point to the YubiHSM 2 PKCS#11 module on your system, that was installed as part of the YubiHSM 2 SDK

The attributes setting is used here to define specific attributes for RSA signing keys.

In this example, we are setting the attribute CKA_SIGN to true for all private key objects of type RSA generated or imported via the PKCS#11 bridge. This translates into the sign-pkcs and sign-pss capabilities, required for generating RSA signatures.

Importing Keys and Certificates

Due to a conflict between SunPKCS11 Provider KeyStore Requirements and the way YubiHSM 2 is designed, it is not possible to import keys and certificates directly using keytool. See also here for a more detailed explanation.

Instead, use for instance yubihsm-shell to import a key and its corresponding certificate. For instance, to import an RSA signing key and its corresponding certificate from PEM-encoded files:

yubihsm-shell -p password --authkey=0x0001 -a put-asymmetric-key -i 0x0002 -d 1 -l MyKey1 -A rsa2048 -c "sign-pkcs,sign-pss,sign-attestation-certificate" --informat=PEM --in signing-key.pem
Using default connector URL: http://127.0.0.1:12345
Session keepalive set up to run every 15 seconds
Created session 1
Stored Asymmetric key 0x0002
yubihsm-shell -p password --authkey=0x0001 -a put-opaque -i 0x0002 -d 1 -l MyKey1 -A opaque-x509-certificate -c sign-pkcs,sign-pss,sign-attestation-certificate --informat=PEM --in signing-crt.pem
Using default connector URL: http://127.0.0.1:12345
Session keepalive set up to run every 15 seconds
Created session 1
Stored 700 bytes to Opaque object 0x0002

Note that because the Java KeyStore requires that each private key object is matched with its corresponding certificate using their ID attributes, both put commands specify the same Object ID using the -i option.

Generating Keys and Certificates on the YubiHSM 2

If it is required to generate cryptographic keys on the YubiHSM 2 instead of importing them, we can use tools provided by Yubico to make sure the SunPKCS11 requirements are adhered to:

  • Use yubihsm-setup, using the ejbca subcommand that is intended for setting up EJBCA, but can also be used for other purposes. Use the --no-new-authkey option to keep the existing authentication keys. See also the manual.

yubihsm-setup --no-new-authkey ejbca
  • Use yubihsm-shell, as described in the PKCS#11 documentation.

  • Use the scripts in our yubihsm-java-enrollment GitHub repository to configure YubiHSM 2 for Java code signing.

Example applications

Some example applications where the SunPKCS11 provider is used with YubiHSM 2 are described in the following pages: