JCA Overview

The Java Cryptography Api or JCA is a plugable architecture which tries to abstract the actual crypto implementation from the algorithm requested.

This allows our code to use Cipher.getInstance(“AES”), and not have to hard code the actual implementation, better or different implementations can be swapped out depending on deployment requirements.

At the heart of the JCA architecture is the Provider abstract class, a specific provider will register different algorithm implementations where each implementation implements a specific *SPI (service provider interface) abstract class depending on which algorithm it’s implementing.

For example:

The class com.sun.net.ssl.internal.ssl.Provider implements sun.security.ssl.SunJSSE which implements Provider, registers support for PKCS12 using

put(“KeyStore.PKCS12”,”sun.security.pkcs12.PKCS12KeyStore”);

sun.security.pkcs12.PKCS12KeyStore extends java.security.KeyStoreSPI which is the JCA abstraction for a KeyStore,

Installing Providers

Providers can be installed

* programmatically or via the

* java.security (<java-home>/lib/security/java.security), file that comes with the JRE.

To programmatically install Providers use the java.security.Security class, e.g

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

To install it via the “java.security” file, e.g

security.provider.10=sun.security.pkcs11.SunPKCS11 /etc/softhsm/pkcs11.cfg

For more detailed instructions see How to implement a Provider (Oracle)

PKCS 11 vs 12

PKCS 12 and 11 in Java JCA

PKCS 11 and PKCS 12 are part of the RSA Public Key Cryptography Standards.

A simple usage summary of both is: PKCS12 is used to store private key and certificate information on files, and PKCS11 stores them on external devices.

Both sun.security.pkcs11.SunPKCS11 and sun.security.ssl.SunJSSE providers register implementations for java.security.KeyStoreSPI, for PKCS11 its sun.security.pkcs11.P11KeyStore

The PKCS11 standard can be used for much more than private key certificate storage and the actual sun.security.pkcs11.SunPKCS11 implementation registers many more services, see: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/security/pkcs11/SunPKCS11.java#499

PKCS11

The PKCS11 standard comes with a series of C header files (pkcs11.h, pkcs11f.h and pkcs11t.h), which different hardware providers provide implementations for.

The lingua franca for hardware is C, so Java has to provide a JCA wrapper for it via JNI, this is essentially what sun.security.pkcs11.SunPKCS11 is, just a huge wrapper class that via JNI calls into the native module (.so, .dll) that implements the PKCS11 C header files.

Luckily for testing a software implementation can be used called SoftHSM.

PKCS11 via SoftHSM

A complete playground/example can be found at https://github.com/gerritjvv/engsectools/tree/master/pkcs11

Install and configure SoftHSM

For ubuntu run, refer to https://github.com/gerritjvv/engsectools/blob/master/pkcs11/Dockerfile

apt-get update && \

apt-get install -y vim && \

apt-get install -y libsofthsm softhsm softhsm-common opensc && \ mkdir -p /var/lib/softhsm/tokens

Update the folder privilege accordingly

chmod 777 /var/lib/softhsm/tokens

Use sofhsm2-util to initialize a token (remember that PKCS11 is a token service).

softhsm2-util — init-token — slot 0 — label “My token 1” — pin 123456 — so-pin 123456

Configure the Java PKCS11 wrapper

Create a file “/etc/softhsm/pkcs11.cfg” that will tell sun.security.pkcs11.SunPKCS11 where to find the PKCS11 implementation and which slot to use.

For SoftHSM2 locate the libsofthsm2.so file using sudo find / -iname “*hsm*.so”, then add to pkcs11.cfg:

name = SoftHSM

library = /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so slotListIndex = 0

Note: always use slotListIndex instead of slot.

Update the “java.security” file with:

Java 1.8:

security.provider.10=sun.security.pkcs11.SunPKCS11 /etc/softhsm/pkcs11.cfg

Java 1.9:

security.provider.12=SunPKCS11 /etc/softhsm/pkcs11.cfg

Note: the number 10 here means the last provider must be 9; if the providers have a gap in the numbers JCA will not see the last providers specified after the gap. Java 1.9 already has the SunPKCS11 entry, you only need to add the configuration file.

Load the PKCS11 KeyStore

Loading a PKCS11 KeyStore in Java is no different than loading any other KeyStore, except that the Input/Output Streams are always null. This does introduce a slight incompatibility with code that always expects a file to be present.

KeyStore ks = KeyStore.getInstance(“PKCS11”);

ks.load(null, pwd.toCharArray()); //edit, add keys etc

ks.store(null, pwd.toCharArray());

PKCS11 and Java KeyTool

The java key tool can be used to list, import and update private keys and certificates by specifying the “storetype” flag as PKCS11