1

I implemented this example of jar file which checks it's own checksum:

   File currentJavaJarFile = new File(MainApp.class.getProtectionDomain().getCodeSource().getLocation().getPath());
        String jarFile = currentJavaJarFile.getAbsolutePath();// + "jarChecksumTest-1.0.jar";

        byte[] data = Files.readAllBytes(Paths.get(jarFile));

        MessageDigest complete = MessageDigest.getInstance(data);

        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(complete.toString().getBytes());

        byte byteData[] = md.digest();

        // convert the byte to hex format
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < byteData.length; i++)
        {
            sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }

        if ("L9ThxnotKPzthJ7hu3bnORuT6xI=".equals(sb.toString()))
        {
            System.out.println("Success!!!");
        }

But then I run the file I get this message:

Caused by: java.security.NoSuchAlgorithmException: D:\.....\target\jarChecksumTest-1.0.jar MessageDigest not available

How I can solve this issue?

Peter Penzov
  • 1,126
  • 134
  • 430
  • 808
  • 1
    This is pretty magic; surely when you run this code the first time to determine the checksum, and then hardcode it, the checksum will change? – Oliver Charlesworth Dec 28 '13 at 12:29
  • 1
    What do you think this line `MessageDigest complete = MessageDigest.getInstance(jarFile);` is doing? – Henry Dec 28 '13 at 12:30
  • `if ("L9ThxnotKPzthJ7hu3bnORuT6xI=".equals(sb.toString()))` - you will never be able to guess the digest. It will change dramatically after writing new string to this if statement – MGorgon Dec 28 '13 at 12:56
  • @MGorgon How I can fix this? – Peter Penzov Dec 28 '13 at 12:57
  • You can read digest string from external file, so you don't have to change code after calculating digest. – MGorgon Dec 28 '13 at 12:59

2 Answers2

3

Try this code, it is running fine. You may choose any algorithm whether it is SHA/MD5

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Checksum 
{
    public static void main(String ar[])
    {
        File currentJavaJarFile = new File(Checksum.class.getProtectionDomain().getCodeSource().getLocation().getPath());
        String filepath = currentJavaJarFile.getAbsolutePath();
        StringBuilder sb = new StringBuilder();
        try
        {
            MessageDigest md = MessageDigest.getInstance("SHA-256");// MD5
            FileInputStream fis = new FileInputStream(filepath);
            byte[] dataBytes = new byte[1024];
            int nread = 0; 

            while((nread = fis.read(dataBytes)) != -1)  
                 md.update(dataBytes, 0, nread);

            byte[] mdbytes = md.digest();

            for(int i=0; i<mdbytes.length; i++)
            sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100 , 16).substring(1));  
        }
        catch(NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }

        System.out.println("Checksum: "+sb);
    }
}
Tech Enthusiast
  • 279
  • 1
  • 5
  • 18
2

MessageDigest.getInstance() takes a string parameter that is the algorithm you wish to use on that message digest, SHA-256 for example. Creating a MessageDigest with a file path makes no sense - Java will try to treat it as a an algorithm, look for an algorithm with the same name as the path, then throw an exception when it can't find one.

Your update makes things worse - you're now passing a stream rather than a String! You're creating the MessageDigest md correctly, but the one called complete is nonsense.

I think what you're trying to do is get the bytes from the file into a byte array? In which case (since Java 7) you can do:

String jarFile = currentJavaJarFile.getAbsolutePath();
byte[] data = Files.readAllBytes(Paths.get(jarFile));

(If you're not running Java 7 see here for a few other ways that can work just as well.) The file's bytes will then be stored in data (so you can then call md.update(data) and then process the digest as before.

Community
  • 1
  • 1
Michael Berry
  • 70,193
  • 21
  • 157
  • 216