jarsigner: Sign and Verify JARs and Legacy APKs in CI
jarsigner signs a JAR (or a v1-scheme APK) with a keystore key and jarsigner -verify checks the signature.
jarsigner is the JDK JAR signer. It still signs library JARs and can produce the legacy v1 APK signature, but for modern APKs apksigner (with v2+) is the right tool. Its flags are what make it scriptable in CI.
What it does
jarsigner attaches a signature block to a JAR using a key from a keystore, and -verify checks it. For APKs it only produces the v1 (JAR) signature; it cannot create the v2+ APK Signature Schemes, which is why Android moved to apksigner. It is bundled with the JDK.
Common usage
jarsigner -keystore release.keystore \
-storepass "$KS_PASS" -keypass "$KEY_PASS" \
-sigalg SHA256withRSA -digestalg SHA-256 \
app-unsigned.apk upload
jarsigner -verify -verbose -certs app-unsigned.apkOptions
| Flag | What it does |
|---|---|
| -keystore <file> | Keystore holding the signing key |
| -storepass / -keypass | Keystore and key passwords |
| -sigalg / -digestalg | Signature and digest algorithms |
| -verify | Verify signatures instead of signing |
| -certs -verbose | Show certificate details on verify |
| <file> <alias> | JAR/APK to sign and the key alias |
In CI
For JAR artifacts (Maven publish, plugins), jarsigner is the right tool. For APKs, prefer apksigner so you get v2/v3 signatures that modern Android requires; if you must use jarsigner for an APK, do it before zipalign, then align. Source passwords from secrets, not the command line.
Common errors in CI
"jarsigner error: java.lang.RuntimeException: keystore load: keystore password was incorrect" means a wrong -storepass. "jarsigner: Certificate chain not found for: <alias>" means the alias does not exist or lacks a cert chain. On verify, "jar is unsigned" means no signature is present. For APKs, an app that installs on older Android but fails "did not verify" on newer ones signals a missing v2 signature; use apksigner.