code signing · java
Code-signing JAR files with an existing certificate on Windows
Already have a code-signing certificate and need to sign a JAR on Windows? These are the commands. The two things to check first are whether the keystore contains the private key and which alias identifies it.
The basic workflow is:
- Install a JDK so
keytoolandjarsignerare available. - Open the keystore containing the certificate and its private key.
- Identify the alias for the signing key.
- Sign the JAR.
- Timestamp the signature.
- Verify the result.
Oracle’s tool references are the source of truth for keytool and jarsigner behaviour:
Install the JDK
Install a current supported JDK, then open a terminal in the JDK bin directory or add it to PATH.
For example:
cd "C:\Program Files\Java\jdk-14.0.1\bin"
Use whatever JDK version is appropriate for your environment. The commands below are the important part, not the exact path.
Use the existing keystore
A .p12 or .pfx is already a PKCS12 keystore. If it contains the signing certificate and private key, jarsigner can use it directly. There’s no need to convert it into JKS and back again, which is the detour the original version of these notes took.
A .cer containing only the public certificate isn’t enough to sign. And if the private key lives on a hardware token, use the appropriate provider for that token; these file-based commands assume an exportable key in a PKCS12 file.
Find the alias
List the keystore contents:
keytool -list -keystore c:\jarfiles\duff.p12 -storetype PKCS12 -v
Find the alias whose entry type is PrivateKeyEntry, rather than trustedCertEntry. You need that alias when signing. Mine was codesigningcert.
Sign the JAR
Sign the JAR and include a timestamp authority:
jarsigner `
-keystore c:\jarfiles\duff.p12 `
-storetype PKCS12 `
-tsa http://timestamp.digicert.com `
c:\jarfiles\myjar.jar `
codesigningcert
The timestamp matters. Without a timestamp, the signature may stop validating cleanly after the signing certificate expires. With a trusted timestamp, verifiers can evaluate whether the certificate was valid at signing time.
Avoid putting keystore passwords directly into shell history. If you need automation, use your CI/CD secret store or a dedicated signing system rather than scattering signing credentials around build scripts.
Verify the signature
Verify the JAR:
jarsigner -verify c:\jarfiles\myjar.jar -verbose -certs -strict
-strict makes severe warnings affect the exit status. In PowerShell, check $LASTEXITCODE as well as the text; “jar verified” can appear alongside trust warnings. You care about:
- Whether the JAR verifies.
- Whether the certificate chain is trusted by the verifier.
- Whether the signature includes a timestamp.
- Whether there are unsigned entries you did not expect.
- Whether weak algorithms or expired certificates are reported.
One detail that is easy to miss: JAR signatures cover individual entries. Unsigned files can be added to an otherwise signed archive. Check the unsigned-entry warnings on the final artifact, after packaging has finished, rather than assuming the presence of a signature covers every file. Jarsigner verification behavior.