català | česky | dansk | deutsch | english | español | français | lingála | magyar | nederlands | norsk | polski | português | svenska

JavaTimeStamping

This page details the process of free trusted codesigning, timestamping, and how to get the Thawte timestamping CA cert into the java runtime CA keystore without user intervention so that a jar file will run trusted over an extended period (9 years in my test). In my case the jar contained an applet and this was necessary.

This page has things in common with the wiki pages TimeStamping and JavaCodeSigningTest. The original copy is at http://nerveplexus.com/Java_Timestamping.htm.

If you open a Thawte freemail account you can generate a free trusted codesigning certificate allowing you to sign jar files. The procedure has been documented elsewhere:-

/!\ As of november 2009, Thawte freemail program and java codesigning has been discontinued.

1. In the section commencing "Personal Freemail account at Thawte" at http://www.crionics.com/products/opensource/faq/signFree.htm

2. About halfway down the page at http://www.dallaway.com/acad/webstart/

The advantage of using Thawte is that their root CA cert is included in the java runtime CA keystore (cacerts file) so the jar security warning popup will be the trusted type automatically for all users.

The popup will show "Thawte Freemail Member" but it is recommended and easy to get your ID verified with Thawte web of trust in which case your name will appear instead.

After a year the certificate will expire and the jar security popup will revert to untrusted. However if you timestamp when signing the jar, and add the below java code to your applet, then the popup should show as trusted for an extended period, 9 years for one that I tried. So the user will not be unduly hassled.

To timestamp the jar include this in the command line when signing:-

-tsa https://timestamp.geotrust.com/tsa

This ties up with Thawte since both Geotrust and Thawte are owned by Verisign.

For example my complete command line for signing the jar is:-

"C:\Program Files\Java\jdk1.6.0_07\bin\jarsigner" -storetype pkcs12 -keystore C:\Control\keystore.p12 -storepass passpass -keypass passpass -tsa https://timestamp.geotrust.com/tsa C:\Master\www\plexos.com\jmUtilm.jar plexel

For the timestamping to work however the Thawte timestamp CA cert needs to be in the java runtime keystore i.e. java.home\lib\security\cacerts. For XP on my system java.home was C:\Program Files\Java\jre1.6.0_07\.

You might think Sun would have put it in there but they didn't so far. It is in Firefox (3.0.3) certificate authorities listed as Thawte Timestamping CA but that doesn't help.

Since you now have a signed jar and if the jar contains an applet then the following code can be added to the applet to import the Thawte timestamp CA cert into the cacerts keystore. It uses the keytool program included with java runtime to import the cert into the keystore located via the java.home property. The user does not need a Java development kit but it is assumed they have installed Java runtime.

If you use an applet init() function then just add in the line timestampCert() otherwise just copy an paste the lot into your applet. An extra class file is generated that needs including in the jar file to be signed. E.g. if your applet is a single file game.class, then game$1.class will also be generated.

public void init() {
timestampCert();
return;}

public void timestampCert() {
// Import TimestampCA.cer to java runtime cacerts keystore. This stops the applet
// expiring when the signing cert expires usually with a year. For a timestamped
// test applet signed in 2008 for me it now expires in 2017. TimestampCA.cer expires
// 31 Dec 2020 so 2017 is a slight mystery. TimestampCA.cer obtained from:- 
//https://knowledge.verisign.com/resources/sites/VERISIGN/content/live/SOLUTION/9000/SO9699/en_US/TimestampCA.cer
// also obtainable from http://www.webneurons.com/TimestampCA.cer
// Sign applet including jarsigner switch " -tsa https://timestamp.geotrust.com/tsa "
try {
   Process p = (Process) AccessController.doPrivileged(new PrivilegedExceptionAction() {
   public Object run() throws Exception {
      String javaHome = System.getProperty("java.home") + "\\";
      String javaHomeLs = javaHome + "lib\\security\\";
      File timestampFile = new File(javaHomeLs + "TimestampCA.cer");
      // Put timestampFile in java.home/lib/security folder if not there. 
      if(!timestampFile.exists()) { 
         String cert = "-----BEGIN CERTIFICATE-----\n" +
            "MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx\n" +
            "FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN\n" +
            "BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd\n" +
            "BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN\n" +
            "MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g\n" +
            "Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG\n" +
            "A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l\n" +
            "c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT\n" +
            "6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa\n" +
            "Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL\n" +
            "8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB\n" +
            "Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC\n" +
            "9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ\n" +
            "pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ\n" +
            "CayJSdM=\n-----END CERTIFICATE-----";
         BufferedWriter out = new BufferedWriter(new FileWriter(timestampFile));
         out.write(cert);
         out.close();
      }
      // Command to be executed. If the timestamp cert is already in
      // java runtime cacerts keystore it just gives a warning.
      String command = javaHome + "bin\\keytool -import -trustcacerts -keystore " +
         javaHomeLs + "cacerts -alias Thawte_timestamp_CA -file " + timestampFile + 
         " -noprompt -storepass changeit";
      Process p = Runtime.getRuntime().exec(command);
      // Messages section. Read any messages from input and error streams.
      // This section could be omitted.
      BufferedReader in  = new BufferedReader(new InputStreamReader(p.getInputStream()));
      BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
      String inLine, errLine;
      Boolean inRead = true, errRead = true;
      while (inRead || errRead) {
         if(inRead) {
            inLine = in.readLine();
            if(inLine == null) {
               inRead = false;  // don't read any more from in
            }
            else {
               System.out.println("Input Stream: " + inLine);
            }
         }
         if(errRead) {
            errLine = err.readLine();
            if(errLine == null) {
               errRead = false;  // don't read any more from err
            }
            else {
               System.out.println("Error Stream: " + errLine);
            }
         }
      }
      // End of messages section
      return p;
   }}); // End of doPrivileged
   p.waitFor();
   p.destroy();
}
catch (Exception e) {
   System.out.println("Exception in timestampCert(): " +e);
}
return;}

It should be possible to use Certum.pl mentioned on the wiki page TimeStamping for the timestamping in the same way as above.

JavaTimeStamping (last edited 2015-03-30 21:27:23 by EtienneRuedin)