views:

104

answers:

4

Good morning,

my Java program builds some files (.html and .txt-files) in one directory. To finish a project I'd like to "pack" these files for example to send it to another person. But the other person should not be able to simple "unpack" the file and manipulate the html/txt-Files. Only open the packed file with my Java program.

My idea was, to zip the directory with a master password (set in the java program) protection. After that I can send the zip-file via eMail and the other person will only be able to open it with my program. Unfortunately there is no easy and free way to zip/unzip a folder with password in Java.

So maybe you have another idea?

Thank you so much!


Ok I think I have to explain the problem a little bit more: I can create a small training with my program. The training contains "normal" pages with information (html-files) and pages with multiple-choice questions (the question and the answers are saved in txt-Files). In the end, the training-user can print a certification ("User XXX did the training"). To play the training the html/txt-files are read into my program. Ok so my problem is that the user can see (and manipulate) the files. However he can see the right answer of the multiple choice test in the txt-file.

A: 

Unfortunately, there really isn't much to be done. This is one of the advantages of writing web applications; the user sees only the inputs and outputs, but doesn't actually have access to the application, itself. Whenever you distribute an application such as a JAR, it is always possible to reverse-engineer and modify it; no obfuscation or encryption can thoroughly or completely prevent it.

Michael Aaron Safyan
Hi Michael, thanks a lot for your answer. But that's not the problem. I don't want to protect the jar-File of my application - but the files I build with my java-programm.
muffin
@muffin, but it is the same problem. Your application data is a part of your application (it may not be the executable, itself, but it, in combination with your executable, comprises the functionality of your application). The best you can do is to do some sort of checksum of the data, send the checksum to your server, and have it send back some token for decrypting the data or something along those lines. You could also have the data be frequently updated. But this kind of thing can still be defeated.
Michael Aaron Safyan
Ok I think I have to explain the problem a little bit more: I can create a small training with my program. The training contains "normal" pages with information (html-files) and pages with multiple-choice questions (the question and the answers are saved in txt-Files). In the end, the training-user can print a certification ("User XXX did the training"). To play the training the html/txt-files are read into my program. Ok so my problem is that the user can see (and manipulate) the files. However he can see the right answer of the multiple choice test in the txt-file.
muffin
+1  A: 

One thing that you can do is generate a CRC number for each an every file you want and pack it in a property file along with the jar file.Each time the user selects the file, check for the CRC value to make sure no-one has edited your files.It's not completely fool proof method.

Similar Questions:

Other Useful Links:

Just like the image is loaded dynamically from jar in the above given link you can load html and txt files from jar.

Emil
+1  A: 

What you are asking for is fundamentally impossible to do in a secure way, (unless all the interesting stuff happens on the server) - just ask anybody who's tried to make a DRM system recently. (I'm looking at you, ubisoft).

If you are just looking for a simple check that will stop a (very) casual attacker, how about storing your support files in a zip as you mentioned, and compare the SHA1 sum to a value coded into your program at runtime. Somebody can modify your code (or for java use a decompiler) and remove the check, but it's as good as anything really.

Jords
+1 Obviously, any decent hash will do. doesn't need to be SHA1.
Joeri Hendrickx
+1  A: 

There is no 100% way to stop people reading files, but you can make it a lot more difficult. What you are need to do is encrypt the file to prevent casual reading, or to sign the file so that you can detect authenticity and tampering.

Here is an overview of how you might encrypt a file with public / private key encryption. The tools you will need are:

  1. GPG. You will be creating keys with this
  2. BouncyCastle PGP. This is an encryption API for Java that implements the OpenPGP specification.

You will be encrypting files with the command line with GPG and reading them from Java with BouncyCastle (BC).

The steps involved in doing this in a secure way are.

  1. Create a unique public / private key pair for signing / encryption with GPG. e.g. gpg --gen-key and follow the onscreen instructions. You can usually pick the default settings, and call your key something like "[email protected]"

  2. Encrypt the file your Java will process. e.g. gpg -e myfiles.zip to encrypt. You could do this from a script fairly easily if its data that changes a lot. Encryption works by encrypting the file with the public key. Someone who wishes to decrypt the file needs the corresponding private key.

  3. Export the private key from the keypair. e.g. file gpg --export-secret-key -a > decryption.key.

  4. Create a new keyring just containing the key you exported. e.g.

    mkdir tmpkeys gpg -homedir=tmpkeys --import decryption.key cp tmpkeys/secring.gpg keyring

  5. In your Java program, embed the keyring as a resource or by base64 encoding it and injecting it into the code as a string. Keep your public key and ensure you do not inadvertently ship it with your app.

  6. Use BouncyCastle PGP to open the keyring.

This is pseudo code, so read the BC APIs for details.

// During initialisation
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

// During decryption
InputStream is = openKeyring(); // Wherever your keyring is
InputStream isData = openDataFile(); 

try {
  PGPSecretKeyRing kr = new PGPSecretKeyRing();
  PGPSecretKey sk = kr.getSecretKey();
  PGPPrivateKey pl = sk.extractPrivateKey("mypassphrase", securityProvider); 
  PGPObjectFactory of = new PGPObjectFactory(isData);
  Object o;
  while ((o = of.nextObject) != null) {
    if (o instanceof PGPCompressedData) {
      readAndDoWhateverINeedtoDo((PGPCompressedData) o).getDataStream());
    }
  }
}
catch (Exception e) {
  rejectFile(e);
}

So basically the Java app gets an encrypted file, gives it to BC along with the private key and gets back an InputStream that it can read the plaintext from. If it has a problem it will throw an exception that you can treat as a fatal error.

Note a few things:

  1. You will need to embed a passphrase somewhere in the Java app, but it doesn't have to be the same one that protects your public key. Remember we exported the private key into a temporary keyring so you could change the passphrase there.
  2. A determined attacked could still hack your Java file to extract the private key & password, or print out the plaintext or remove this test altogether. I suggest if this is a worry you should be obfuscating your code and putting surreptitious checks to ensure validation is not bypassed in some way. Nothing will prevent this 100% though.
  3. Just signing a file is similar to encryption except you give out the public key and keep the private key secret. In this case the Java app can detect file tampering, but the payload is plaintext.
  4. BouncyCastle is straightforward when you know it, but the documentation is terrible. You should download the source code since there are some test samples which will put you on the right course.
locka
Thank you very much for your help. I encrypted my .txt-Files and it works fine now :)
muffin