Skip to main content

Integrating with jarsigner

Overview

This guide provides instructions on how to configure jarsigner to use keys and certificates from Next-Gen Trust Security (NGTS).

By following these steps, you can sign your Java applications using a centrally managed key without exposing the private key material on your local machine.

Before you begin

Before you can integrate jarsigner, you must have the following prerequisites met:

  • Java Development Kit (JDK) installed — The jarsigner and keytool utilities are part of the JDK. Ensure the JDK is installed and the bin directory is in your system's PATH.
  • Code Sign Client installed — This provides the PKCS#11 library that jarsigner uses to communicate with the service.
  • JAR file to sign — Have a Java application (.jar file) ready for signing.

How do I get started?

The integration process involves three main steps:

  1. Create a PKCS#11 configuration file — a text file that tells the Java security provider where to find the PKCS#11 library.
  2. Sign the JAR file — run the jarsigner command, pointing it to your configuration file and specifying the key to use.
  3. Verify the signature — use jarsigner's verification command to confirm the signature is valid.

Linux example integration

Additional configuration required. This integration method will fail on modern JDKs (Java 9 or newer) without the following configuration.

  1. Set Java VM options — Modern JDKs hide the PKCS#11 provider by default. Export an environment variable to expose it before running keytool or jarsigner.

    export _JAVA_OPTIONS="--add-opens=jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED"
  2. Add client binaries to the system PATH (portable package) — If using the portable package, add the client's bin and lib directories to your PATH.

    export PATH=$PATH:/path/to/codesign-client/bin:/path/to/codesign-client/lib

Create a configuration file (for example, /root/venafipkcs11.conf):

name = VenafiPKCS11
library ="/opt/venafi/codesign/lib/venafipkcs11.so"
slot = 0

If you want to configure it globally, add a provider to java.security, which applies to all use of Java on the system. For example:

...
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.pkcs11.SunPKCS11 /root/venafipkcs11.conf
...

Sign the JAR. Replace <your-jar-file> with the JAR you want to sign, <your-key-label> with the label of your Signing Key, and <path-to-config> with the path to your PKCS#11 configuration file:

jarsigner \
-verbose <your-jar-file> "<your-key-label>" \
-keystore NONE \
-storetype PKCS11 \
-certs \
-storepass none \
-providerclass sun.security.pkcs11.SunPKCS11 \
-providerArg <path-to-config>

Verify a JAR with the Code Sign Client PKCS#11 library:

jarsigner -verify \
-keystore NONE \
-storetype PKCS11 \
-storepass none \
-providerclass sun.security.pkcs11.SunPKCS11 \
-providerArg <path-to-config> <your-jar-file>

Important notes:

  • You may see warnings about an invalid certificate chain. This is expected if the default Java trust store does not include the signing certificate's chain. Signing is still successful.
  • If you run jarsigner -verify <your-jar-file> without PKCS#11 options, it may fail due to trust chain issues. This does not affect signing.
  • Troubleshooting:
    • Provider not found — Check the _JAVA_OPTIONS export.
    • Library not found — Verify the path in your configuration file.
    • Alias not found — Ensure the key label matches what is configured in NGTS.

macOS example integration

Additional configuration required. This integration method will fail on modern JDKs (Java 9 or newer) without the following configuration.

  1. Set Java VM options:

    export _JAVA_OPTIONS="--add-opens=jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED"
  2. Add client binaries to the system PATH (portable package):

    export PATH=$PATH:/path/to/codesign-client/bin:/path/to/codesign-client/lib

Create a configuration file (for example, /Users/signcode/venafipkcs11.conf):

name = VenafiPKCS11
#library = "/Library/Venafi/CodeSigning/lib/venafipkcs11spy.so"
library ="/Library/Venafi/CodeSigning/lib/venafipkcs11.so"
slot = 0

Sign the JAR:

jarsigner \
-verbose /Users/codesign/tosign/test.jar Sample-Development-Environment \
-keystore NONE \
-storetype PKCS11 \
-certs \
-storepass none \
-providerclass sun.security.pkcs11.SunPKCS11 \
-providerArg /Users/codesign/venafipkcs11.conf

Verify the JAR using the same steps included in the Linux section.

Windows PKCS#11 example integration

Prerequisites for PKCS#11. This integration method is complex and will fail on modern systems without the following configuration. These steps are required when using a modern JDK (Java 9+) and/or the portable package (.zip) client.

  1. Set Java VM options before running keytool or jarsigner:

    For PowerShell:

    $env:_JAVA_OPTIONS = "--add-opens=jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED"

    For Windows CMD:

    set _JAVA_OPTIONS=--add-opens=jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED
  2. Add client binaries to the system PATH (portable package):

    For PowerShell:

    $env:Path = $env:Path + ";C:\path\to\codesign-client\bin;C:\path\to\codesign-client\PKCS11"

    For Windows CMD:

    set PATH=%PATH%;C:\path\to\codesign-client\bin;C:\path\to\codesign-client\PKCS11

Create a configuration file.

Example for the .msi installer (admin), pointing to the default installation directory:

name = VenafiPKCS11
library = "c:\\Program Files\\Venafi CodeSign Protect\\PKCS11\\VenafiPkcs11.dll"
slot = 0

Example for the portable package (non-admin). This example assumes the client was extracted to C:\codesign-client; update the path to match your own extraction location:

name = VenafiPKCS11
library = "c:\\codesign-client\\PKCS11\\venafipkcs11.dll"
slot = 0

List contents:

keytool ^
-list ^
-keystore none ^
-storetype PKCS11 ^
-providerclass sun.security.pkcs11.SunPKCS11 ^
-providerArg c:\venafipkcs11.conf

List alias names:

keytool ^
-keystore NONE ^
-storetype PKCS11 -list

Sign the JAR:

jarsigner ^
-verbose c:\tosign\jrt-fs.jar Sample-Development-Environment ^
-keystore NONE ^
-storetype PKCS11 ^
-certs ^
-storepass none ^
-providerclass sun.security.pkcs11.SunPKCS11 ^
-providerArg c:\venafipkcs11.conf

Windows CSP example integration

Admin privileges required. The Windows CSP integration is the recommended method for Windows, but it requires the full, system-wide installation of the Code Sign Client using the installer (.msi).

This method is not compatible with the non-admin portable package (.zip). The CSP driver must be registered in the Windows system registry, which is not possible with a non-admin portable installation.

The following is a sample command line for jarsigner. Use the correct path to jarsigner on your system:

cd "C:\\Program Files\\jdk\\microsoft_dist_openjdk_1.8.0.9\\bin"
jarsigner.exe^
-verbose^
-storetype Windows-My^
-Keystore NONE c:\Source\android-rottentomatoes-demo-master\libs\picasso-2.1.1.jar "Sample Code Signers Are Us, LLC"^
-tsa http://timestamp.digicert.com

In the example above, the -storetype parameter specifies the local trust store, which triggers the CSP. The key being used has a common name of "Sample Code Signers Are Us, LLC", and the binary being signed is the picasso-2.1.1.jar file. This sample also uses a DigiCert timestamp server.

What's next

You can now integrate this jarsigner command into your automated build and release pipelines to ensure all your Java applications are securely signed.