Walk through the practical workflow of signing and verifying a JAR with keytool and jarsigner.
answer
- keytool = keys/keystore; jarsigner = sign/verify
- genkeypair → self-signed cert under an alias
- sign writes MANIFEST digests + .SF + .RSA/.EC block
- jarsigner -verify -certs
- add -tsa timestamp so it survives cert expiry
basics
~20 sUse keytool to create a keypair/certificate in a keystore, then jarsigner to sign the JAR with that key. To check a JAR, run 'jarsigner -verify' which recomputes hashes and validates the signature against the certificate.
solid answer
~50 sFirst you need a key. 'keytool -genkeypair' creates a private key plus a self-signed certificate stored under an alias in a keystore (a password-protected key/cert file, e.g. a .jks or PKCS12). For a real publisher identity you'd instead generate a CSR, get it signed by a CA, and import the chain. Then 'jarsigner -keystore ks.jks app.jar myalias' signs: it hashes every entry, writes the digests into META-INF/MANIFEST.MF, creates an ALIAS.SF signature file, and an ALIAS.RSA/EC/DSA signature block holding the actual signature plus the certificate. To check, anyone runs 'jarsigner -verify -verbose -certs app.jar', which recomputes each digest, validates the signature against the embedded cert, and checks the cert chain/validity. You should also add a timestamp ('-tsa <url>') so signatures stay valid after the signing certificate expires. Verification proving 'jar is verified' still leaves trust-of-the-cert as a separate decision.
code
java · 18 lines// Shell workflow (annotated; not Java code) ---------------------
//
// 1) create a key pair + self-signed cert in a PKCS12 keystore
// keytool -genkeypair -alias myalias -keyalg RSA -keysize 3072 \
// -validity 365 -keystore ks.jks -storetype PKCS12
//
// 2) sign the jar, with a trusted timestamp
// jarsigner -keystore ks.jks -tsa http://timestamp.example/tsa \
// app.jar myalias
//
// 3) verify (recompute digests + check signature/chain)
// jarsigner -verify -verbose -certs app.jar
// -> prints "jar verified." plus per-entry signer info
//
// Resulting META-INF entries:
// MANIFEST.MF (per-entry SHA-256 digests)
// MYALIAS.SF (digest of the manifest)
// MYALIAS.RSA (signature over .SF + certificate chain)go deeper
Knows the two tools by role: keytool makes a key, jarsigner signs and verifies a JAR.
Can run the genkeypair → sign → verify commands and name the META-INF files that signing produces.
Explains CSR/CA flow, timestamping rationale, key custody, algorithm hygiene, and that verification is not trust.
Owns the signing infrastructure: HSM/key custody, rotation/revocation, CA strategy, CI signing automation, and integration with broader supply-chain attestation.
## The two tools The JDK ships two command-line tools for this: - **`keytool`** — manages **keystores**: it creates key pairs and certificates, imports/exports certs, and generates certificate signing requests. A **keystore** is a single password-protected file holding entries indexed by an **alias** (a short name you pick); each entry is either a private key + its certificate chain, or a trusted certificate. - **`jarsigner`** — uses a key from a keystore to **sign** a JAR, and (with `-verify`) to **verify** one. ## Step 1 — create a key pair (keytool) ``` keytool -genkeypair -alias myalias -keyalg RSA -keysize 3072 \ -validity 365 -keystore ks.jks -storetype PKCS12 ``` This generates a **private key** (kept secret) and a matching **public key**, wraps the public key in a **self-signed certificate** (you are the issuer), and stores both under `myalias`. It prompts for a Distinguished Name (CN, O, etc.) and keystore/key passwords. `-storetype PKCS12` is the modern, portable keystore format (the old proprietary `JKS` is legacy). ## Step 1b — getting a real (CA-backed) identity A self-signed cert proves only key consistency. For third-party trust: 1. `keytool -certreq` produces a **CSR** (Certificate Signing Request) — your public key + identity to be vouched for. 2. A **Certificate Authority** verifies you and returns a signed certificate (plus intermediates). 3. `keytool -importcert` imports that chain back under the alias, replacing the self-signed cert. ## Step 2 — sign (jarsigner) ``` jarsigner -keystore ks.jks -tsa http://timestamp.example/tsa \ app.jar myalias ``` jarsigner: hashes every entry and writes those digests into `META-INF/MANIFEST.MF`; creates `META-INF/MYALIAS.SF` (a signature file containing a digest of the manifest); and creates `META-INF/MYALIAS.RSA` (or `.EC`/`.DSA`) — the **signature block**, holding the digital signature over the `.SF` file plus your certificate chain. The block extension reflects the key algorithm. **Timestamping (`-tsa`)** is important: it asks a trusted **Time Stamp Authority** to attest *when* you signed. Without it, once your signing certificate expires the signature is treated as invalid; with a timestamp, verifiers accept that the signature was valid at signing time even after the cert expires. ## Step 3 — verify (jarsigner) ``` jarsigner -verify -verbose -certs app.jar ``` This recomputes each entry's digest and compares to the manifest (integrity), verifies the `.SF` signature against the certificate's public key (authenticity), and checks the certificate's validity and chain. Output `jar verified.` means cryptography passed. Watch for warnings: an **expired certificate** (mitigated by a timestamp), a **self-signed** chain (no CA), or **unsigned entries** present in the JAR. ## Key custody and algorithm hygiene - The **private key must stay secret** — leaking it lets anyone impersonate you; rotate and revoke if compromised. Protect the keystore password; consider an HSM for production keys. - Prefer strong algorithms (RSA ≥2048/3072 or EC) and modern hashes (SHA-256+); weak/legacy algorithms (MD5, SHA-1, small keys) are rejected or warned about by current JDKs. ## Verification ≠ trust `jar verified.` only means the bytes are unchanged and signed by *some* certificate. Deciding whether that certificate is one you trust — by CA chain or by pinning — is a separate policy step the tooling does not make for you. ## Note on sealing This workflow is orthogonal to **sealing**: sealing is a manifest attribute about single-JAR origin and uses no keys or tools beyond setting a header. You can sign a sealed JAR or an unsealed one.
- Why add a timestamp with -tsa when signing?A timestamp from a trusted Time Stamp Authority records when the JAR was signed. Without it, the signature is rejected once the signing certificate expires. With it, verifiers accept that the signature was valid at signing time, so the artifact stays verifiable long after the cert's validity window ends.
- What is the difference between keytool and jarsigner?keytool manages the keystore — generating key pairs and certificates, creating CSRs, importing/exporting certs. jarsigner consumes a key from that keystore to sign a JAR, and with -verify recomputes digests and validates the signature against the embedded certificate. One makes the credentials, the other uses them.
saying these in an interview costs you the question
- Saying jarsigner creates the key pair — keytool does that; jarsigner only signs/verifies.
- Thinking 'jar verified.' means the certificate is trusted — it only means cryptography passed; trust is separate.
- Omitting timestamping and being surprised signatures break after cert expiry.
- Committing or sharing the private key / keystore password — the private key must stay secret.
- Using SHA-1/MD5 or undersized keys, which modern JDKs warn about or disable.