Code Signing (JAR) with Primus HSM
This guide covers two end-to-end workflows for signing Java Archives (JARs) with private keys stored on a Securosys Primus HSM:
- Self-signed certificate chain - Root CA → Intermediate CA → Code Signing, fully managed on the HSM.
- CA-issued certificate - Code-signing key on the HSM, certificate issued by an external CA (DigiCert, SwissSign, etc.).
All examples use <HSM> as shorthand.
-host <host> -port <port> -user <user> -password <password> -proxyuser <proxyuser> -proxypassword <proxypassword>
Note: When using Securosys CloudHSM with JarsignerX or KeytoolX, proxy credentials are required. In this case, use the parameters -proxyuser and -proxypassword.
Please note that these parameters differ from the standard Primus tools usage, which uses
-primusproxyuser and -primusproxypassword.
Workflow 1: Self-Signed Certificate Chain
Use this workflow for internal distribution, testing, or when you manage your own PKI.
Create the Root CA
# Generate RSA 4096-bit key pair
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-genkeypair -alias root-ca-key \
-keyalg RSA -keysize 4096 -sigalg SHA256withRSA \
-dname "CN=My Root CA,OU=IT,O=My Organisation,C=CH" \
-keysize 4096 \
-validity 3650
# Re-issue self-signed cert with CA extensions (BasicConstraints)
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-selfcert -alias root-ca-key \
-sigalg SHA256withRSA \
-dname "CN=My Root CA,OU=IT,O=My Organisation,C=CH" \
-validity 3650 \
-ext bc=ca:true -ext ku=keyCertSign,cRLSign
# Export root certificate
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-exportcert -alias root-ca-key -rfc -file root-ca.pem
Create the Intermediate CA
# Generate key pair
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-genkeypair -alias intermediate-ca-key \
-keyalg RSA -keysize 4096 -sigalg SHA256withRSA \
-dname "CN=My Intermediate CA,OU=IT,O=My Organisation,C=CH" \
-keysize 4096 \
-validity 1825
# Generate CSR
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-certreq -alias intermediate-ca-key \
-sigalg SHA256withRSA -file intermediate-ca.csr
# Root CA signs the intermediate certificate
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-gencert -alias root-ca-key \
-infile intermediate-ca.csr -outfile intermediate-ca.pem \
-validity 1825 \
-ext bc=ca:true -ext ku=keyCertSign,cRLSign -rfc
Create the Code-Signing Key
# Generate RSA 4096-bit key pair
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-genkeypair -alias codesign-key \
-keyalg RSA -keysize 4096 -sigalg SHA256withRSA \
-dname "CN=My Code Signing,OU=IT,O=My Organisation,C=CH" \
-keysize 4096 \
-validity 730
# Generate CSR
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-certreq -alias codesign-key \
-sigalg SHA256withRSA -file codesign.csr
# Intermediate CA signs the code-signing certificate
java -jar primus-tools.jar KeytoolX \
<HSM> \
-storetype Primus \
-gencert -alias intermediate-ca-key \
-infile codesign.csr -outfile codesign.pem \
-validity 730 \
-ext eku=codeSigning -ext ku=digitalSignature -rfc
Assemble the Chain
cat codesign.pem intermediate-ca.pem root-ca.pem > codesign-fullchain.pem
The file should contain three certificates in order: end-entity → intermediate → root.
Continue now with Workflow 3 - Sign & Verify.
Workflow 2: CA-Issued Certificate
Use this workflow for public distribution where JARs must be signed with a certificate trusted by end users (e.g. DigiCert, SwissSign, GlobalSign).
Create Key and Generate CSR
java -jar primus-tools.jar KeytoolX <HSM> -storetype Primus \
-genkeypair -alias codesign-key \
-keyalg RSA -keysize 4096 -sigalg SHA256withRSA \
-dname "CN=My Code Signing,OU=IT,O=My Organisation,C=CH" \
-validity 730
java -jar primus-tools.jar KeytoolX <HSM> -storetype Primus \
-certreq -alias codesign-key \
-sigalg SHA256withRSA -file codesign.csr
Submit CSR to Your CA
- Submit
codesign.csrto your CA's code-signing certificate portal. - Complete the CA's validation process.
- Download the signed certificate and full chain as a PEM file (name it:
codesign-fullchain.pem).
The chain PEM should contain certificates in order: end-entity → intermediate(s) → root.
Workflow 3: Sign & Verify
Sign
java \
--add-opens=java.base/javax.security.auth.x500=ALL-UNNAMED \
--add-opens=java.base/sun.security.x509=ALL-UNNAMED \
-jar primus-tools.jar JarsignerX \
<HSM> \
-storetype Primus -providerName SecurosysPrimusXSeries \
-tsa http://tsa.swisssign.net \
-tsa http://timestamp.digicert.com \
-digestalg SHA-256 \
-certchain codesign-fullchain.pem \
myapp.jar codesign-key
| Parameter | Description |
|---|---|
| tsa | The timestamp authority |
| myapp.jar | the jar to be signed |
| codesign-key | the HSM KeyName |
Verify
Online (via HSM):
java -jar primus-tools.jar JarsignerX <HSM> -verify myapp.jar
Offline (no HSM needed):
keytool -importcert -alias root-ca-key -file codesign-fullchain.pem -keystore truststore.jks -storepass changeit -noprompt
keytool -importcert -alias intermediate-ca-key -file intermediate-ca.pem -keystore truststore.jks -storepass changeit -noprompt
keytool -importcert -alias codesign-key -file codesign.pem -keystore truststore.jks -storepass changeit -noprompt
jarsigner -verify -keystore truststore.jks -storepass changeit myapp.jar
CA-issued certificates are trusted by default; standard jarsigner works:
jarsigner -verify myapp.jar
Known Issues
- KeytoolX
-importcertcorrupts Private Key Entry, read this for details