class checksums

  • Thread starter Michael Fairbank
  • Start date
M

Michael Fairbank

Is there a simple way I can calculate a checksum on a java class?
I want some simple verification that my applet has not been modified before
it submits to the server. I know it's not going to be 100% secure but it's
better than nothing.

I was thinking of using ClassLoader.getSystemResouceAsStream, and then
writing my own checksum algorithm on that stream. Is there a simpler way to
do this?

Also, another problem I am going to have with that is that
getSystemResouceAsStream takes a string argument for the class name. This
is annoying because the obfuscator I run will change all the class names! It
would be better if I pass the object itself, e.g. call to a function as
calcChecksum(this).

I'm grateful for any suggestions.
Thanks in advance,
Mike
 
S

Sudsy

Michael said:
Is there a simple way I can calculate a checksum on a java class?
I want some simple verification that my applet has not been modified before
it submits to the server. I know it's not going to be 100% secure but it's
better than nothing.

I was thinking of using ClassLoader.getSystemResouceAsStream, and then
writing my own checksum algorithm on that stream. Is there a simpler way to
do this?

Why bother writing your own? Both MD5 (Message Digest 5) and SHA1
(Secure Hash Algorithm 1) would do what you require and they've
been around a bit ("been around a bit, eh?...know what I mean?...
nudge, nudge, say no more!").
 
M

Michael Borgwardt

Michael said:
Is there a simple way I can calculate a checksum on a java class?
I want some simple verification that my applet has not been modified before
it submits to the server. I know it's not going to be 100% secure but it's
better than nothing.

Ain't worth the bother. If someone wants to manipulate your applet, making it
send the "correct" checksum is a *very* minor additional difficulty.
 
N

nos

i did that but using sha instead of checksum
then i convert to base64 so it can be read
i got much of the code from a book, but it works
and should serve your purpose
------------
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;

class MyDigest extends Frame {

public MyDigest(String Filename) {

// from java book page 169
// reads a file and calculates a message digest for it
File f = new File(Filename);
if (!f.exists()) {
System.out.println("That file seems not to exist");
System.exit(1);
}
// all current java files are less than 1000 lines except one
java.util.List text = new ArrayList(1000); // default capacity is 10

// Get an object that can compute an SHA message digest
MessageDigest digester = null;
try {
digester = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
// A stream to read bytes from the file f
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
// A stream that reads bytes from fis and computes an SHA message digest
DigestInputStream dis = new DigestInputStream(fis, digester);
// A stream that reads bytes from dis and converts them to characters
InputStreamReader isr = new InputStreamReader(dis);
// A stream that can read a line at a time
BufferedReader br = new BufferedReader(isr);
// Now read lines from the stream
try {
for (String line;(line = br.readLine()) != null; text.add(line)) {
}
} catch (IOException e3) {
e3.printStackTrace();
}
// Close the streams
try {
br.close();
} catch (IOException e4) {
e4.printStackTrace();
}
// Get the message digest
byte[] digest = digester.digest();

// warning: sun says to not use sun library methods
// there is no import because it is not available -- just use library
String s = new sun.misc.BASE64Encoder().encode(digest);
System.out.println(s); // show user the encoded digest

System.exit(0);
//==================================

addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Argument is name of file");
System.exit(1);
}
MyDigest mainFrame = new MyDigest(args[0]);
mainFrame.setSize(200, 200);
mainFrame.setTitle("MyDigest");
mainFrame.setVisible(false); // no need to show frame
}
}
------------
 
S

Sudsy

Michael Borgwardt wrote:
Ain't worth the bother. If someone wants to manipulate your applet,
making it
send the "correct" checksum is a *very* minor additional difficulty.

But the very nature of message digests and secure hash functions is
such that it would take considerable effort to generate something
which would both run and checksum to the same value as the original.
Even minor changes will significantly permutate the results, which
is why these algorithms serve as the basis for digital signatures
(in conjunction with public/private key cryptography).
 
M

Michiel Konstapel

Michael Borgwardt wrote:


But the very nature of message digests and secure hash functions is
such that it would take considerable effort to generate something
which would both run and checksum to the same value as the original.
Even minor changes will significantly permutate the results, which
is why these algorithms serve as the basis for digital signatures
(in conjunction with public/private key cryptography).

Ah, but you don't actually have to *have* the same checksum, just say you
do.
Somewhere in the to be manipulated applet there's some calcChecksum()
method.
If the original applet had a checksum of, say, 0xCAFEBABE, just change
calcChecksum() to

public int calcChecksum() {
// heavily optimised checksummer - runs in O(1) time!
return 0xCAFEBABE;
}

Michiel
 
M

Michael Fairbank

I reckon it's worth me trying.

But my major problem is not the checksum evaluation function, but how to get
at the class bytecode itself.
So is the best solution really to use ClassLoader.getResourceAsStream(String
classname). I would rather find a function that takes an Object as an
argument instead of a String, if there is such a function. Can anyone
suggest one or is that function my best bet?

Thanks again,
Mike.
 
M

Michael Borgwardt

Michael said:
I reckon it's worth me trying.

Well, it's your time to waste.
But my major problem is not the checksum evaluation function, but how to get
at the class bytecode itself.
So is the best solution really to use ClassLoader.getResourceAsStream(String
classname). I would rather find a function that takes an Object as an
argument instead of a String, if there is such a function. Can anyone
suggest one or is that function my best bet?

That's a two-liner.
If you have an Object, you can invoke its getClass() method which gives
you access via getName() to its class name and a getResourceAsStream() method
that will automatically look in the right location. All you need to do is
remove the package component from the name.
 
A

Adam Jenkins

Sudsy said:
Michael Borgwardt wrote:



But the very nature of message digests and secure hash functions is
such that it would take considerable effort to generate something
which would both run and checksum to the same value as the original.
Even minor changes will significantly permutate the results, which
is why these algorithms serve as the basis for digital signatures
(in conjunction with public/private key cryptography).

I think you missed Michael's point. It would be impossible for all
practical purposes to modify the applet class such that it still has the
same checksum. However, there's no need to. Just save the checksum of
the unmodified applet class, and then when you modify the applet class,
one of your modifications will be to change the function that computes
the checksum so that it always returns the checksum of the unmodified
applet class. That's why this whole idea is pretty silly; it only makes
it *slightly* more work to hack the applet.

If the original poster's intent is to allow the client to ensure that
they're running an unmodified applet, then he should use jarsigner to
sign his applet. The server security should not depend on the applet
being unmodified, it should just not accept invalid requests.

Adam
 
M

Michael Fairbank

That's a two-liner.
If you have an Object, you can invoke its getClass() method which gives
you access via getName() to its class name and a getResourceAsStream() method
that will automatically look in the right location. All you need to do is
remove the package component from the name.

I'm having problems with this. I cannot get the "resource as stream"
functions to work when the filename ends in ".class". For example, the
following code prints "null"

String className=obj.getClass().getName();
className=className+".class";
InputStream in=ClassLoader.getSystemResourceAsStream(className);
System.out.println(className+" in="+(in==null?"null":in.toString()));

The above code works fine if I change it to search for a filename ending in
any other suffix, e.g. "classname.java".
I've also tried using obj.getClass().getResourceAsStream(className) on line
3 with exactly the same problem.
It's not that the class file is in-use because I've tried reading class
files from other java applications - same problem.
Is this a bug in my java implementation? - I'm only using jdk1.1.

Thanks.
Mike
 
D

David Zimmerman

Michael said:
I'm having problems with this. I cannot get the "resource as stream"
functions to work when the filename ends in ".class". For example, the
following code prints "null"

String className=obj.getClass().getName();
className=className+".class";
InputStream in=ClassLoader.getSystemResourceAsStream(className);
System.out.println(className+" in="+(in==null?"null":in.toString()));

You need to change the '.'s in the classname to '/'s, the file seperator
in resources
 
M

Michael Borgwardt

Michael said:
that will automatically look in the right location. All you need to do is
remove the package component from the name.


I'm having problems with this. I cannot get the "resource as stream"
functions to work when the filename ends in ".class". []
Is this a bug in my java implementation? - I'm only using jdk1.1.

Sorry, can't help you there, especially not with Java 1.1.
Might be a bug, might be intentional.

Looking at the 1.4 JRE source, the class sun.misc.URLClassPath would
be in charge of handling it. You can get the source of the sun.*
packages under Sun's community source program, but you obviously want
it to work on the Microsoft VM, and I have no idea how it's done there
and doubt one can get the source code.
 
M

Michael Fairbank

Do you mean look for "classname/class"? This doesn't seem to fix it.
Also I wouldn't expect so because it works fine with "classname.java" or
"xxx.gif"
 
M

Michael Borgwardt

Michael said:
Do you mean look for "classname/class"? This doesn't seem to fix it.
Also I wouldn't expect so because it works fine with "classname.java" or
"xxx.gif"

No, he meant the dots within the classname, that separate package, subpackage
and class, like in java.lang.String.

I'm kinda embarassed that I forgot about that.
 
M

Michael Fairbank

It's still not that because there are no prefixes to the string I am using.
It is simply "classname.class" and is in the current (i.e. the applet's)
directory.
But it does work fine for "classname.java" or "xxx.gif", which also have no
prefix and also exist in the applet's' directory.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top