Wednesday, March 28, 2007

HOWTO: use Netbeans and ANT to auto-run jarsigner

Overview
There are times when you need to sign jar files. In my world it is is all the time since I tend to favor Java WebStart applications. There are techniques using ANT to auto sign JAR files, however, they require you to include your store password which is ok if your code remains internal but may not be so good if you post it to Google Code.

To get around this, there is a pretty easy to implement solution. I, being the Netbeans fan, will describe it from the Netbeans perspective, however, ANT is ANT so it should work using anything.

Description
There is a file within the ANT build process called build.xml. This file is usually located in the root of your project directory. This file lets you create additional targets without directly changing the core build script. Typical usage for me is to add -pre-jar and -post-jar targets. In this case we are going to add a new -post-jar target that will be responsible for signing all the JAR files in the dist directory.

Within the build.xml's <project> open and close tag, I add the following XML blob.
<target name="-post-jar">
<exec dir="${dist.dir}" executable="bulkjarsigner.csh" os="Linux" />
</target>
In this blob you can see a few bits. The main thing is a C-Shell file I wrote, called bulkjarsigner.csh, that has 700 permissions and sits outside my project tree in my personal bin directory (which is in my path).

The script is basic. It gets a listing of all jar files in the dist directory (and sub-directories) and runs jarsigner on it. The following is the script I use (with the obvious passwords changed):

#!/bin/csh
#
#
init:
onintr outahere
set KEYSTORE="~/keystore/my.jks"
set STOREPASS="mystorepassword"
set KEYPASS="mykeypass"
set ALIAS="keyalias"
set FILELIST=`find ./ -print |grep ".jar"`

main:
echo "--- Working out of `pwd` ----"

foreach ARG ($FILELIST)
echo "---- Processing $ARG ----"
jarsigner -storepass $STOREPASS -keypass $KEYPASS -keystore $KEYSTORE $ARG $ALIAS
echo " "
end

set KEYSTORE=""
set STOREPASS=""
set KEYPASS=""
set ALIAS=""

goto pissoff

outahere:
echo " "
echo "User Exit..."

pissoff:
You will note that it does not take any command line args at all. It just takes the current directory specified by ${dist.dir} and gets a listing of all the jar files. foreach jar in the list, it runs jarsigner.

The example above is written in C-SHELL but it could really be any scripting language (even BAT for Windows users).

What You Will See
When you do a build or a clean build, you will see your code compile, be bundled in JAR files and then signed.

That is it. The signed jar files can be verified (jarsigner -verify -verbose...) to confirm that all is well.

Last Thoughts
It is pretty simple to add and remove. It is also handy since you can change the password, alias, keystore,... in one place without having to re-touch every build.xml.
- - -

4 comments:

Jose said...

You can also sign your JAR without using external files with

<target name="-post-jar">
<exec dir="${work.dir}" executable="jarsigner.exe">
<arg value="-verbose" />
<arg value="-storepass" />
<arg value="mypass" />
<arg value="-keypass" />
<arg value="mypass" />
<arg value="${dist.jar}" />
<arg value="keyname" />
</exec>
</target>

Erin said...

Here's another way to do the same thing with less hassle whilst keeping all the configuration in your NetBeans project:

http://ezzatron.com/2009/09/29/automatically-signing-jar-files-in-netbeans/

Anonymous said...
This comment has been removed by a blog administrator.
uuklanger said...

Jose and Erin:

I agree with both your approaches however, this requires you to include your keyring password within your project. This may be acceptable for most project but in some cases the password may want to be kept secret.

The main purpose of this blog is to show how to sign your jar files using ANT/Netbeans but with an external script that knows about the password. This way you can share your code but not your password.

I think you both for your feedback.