Share this page 

Create a checksumTag(s): Security


MD5 digests have been widely used in the software world to provide some assurance that a downloaded file has not been altered. A user can compare a published MD5 sum with the checksum of a downloaded file.
import java.io.*;
import java.security.MessageDigest;

public class MD5Checksum {

   public static byte[] createChecksum(String filename) throws
       Exception
   {
     InputStream fis =  new FileInputStream(filename);

     byte[] buffer = new byte[1024];
     MessageDigest complete = MessageDigest.getInstance("MD5");
     int numRead;
     do {
      numRead = fis.read(buffer);
      if (numRead > 0) {
        complete.update(buffer, 0, numRead);
        }
      } while (numRead != -1);
     fis.close();
     return complete.digest();
   }

   // see this How-to for a faster way to convert
   // a byte array to a HEX string
   public static String getMD5Checksum(String filename) throws Exception {
     byte[] b = createChecksum(filename);
     String result = "";
     for (int i=0; i < b.length; i++) {
       result +=
          Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
      }
     return result;
   }

   public static void main(String args[]) {
     try {
       System.out.println(getMD5Checksum("apache-tomcat-5.5.17.exe"));
       // output :
       //  0bb2827c5eacf570b6064e24e0e6653b
       // ref :
       //  http://www.apache.org/dist/
       //          tomcat/tomcat-5/v5.5.17/bin
       //              /apache-tomcat-5.5.17.exe.MD5
       //  0bb2827c5eacf570b6064e24e0e6653b *apache-tomcat-5.5.17.exe
     }
     catch (Exception e) {
         e.printStackTrace();
     }
   }
}
The next example is used to create a .chk file which contains a MD5 checksum of a given file. The same program is used to check if a file has been altered by looking at previously generated .chk file and compared with current checksum of the given file.
import java.security.*;
import java.io.*;

public class Checksum {

  //
  // returns 0 error
  //         1 ok (create)
  //         1 same (check)
  //         2 different (check)
  //
  public static void main(String args[]) {
     if (args.length == 2) {
        if (args[0].equals("create")) {
           System.exit(new Checksum().create(args[1]));
        }
        else if (args[0].equals("check")) {
           System.exit(new Checksum().check(args[1]));
        }
     }
     else {
        System.out.println("Usage : java Checksum create [filename]\n"+
                           "        java Checksum check  [filename]");
     }
  }


  public int create(String filename){
     try {
        byte[] chk = createChecksum(filename);
        File f = new File(filename + ".chk");
        OutputStream os = new FileOutputStream(f);
        os.write(chk);
        os.close();
        return 1;
     }
     catch(Exception e) {
        e.printStackTrace();
        return 0;
     }
  }

  public int check(String filename){
     int rc = 0;
     try {
        byte[] chk1 = createChecksum(filename);
        byte[] chk2 = new byte[chk1.length];
        File f = new File(filename + ".chk");
        InputStream is = new FileInputStream(f);

        is.read(chk2);

        if (new String(chk2).equals(new String(chk1))) {
           System.out.println("Same!");
           rc = 1;
        }
        else {
          System.out.println("Different!");
          rc = 2;
          }
        is.close();
        return rc;
     }
     catch(Exception e) {
        e.printStackTrace();
        return rc;
     }
  }

  public byte[] createChecksum(String filename) throws Exception{
     InputStream fis =  new FileInputStream(filename);

     byte[] buffer = new byte[1024];
     MessageDigest complete = MessageDigest.getInstance("MD5");
     int numRead;
     do {
       numRead = fis.read(buffer);
       if (numRead > 0) {
         complete.update(buffer, 0, numRead);
       }
     } while (numRead != -1);
     fis.close();
     return complete.digest();
  }
}

The java.util.zip package can be used to create a checksum. However the CRC32 is not a very strong way to make sure that a file is not altered.
import java.io.*;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

public class ComputeCRC32 {
  public static long getChecksumValue(Checksum checksum, String fname) {
    try {
       BufferedInputStream is = new BufferedInputStream(
         new FileInputStream(fname));
       byte[] bytes = new byte[1024];
       int len = 0;

       while ((len = is.read(bytes)) >= 0) {
         checksum.update(bytes, 0, len);
       }
       is.close();
    }
    catch (IOException e) {
       e.printStackTrace();
    }
    return checksum.getValue();
    }

  public static void main(String[] args) {
    if (args.length != 1) {
      System.err.println("Usage: java ComputeCRC32 <file>");
      System.exit(1);
    }
    long cs = getChecksumValue(new CRC32(), args[0]);
    System.out.println("crc32 " + args[0] + " : " + cs);
  }
}

However, MD5 is not secure anymore because researchers have proven that it is possible to manipulate the original data to get the same MD5 as the original. The alternative is to use SHA-1 which is on 160-bits (MD5 is 128-bits). It's still not perfect but it is better than MD5.
import java.io.*;
import java.security.MessageDigest;

public class ChecksumSHA1 {

   public static byte[] createChecksum(String filename) throws
       Exception
   {
     InputStream fis =  new FileInputStream(filename);

     byte[] buffer = new byte[1024];
     MessageDigest complete = MessageDigest.getInstance("SHA1");
     int numRead;
     do {
      numRead = fis.read(buffer);
      if (numRead > 0) {
        complete.update(buffer, 0, numRead);
      }
     } while (numRead != -1);
     fis.close();
     return complete.digest();
   }

   // see this How-to for a faster way to convert
   // a byte array to a HEX string
   public static String getSHA1Checksum(String filename) throws Exception {
     byte[] b = createChecksum(filename);
     String result = "";
     for (int i=0; i < b.length; i++) {
       result +=
          Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
      }
     return result;
   }

   public static void main(String args[]) {
     try {
       System.out.println(getSHA1Checksum("c:/temp/isapi_redirect-1.2.30.dll"));
       // output :
       //  cca9176f72ff56beb1f76c21b1d7daa6be192890
       // ref :
       //   http://tomcat.apache.org/
       //          dev/dist/tomcat-connectors/
       //            jk/binaries/win32/jk-1.2.30/
       //              isapi_redirect-1.2.30.dll.sha1
       //
       //  cca9176f72ff56beb1f76c21b1d7daa6be192890 *isapi_redirect-1.2.30.dll

     }
     catch (Exception e) {
         e.printStackTrace();
     }
   }
}

MD5 or SHA1 checksum can be used to validate a password without passing the actual password.

  1. The server sends a random string to the client.
  2. The client appends his password to the random string, and returns an MD5/SHA1 sum of the result to the server.
  3. On the server, do the same and compare the MD5/SHA1 sums.
  4. If both MD5/SHA1 are identicals then the password is good.