Navigating Code Signing and Notarization for Java Applications
Distributing cross-platform Java applications using jpackage is a powerful way to provide native-feeling installers. However, modern operating systems have implemented stringent security layers—Gatekeeper on macOS and SmartScreen on Windows—to protect users from malicious software. To bypass these "unidentified developer" warnings and "blocked for your protection" alerts, you must establish a formal developer identity and integrate binary signing and attestation into your build pipeline.
This guide details the requirements and processes for both Apple and Microsoft ecosystems specifically tailored for a Java engineer using jpackage.
1. The Apple Ecosystem: macOS Gatekeeper and Notarization
Apple requires two distinct steps: Signing (identifying who you are) and Notarization (Apple scanning your app for malware).
Establishing Credentials
- Enroll in the Apple Developer Program: You must register as an individual or organization ($99 USD/year).
- Generate Certificates: Use the Apple Developer Portal or Xcode to create:
- Developer ID Application: Used to sign the application binaries and app bundle.
- Developer ID Installer: Used to sign the
.pkg installer generated by jpackage.
- Install on Build Machine: Download these certificates and install them into your macOS Keychain.
The jpackage Workflow
When running jpackage on macOS, you can automate the signing of the app bundle using specific flags:
jpackage \
--type pkg \
--name "MyJavaApp" \
--input input_dir \
--main-jar myapp.jar \
--mac-sign \
--mac-signing-key-user-name "Developer ID Application: Your Name (ID)" \
--mac-package-signing-prefix "com.yourcompany."
The Critical Step: Notarization
Signing alone is no longer enough for macOS. You must submit your signed package to Apple’s Notary Service.
- Create an App-Specific Password: Go to your Apple ID management page and generate a password for
notarytool.
- Submit for Notarization:
xcrun notarytool submit MyJavaApp.pkg \
--apple-id "your-email@example.com" \
--password "your-app-specific-password" \
--team-id "YOUR_TEAM_ID" \
--wait
- Staple the Ticket: Once approved, "staple" the notarization ticket to the package so it can be verified offline.
xcrun stapler staple MyJavaApp.pkg
2. The Microsoft Ecosystem: Windows SmartScreen and Authenticode
Windows uses Authenticode signing to verify the publisher and SmartScreen to determine the reputation of the executable.
Establishing Credentials
- Purchase a Code Signing Certificate: Unlike Apple, Microsoft does not sell certificates directly. You must buy one from a third-party Certificate Authority (CA) like DigiCert, Sectigo, or GlobalSign.
- Standard Code Signing: Cheaper, but you must "build reputation" over time before SmartScreen warnings disappear.
- EV (Extended Validation) Code Signing: Requires a more rigorous identity check. It provides instant reputation with SmartScreen, meaning no warnings from day one.
- Hardware Security Modules (HSM): As of 2023, CAs require that private keys for code signing be stored on FIPS-compliant hardware (like a YubiKey or a cloud HSM).
The jpackage Workflow
jpackage can trigger the signing process if the signtool.exe utility (from the Windows SDK) is in your PATH.
jpackage \
--type msi \
--name "MyJavaApp" \
--win-upgrade-uuid some-uuid \
--win-shortcut \
--win-menu \
--win-sign \
--win-signing-certificate-subject-name "Your Company, Inc."
Note: If you are using an EV certificate on a physical USB token, jpackage will prompt for your hardware token's PIN during the build process.
Manual Signing (Alternative)
Sometimes it is more reliable to sign the output of jpackage manually using signtool:
signtool sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /n "Your Company, Inc." MyJavaApp.msi
3. Automation and CI/CD Considerations
Integrating these steps into a CI/CD pipeline (like GitHub Actions or GitLab CI) presents challenges due to the requirement for physical hardware (Windows) and macOS-specific tools.
For macOS:
- Use a macOS runner.
- Store your certificates as Base64-encoded secrets and import them into a temporary keychain during the build.
- Store the App-Specific Password as a secret for the
notarytool step.
For Windows:
- Cloud HSMs: To avoid physical USB tokens, use cloud-based signing services like Azure Trusted Signing or DigiCert KeyLocker. These allow your CI/CD pipeline to sign binaries using an API key and a remote private key.
jpackage does not natively support cloud signing providers easily; you may need to run jpackage without the --win-sign flag and then run a custom signing script using the cloud provider's CLI tool on the resulting .msi or .exe.
Summary of Requirements
| Feature |
macOS (Apple) |
Windows (Microsoft) |
| Program |
Apple Developer Program ($99/yr) |
Third-party CA (e.g., DigiCert) |
| Identity Verification |
Managed by Apple |
Managed by CA (Vetting process) |
| Hardware Requirement |
Any Mac |
HSM (USB Token or Cloud HSM) |
| Attestation Step |
Notarization (notarytool) |
SmartScreen Reputation (EV recommended) |
| Primary Tool |
jpackage + xcrun |
jpackage + signtool |
By implementing these steps, you transform your Java application from "untrusted software" into a professional, verified product that installs seamlessly on your users' machines.
Navigating Code Signing and Notarization for Java Applications
Distributing cross-platform Java applications using
jpackageis a powerful way to provide native-feeling installers. However, modern operating systems have implemented stringent security layers—Gatekeeper on macOS and SmartScreen on Windows—to protect users from malicious software. To bypass these "unidentified developer" warnings and "blocked for your protection" alerts, you must establish a formal developer identity and integrate binary signing and attestation into your build pipeline.This guide details the requirements and processes for both Apple and Microsoft ecosystems specifically tailored for a Java engineer using
jpackage.1. The Apple Ecosystem: macOS Gatekeeper and Notarization
Apple requires two distinct steps: Signing (identifying who you are) and Notarization (Apple scanning your app for malware).
Establishing Credentials
.pkginstaller generated byjpackage.The
jpackageWorkflowWhen running
jpackageon macOS, you can automate the signing of the app bundle using specific flags:The Critical Step: Notarization
Signing alone is no longer enough for macOS. You must submit your signed package to Apple’s Notary Service.
notarytool.2. The Microsoft Ecosystem: Windows SmartScreen and Authenticode
Windows uses Authenticode signing to verify the publisher and SmartScreen to determine the reputation of the executable.
Establishing Credentials
The
jpackageWorkflowjpackagecan trigger the signing process if thesigntool.exeutility (from the Windows SDK) is in your PATH.Note: If you are using an EV certificate on a physical USB token,
jpackagewill prompt for your hardware token's PIN during the build process.Manual Signing (Alternative)
Sometimes it is more reliable to sign the output of
jpackagemanually usingsigntool:3. Automation and CI/CD Considerations
Integrating these steps into a CI/CD pipeline (like GitHub Actions or GitLab CI) presents challenges due to the requirement for physical hardware (Windows) and macOS-specific tools.
For macOS:
notarytoolstep.For Windows:
jpackagedoes not natively support cloud signing providers easily; you may need to runjpackagewithout the--win-signflag and then run a custom signing script using the cloud provider's CLI tool on the resulting.msior.exe.Summary of Requirements
notarytool)jpackage+xcrunjpackage+signtoolBy implementing these steps, you transform your Java application from "untrusted software" into a professional, verified product that installs seamlessly on your users' machines.