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
bindirectory 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 (
.jarfile) ready for signing.
How do I get started?
The integration process involves three main steps:
- Create a PKCS#11 configuration file — a text file that tells the Java security provider where to find the PKCS#11 library.
- Sign the JAR file — run the jarsigner command, pointing it to your configuration file and specifying the key to use.
- 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.
-
Set Java VM options — Modern JDKs hide the PKCS#11 provider by default. Export an environment variable to expose it before running
keytoolorjarsigner.export _JAVA_OPTIONS="--add-opens=jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED" -
Add client binaries to the system PATH (portable package) — If using the portable package, add the client's
binandlibdirectories to yourPATH.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_OPTIONSexport. - Library not found — Verify the path in your configuration file.
- Alias not found — Ensure the key label matches what is configured in NGTS.
- Provider not found — Check the
macOS example integration
Additional configuration required. This integration method will fail on modern JDKs (Java 9 or newer) without the following configuration.
-
Set Java VM options:
export _JAVA_OPTIONS="--add-opens=jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED" -
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.
-
Set Java VM options before running
keytoolorjarsigner: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 -
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.