Jsign is a Java implementation of Microsoft Authenticode that lets you sign and timestamp executable files for Windows, Microsoft Installers (MSI), Cabinet files (CAB) and scripts (PowerShell, VBScript, JScript, WSF). Jsign is platform independent and provides an alternative to native tools like signcode/signtool on Windows or the Mono development tools on Unix systems.
Jsign comes as an easy to use task/plugin for the main build systems (Maven, Gradle, Ant). It's especially suitable for signing executable wrappers and installers generated by tools like NSIS, msitools, install4j, exe4j or launch4j. Jsign can also be used programmatically or standalone as a command line tool.
Jsign is free to use and licensed under the Apache License version 2.0.
Features
- Platform independent signing of Windows executables, DLLs, Microsoft Installers (MSI), Cabinet files (CAB) and scripts (PowerShell, VBScript, JScript, WSF)
- Timestamping with retries and fallback on alternative servers (RFC 3161 and Authenticode protocols supported)
- Supports multiple signatures per file, for all file types
- Extracts and embeds detached signatures to support reproducible builds
- Hashing algorithms: MD5, SHA-1, SHA-256, SHA-384 and SHA-512
- Keystores supported:
- PKCS#12, JKS and JCEKS files
- PKCS#11 hardware tokens (YubiKey, Nitrokey, etc)
- Cloud key management systems (Azure Key Vault, DigiCert ONE, Google Cloud KMS, SSL.com eSigner)
- Private key formats: PVK and PEM (PKCS#1 and PKCS#8), encrypted or not
- Certificates: PKCS#7 in PEM and DER format
- Build tools integration (Maven, Gradle, Ant)
- Command line signing tool
- Authenticode signing API (Javadoc)
Ant Task
Here is an example showing how the signing works with Ant, using a Java keystore:
<taskdef name="jsign" classname="net.jsign.JsignTask" classpath="jsign-4.1.jar"/> <jsign file="application.exe" name="My Application" url="http://www.example.com" keystore="keystore.jks" alias="test" storepass="password" tsaurl="http://timestamp.sectigo.com"/>
Another example with SPC
and PVK
files commonly used with signcode.exe
:
<jsign file="application.exe" certfile="certificate.spc" keyfile="key.pvk" keypass="password" tsaurl="http://timestamp.digicert.com"/>
The task also accepts a fileset to sign multiple files:
<jsign keystore="keystore.p12" alias="test" storepass="password"> <fileset dir="build/binaries" includes="*.exe"/> </jsign>
Attribute | Description | Required |
---|---|---|
file | The file to be signed. The supported files are Windows executables (EXE), DLLs, Microsoft Installers (MSI), Cabinet files (CAB) and scripts (PowerShell, VBScript, JScript, WSF) | Yes, unless a fileset is specified. |
name | The name of the application | No |
url | The URL of the application | No |
keystore | The keystore file, or the SunPKCS11 configuration file | Yes, unless certfile and keyfile are specified. |
storepass |
The password to open the keystore. The password can be loaded from a file by using the file: prefix
followed by the path of the file, or from an enviroment variable by using the env: prefix followed
by the name of the variable.
|
No |
storetype |
The type of the keystore:
|
No, automatically detected for file based keystores. |
alias | The alias of the certificate used for signing in the keystore. | Yes, if keystore is specified and more than one alias exist |
certfile | The file containing the PKCS#7 certificate chain (.p7b or .spc files). |
Yes, unless keystore is specified. |
keyfile |
The file containing the private key. PEM and PVK files are supported.
|
|
keypass |
The password of the private key. When using a keystore, this parameter can be omitted if the keystore shares
the same password. The password can be loaded from a file by using the file: prefix followed by
the path of the file, or from an enviroment variable by using the env: prefix followed by the
name of the variable.
|
No |
alg | The digest algorithm (SHA-1, SHA-256, SHA-384 or SHA-512) | No; defaults to SHA-256 |
tsaurl |
The URL of the timestamping authority, either RFC 3161 or Authenticode services.
You can use for example the Sectigo (http://timestamp.sectigo.com)
or the DigiCert (http://timestamp.digicert.com) services. Several URLs separated by a comma can be specified to fallback on alternative servers. |
No |
tsmode | The timestamping mode (RFC3161 or Authenticode) | No; defaults to Authenticode |
tsretries | The number of retries for timestamping | No; defaults to 3 |
tsretrywait | The number of seconds to wait between timestamping retries | No; defaults to 10 seconds |
replace | Tells if previous signatures should be replaced. | No; defaults to "false" |
encoding | The encoding of the script to be signed (if it doesn't contain a byte order mark). | No; defaults to "UTF-8" |
detached |
Tells if a detached signature should be generated or reused. The detached signature
is a file in the same directory using the name of the file signed with the .sig
suffix added (for example application.exe.sig ).
|
No; defaults to "false" |
Maven plugin
Here is an example showing how the signing works with Maven. The parameters
are the same as those described above for the Ant task. The execution is bound
by default to the package
phase.
<build> <plugins> <plugin> <groupId>net.jsign</groupId> <artifactId>jsign-maven-plugin</artifactId> <version>4.1</version> <executions> <execution> <goals> <goal>sign</goal> </goals> <configuration> <file>application.exe</file> <name>My Application</name> <url>http://www.example.com</url> <keystore>keystore.jks</keystore> <alias>test</alias> <storepass>password</storepass> </configuration> </execution> </executions> </plugin> </plugins> </build>
It's possible to sign multiple files by using a fileset
element instead of file
:
... <configuration> <fileset> <directory>target</directory> <includes> <include>*.exe</include> </includes> </fileset> <keystore>keystore.jks</keystore> <alias>test</alias> <storepass>password</storepass> </configuration> ...
Gradle plugin
Here is an example showing how to use Jsign with Gradle. The parameters are the same as those described above for the Ant task.
buildscript { dependencies { classpath 'net.jsign:jsign-gradle-plugin:4.1' } } apply plugin: 'net.jsign' task sign { doLast { jsign(file : 'application.exe', name : 'My Application', url : 'http://www.example.com', keystore : 'keystore.p12', alias : 'test', storepass : 'secret', tsaurl : 'http://timestamp.sectigo.com') } }
Command Line Tool
Jsign can also be used as a command line tool. A Debian package and a RPM package are provided to install it easily on most Linux distributions. On these systems the command line is invoked with:
jsign [OPTIONS] [FILE]...
On other systems the command line is invoked by running the jar with:
java -jar jsign-4.1.jar [OPTIONS] [FILE]...
The parameters expected are the same as those used by the Ant task:
usage: jsign [OPTIONS] [FILE]... Sign and timestamp Windows executable files, Microsoft Installers (MSI), Cabinet files or scripts (PowerShell, VBScript, JScript, WSF). -s,--keystore <FILE> The keystore file, or the SunPKCS11 configuration file --storepass <PASSWORD> The password to open the keystore --storetype <TYPE> The type of the keystore: - JKS: Java keystore (.jks files) - JCEKS: SunJCE keystore (.jceks files) - PKCS12: Standard PKCS#12 keystore (.p12 or .pfx files) - PKCS11: PKCS#11 hardware token - AZUREKEYVAULT: Azure Key Vault key management system - DIGICERTONE: DigiCert ONE Secure Software Manager - ESIGNER: SSL.com eSigner - GOOGLECLOUD: Google Cloud KMS -a,--alias <NAME> The alias of the certificate used for signing in the keystore. --keypass <PASSWORD> The password of the private key. When using a keystore, this parameter can be omitted if the keystore shares the same password. --keyfile <FILE> The file containing the private key (supports PEM & PVK files) -c,--certfile <FILE> The file containing the PKCS#7 certificate chain (.p7b or .spc files). -d,--alg <ALGORITHM> The digest algorithm (SHA-1, SHA-256, SHA-384 or SHA-512) -t,--tsaurl <URL> The URL of the timestamping authority. Several URLs separated by a comma can be specified to fallback on alternative servers -m,--tsmode <MODE> The timestamping mode (RFC3161 or Authenticode) -r,--tsretries <NUMBER> The number of retries for timestamping -w,--tsretrywait <SECONDS> The number of seconds to wait between timestamping retries -n,--name <NAME> The name of the application -u,--url <URL> The URL of the application --proxyUrl <URL> The URL of the HTTP proxy --proxyUser <NAME> The user for the HTTP proxy. If an user is needed. --proxyPass <PASSWORD> The password for the HTTP proxy user. If an user is needed. --replace Tells if previous signatures should be replaced. -e,--encoding <ENCODING> The encoding of the script to be signed (UTF-8 by default, or the encoding specified by the byte order mark if there is one) --detached Tells if a detached signature should be generated or reused. -h,--help Print the help
Example using a Java keystore:
jsign --keystore keystore.jks --alias test --storepass password \ --tsaurl http://timestamp.sectigo.com application.exe
Example using SPC/PVK files:
jsign --certfile certificate.spc --keyfile key.pvk --keypass password application.exe
Example using a YubiKey:
When using a YubiKey the X.509 Certificate for Digital Signature certificate (slot 9c) is used by default but can be overridden by specifying another alias. The ykcs11 library from the Yubico PIV Tool must be installed on the system at the default location.
jsign --storetype YUBIKEY --certfile full-chain.pem --storepass 123456 application.exe
Example using Azure Key Vault:
Certificates and keys stored in the Azure Key Vault key management system can be used with:
jsign --storetype AZUREKEYVAULT --keystore vaultname --alias test \ --storepass <api-access-token> application.exe
Example using DigiCert ONE:
Certificates and keys stored in the DigiCert ONE Secure Software Manager can be used directly without installing the DigiCert client tools. It requires an API key and a PKCS#12 keystore holding a client certificate for the authentication.
jsign --storetype DIGICERTONE --alias test \ --storepass "<api-key>|/path/to/Certificate_pkcs12.p12|<password>" application.exe
Example using SSL.com eSigner:
When signing with the SSL.com eSigner service, the SSL.com username and password are used as the keystore password, and the base64 encoded TOTP secret is used as the key password:
jsign --storetype ESIGNER --storepass "<username>|<password>" \ --alias 8b072e22-7685-4771-b5c6-48e46614915f \ --keypass <totp-secret> application.exe
SSL.com provides a sandbox environment, to use a test certificate simply add the parameter
--keystore https://cs-try.ssl.com
.
Example using Google Cloud KMS:
Google Cloud KMS stores only the private key, the certificate must be provided separately. The keystore parameter references the path of the keyring. The alias can specify either the full path of the key, or only the short name. If the version is omitted the most recent one will be picked automatically.
jsign --storetype GOOGLECLOUD --storepass <api-access-token> \ --keystore projects/first-rain-123/locations/global/keyRings/mykeyring \ --alias test --certfile full-chain.pem application.exe
API
Jsign also provides a simple API for signing files and can be embedded in another application.
Simply add this dependency to the project:
<dependency> <groupId>net.jsign</groupId> <artifactId>jsign-core</artifactId> <version>4.1</version> </dependency>
and then use the AuthenticodeSigner
class like this:
KeyStore keystore = KeyStoreUtils.load(new File("keystore.p12"), "PKCS12", "password", null); AuthenticodeSigner signer = new AuthenticodeSigner(keystore, "test", "secret"); signer.withProgramName("My Application") .withProgramURL("http://www.example.com") .withTimestamping(true) .withTimestampingAuthority("http://timestamp.sectigo.com"); try (Signable file = Signable.of(new File("application.exe"))) { signer.sign(file); }
See the Javadoc for more details about the API.
Downloads
- jsign_4.1_all.deb - Jsign command line tool for Debian/Ubuntu
- jsign-4.1-1.noarch.rpm - Jsign command line tool for RedHat/Fedora/CentOS
- jsign-4.1.jar - Jsign Ant Task
Credits
Jsign leverages the cryptography API developed by the Bouncy Castle project.
PVK parsing is based on the pvktool by Stephen N Henson.
MSI signing was possible thanks to the work done by the osslsigncode and Apache POI projects.
Jsign includes contributions from Emmanuel Bourg, Florent Daigniere, Michael Szediwy, Michael Peterson, Markus Kilås, Erwin Tratar, Björn Kautler and Joseph Lee.
Contact
Emmanuel Bourg (ebourg@apache.org, @smanux)