Using PKCS11 Credentials

xmlsectool supports using credentials stored in PKCS#11 tokens such as cryptographic smart cards, both to sign and verify documents.

To do this, it makes use of the Java runtime's ability to present an external PKCS#11 token as a Java keystore as described in the PKCS#11 Reference Guide.

Not all PKCS#11 implementations can be used in this way; in particular, tokens which do not allow an X.509 certificate to be stored alongside the private key are not compatible with the SunPKCS11 provider and thus cannot be used with xmlsectool. This is, unfortunately, true of some (but by no means all) high-end hardware security modules (HSMs).

A compatible PKCS#11 implementation must be configured into the SunPKCS11 provider as described in the PKCS#11 Reference Guide. This requires providing a simple configuration file, such as the following example:

1 2 3 name=acs library=/path/to/library.so description=ACOS5 token

This configuration can be provided in one of two ways:

  • Statically, by editing the java.security file within the Java runtime, or

  • Dynamically, by providing it to xmlsectool's --pkcs11Config option.

Although xmlsectool supports both options, we strongly recommend dynamic configuration over static: because static configuration requires you to change a file within the Java runtime itself, the changes apply to every application using that runtime, require additional permissions on most systems, and may be erased whenever the runtime is updated.

We do not recommend mixing dynamic and static configuration (i.e., using --pkcs11Config with a modified java.security file, as this can cause two copies of the provider to be loaded. This may result in hard to debug errors, such as "Private keys must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding" or "No installed provider supports this key".

Using xmlsectool with Dynamic PKCS#11 Configuration

To use a credential from a dynamically configured PKCS#11 token, use the --pkcs11Config option as follows:

1 ...xmlsectool.sh --pkcs11Config /path/to/config.cfg ...

For example:

1 2 3 ...xmlsectool.sh --sign --pkcs11Config /path/to/config.cfg \ --keyAlias key2048 --keyPassword 1234 \ --inFile unsigned.xml --outFile signed.xml

Verification works in the same way:

1 2 3 ...xmlsectool.sh --verifySignature --pkcs11Config /path/to/config.cfg \ --keyAlias key2048 --keyPassword 1234 \ --inFile signed.xml

Of course, because signature verification does not involve the private key, it may be simpler to use a file-based credential for this operation through the --certificate option rather than using PKCS#11.

Using xmlsectool with Static PKCS#11 Configuration

If for some reason you can not use the recommended dynamic PKCS#11 configuration, xmlsectool also supports static configuration of your PKCS#11 provider.

As described in the PKCS#11 Reference Guide, one way to do this is to modify the JDK's java.security file. Add a new configured security provider to the end of the list, after the unconfigured SunPKCS11 provider, like this:

1 2 3 4 5 security.provider.1=SUN security.provider.2=SunRSASign ... security.provider.13=SunPKCS11 security.provider.14=SunPKCS11 /path/to/config.cfg

(Alternatively, you can augment or override the JDK's java.security file, see below.)

The number of providers in the distributed java.security file may vary between Java versions and between platforms: the list should always end with a SunPKCS11 entry; your configured provider should be added after that with the next sequential index.

Once you have modified java.security you can access PKCS#11 credentials from the new provider like this:

1 ...xmlsectool.sh --keystore /dev/null --keystoreType PKCS11 ...

Here, "/dev/null" represents the null device for your system.

For example:

1 2 3 ...xmlsectool.sh --sign --keystore /dev/null --keystoreType PKCS11 \ --keyAlias key2048 --keyPassword 1234 \ --inFile unsigned.xml --outFile signed.xml

Augmenting or overriding java.security

It is possible to use static PKCS#11 configuration without editing the JDK's master version of java.security. This mechanism is documented in the master java.security file itself and involves adding "-Djava.security.properties=<URL>" to the command line; refer to java.security for full details.

The indicated local file can be used to either supplement or override the master java.security file. You can add extra JVM options to the xmlsectool command line like this:

1 JVMOPTS="... extra parameters here ..." ...xmlsectool.sh ... normal options here ...

For example:

1 JVMOPTS="-Djava.security.properties=local-java.security" /opt/xmlsectool/xmlsectool.sh --sign ...

As described in java.security, the above example augments the JDK's version of java.security; it might just contain a single line:

1 security.provider.14=SunPKCS11 /path/to/config.cfg

Alternatively, you can override the master version of java.security entirely by using == instead of = like this:

1 JVMOPTS="-Djava.security.properties==local-java.security" /opt/xmlsectool/xmlsectool.sh --sign ...

I this case, local-java.security must include the complete configuration normally found in the master version of java.security.

Upgrading from a previous version of xmlsectool

In Java 9, a change was made to the way security providers such as the SunPKCS11 provider are handled, and in particular configured. This has necessarily resulted in changes to the way xmlsectool provides this functionality.

If in a previous version of xmlsectool you used a command line with both --pkcs11Config and --keystoreProvider options, like this:

1 ... --pkcs11Config /path/to/config.cfg --keystoreProvider sun.security.pkcs11.SunPKCS11 ...

... you will now receive the following warning message:

1 WARN DEPRECATED - command-line option '--keystoreProvider', (now ignored when used with --pkcs11Config): This will be removed in the next major version of this software

You should update your command line to omit the --keystoreProvider option in this case. This will become an ERROR in a future version of xmlsectool.

If in a previous version of xmlsectool you used a command line with a dummy --pkcs11Config option and no --keystoreProvider option, like this:

1 ... --pkcs11Config DUMMY ...

... you will now receive an error message saying that the file DUMMY does not exist:

1 2 ERROR CredentialHelper - PKCS#11 configuration file 'DUMMY' does not exist ERROR XMLSecTool - Error accessing PKCS11 store

This old style of static configuration is equivalent to the "--keystore /dev/null --keystoreType PKCS11" mechanism described above, and you should update your command line accordingly.