Sep
29
2009

Automatically signing .jar files in NetBeans

Just a quick article on something I struggled to find a good example for – configuring NetBeans to sign a .jar file after compilation is complete.

This is very handy, for example, when developing an applet that requires permission to access the file system. This requires the applet to be “signed” using the jarsigner utility, and this quickly becomes a tedious step when testing changes made in your applet in the browser itself.

I’m assuming that since you’re reading this article you have basic knowledge of Java and the keytool and jarsigner utilities. If not, there is a good introduction here.

Please note that this how-to is intended for a development environment situation only. Before deploying to a production environment you should read up on the best practices and security implications of the .jar signing process.

Step 1: Setting up your keystore

For this step we will be using the keytool utility distributed with your JDK. This will most likely be in the bin directory of your JDK installation.

Assuming keytool is in your system path, run the command:

keytool -genkey -alias <alias name> -keystore <keystore path> -validity 36500

Replacing <alias name> with a suitable alias, and <keystore path> with the filename you’d like for your keystore.

You will then be prompted for a number of inputs. For a test setup, use the following answers:

Enter keystore password: <keystore password> <enter>
Re-enter new password: <keystore password> <enter>
What is your first and last name?
  [Unknown]: <enter>
What is the name of your organizational unit?
  [Unknown]: <enter>
What is the name of your organization?
  [Unknown]: <enter>
What is the name of your City or Locality?
  [Unknown]: <enter>
What is the name of your State or Province?
  [Unknown]: <enter>
What is the two-letter country code for this unit?
  [Unknown]: <enter>
Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
  [no]:  y <enter>

Enter key password for <<alias name>>
  (RETURN if same as keystore password): <key password> <enter>

This will create a keystore file at <keystore path> which we will use in the next step to sign .jar files. Remember the passwords you used in this step as you’ll need them very soon.

The -validity 36500 section simply specifies that we want this key to last for a very long time (100 years to be exact). This is fine in a development environment as you probably don’t want to have to regenerate new keys all the time, but in a production environment this would obviously be much shorter. The -validity value is specified in days.

Step 2: Configuring your NetBeans project

In this step we will be editing two configuration files from your NetBeans project; project.properties and build.xml.

The project.properties file should be located in the nbproject directory of your NetBeans project, and the build.xml should be in the main project folder itself.

You can edit these files by hand, or you can do so in NetBeans itself by switching to the Files window.

Add the following lines somewhere in your project.properties file, substituting the relevant paths etc. (hint: your jarsigner utility should be in the bin directory of your JDK installation):

jarsign.jarsigner=<path to the jarsigner utility>
jarsign.keystore=<keystore path>
jarsign.storepass=<keystore password>
jarsign.keypass=<key password>
jarsign.signedjar=<path to create signed jar file at>
jarsign.alias=<alias name>

Add the following inside the <project> block in your build.xml file:

<target name="-post-jar">
   <exec executable="${jarsign.jarsigner}">
      <arg line="-keystore" />
      <arg file="${jarsign.keystore}" />
      <arg line="-storepass ${jarsign.storepass}" />
      <arg line="-keypass ${jarsign.keypass}" />
      <arg line="-signedjar" />
      <arg file="${jarsign.signedjar}" />
      <arg file="${dist.jar}"/>
      <arg line="${jarsign.alias}" />
   </exec>
   <echo>Signed Jar '${jarsign.signedjar}' created</echo>
 </target>

And that’s it. The next time you build your project, a signed copy of the .jar file should be created automatically at the path you specified. You should also see a confirmation message in the build output.

Enjoy!

19 Comments »

  • Patrick says:

    I tried the above tutorial, and still receive a SocketPermission error, 127.0.0.1:3306 connect,resolve issue, or looks like [0:0:0:0:0:0:1:3306] connect, resolve. I placed the signed jar in the webserver’s correct folder. Now i stuck with my java program not working, Please get back to me if you can help, thanks

    • Erin says:

      Hi Patrick. Are you clearing your classloader cache after building the .jar file?

      If you are using the applet from within a browser like Firefox or IE, you must clear the classloader cache in order to load the new version of the applet. Simply refreshing the page is not enough. This should also force Java to re-evaluate the applet’s permissions.

      To clear your classloader cache, open your Java Console and press ‘x’.

      • Patrick says:

        Unfortunately, i gave the classloarder cache clear and i didn’t not change the result. Caused by: java.net.SocketException: java.security.AccessControlException: access denied (java.net.SocketPermission [0:0:0:0:0:0:0:1]:3306 connect, resolve)

        • Erin says:

          Can you try something for me?

          Make a copy of the .jar file that is being loaded in your browser (make sure it is NOT the unsigned one initially created by NetBeans).

          Once you have made a copy of the file, change the extension from .jar to .zip and open with any zip program such as WinZip (.jar files are just .zip files anyway).

          Now look in the folder called META-INF. You should see three files; MANIFEST.MF, and two other files ending in .DSA and .SF. If you don’t see the .DSA and .SF files, then your applet has not been signed correctly.

          If everything is in place and your applet is definitely signed, then you may have encountered a bug in your version of Java. There are lots of bug reports out there for this sort of thing. Update to the latest JRE and if the problem persists, start a thread on the official forum asking for help:

          http://forums.sun.com/forum.jspa?forumID=30

          Good luck and let me know how you go.

  • Patrick says:

    It works with java’s tutorial and your keystore directions. Thanks

  • Wilson says:

    I am using Windows XP, and Netbean IDE 6.91

    I have problem using your first step to generate the key

    where is the keyfile located in C:\Program Files\Java\jdk1.6.0_23 ?

    keystore (what is keystore path in Window C:\ ?

    how is the file and directory for ?
    jarsign.jarsigner=
    jarsign.keystore=
    jarsign.storepass=
    jarsign.keypass=
    jarsign.signedjar=

    Thank in advance email me wilson_three@yahoo.com.au

  • Wilson says:

    will this password protected my .jar file from unzip?

    • Erin says:

      No, that is not possible. If you password protected (encrypted) your .jar file, the Java runtime environment would not be able to understand the contents in order to run it.

  • Faisal Basra says:

    Hi, I did the settings as you said but get the following error.

    jarsigner: Certificate chain not found for:

    any help?

    • Erin says:

      Is that the full error message? If there’s nothing after the ‘for:’ part it probably means that you’re not passing the alias name at all.

      Make sure that you have set jarsign.alias correctly in your project.properties file, and that there is an argument for jarsign.alias in your build.xml file.

      If it’s still not working, go back to basics. Try manually signing your .jar file from the command line using your keystore. If that’s not working, you’ll know it’s a problem with your keystore, and Google should be able to help you from with that.

  • rajeena` says:

    The following error occurred while executing this line:
    C:\Documents and Settings\work\My Documents\NetBeansProjects\helloApplet\build.xml:75: Unexpected text “target name=”-post-jar”>”
    BUILD FAILED (total time: 0 seconds)
    Can u explain this?

  • Fiar says:

    if i using
    jarsign.signedjar=dist/TestApplet.jar

    The following error occurred :
    Exception in thread “main” java.util.zip.ZipError: jzentry == 0,
    jzfile = 45300144,
    total = 5,
    name = D:\TestApplet\dist\TestApplet.jar,
    i = 1,
    message = null
    at java.util.zip.ZipFile$2.nextElement(ZipFile.java:321)
    at java.util.zip.ZipFile$2.nextElement(ZipFile.java:299)
    at sun.security.tools.JarSigner.getManifestFile(JarSigner.java:1554)
    at sun.security.tools.JarSigner.signJar(JarSigner.java:892)
    at sun.security.tools.JarSigner.run(JarSigner.java:203)
    at sun.security.tools.JarSigner.main(JarSigner.java:74)
    Result: 1
    Signed Jar ‘dist/TestApplet.jar’ created

    if i not using
    jarsign.signedjar=dist/TestApplet.jar
    it works, it creates signed TestApplet.jar
    But it should created at dist/TestApplet.jar in order to run properly

    • Rodrighez says:

      You should do the following:
      1. Create a folder in your project directory(for example: toerase)
      2. write this line over: dist.dir=dist
      with this: dist.dir=toerase
      in project.properties

      It should works!

      You’ll have your new folder and the unsigned jar inside, but i think it’s not a problem.

  • Alexandros Monastiriotis says:

    Thank you for this excellent tutorial.

  • koool says:

    I tried using this I get the error
    Please type jarsigner -help for usage
    Please specify jarfile name
    Result: 1
    Signed Jar ‘dist\my_project_signed.jar’ created

    project.properties changes

    jarsign.jarsigner=”C:\\Program Files (x86)\\Java\\jdk1.7.0\\bin\\jarsigner.exe”
    jarsign.keystore=”C:\\Users\\abc\\.keystore”
    jarsign.storepass=pass1234
    jarsign.keypass=pass1234
    jarsign.signedjar=dist\\my_project_signed.jar
    jarsign.alias=myalias

    build.xml copy pasted in project element

    Signed Jar ‘${jarsign.signedjar}’ created

  • koool says:

    [code]

    Signed Jar '${jarsign.signedjar}' created
    [/code]

  • koool says:

    I cannot copy the xml thing but I did not make any changes to it…. just copy pasted you code. Could anyone please help me with this

RSS feed for comments on this post. TrackBack URL


Leave a Reply