Java applications that need to protect their cryptographic keys have several options to do so using YubiHSM 2:
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.
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.
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.
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.
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.
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:
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.
Some example applications where the SunPKCS11 provider is used with YubiHSM 2 are described in the following pages: