0

I'm writing a desktop java application. The program receives XML files from the customer's server. The data in a couple of tags is of type integer and is "encrypted" with some math formulas. When my program parses XML files, I need to decrypt those tags. The formulas for decryption looks like this:
int decrypted = (int) Math.ceil(Math.pow ((idProduct + 1) / 3, 1.5));
The decrypted data is then saved to H2 database, which is encrypted with AES-128.

What I need is to somehow hide such formulas from decompilation.

My attempts:
1. To hide the formulas I tried to use obfuscators, but I haven't found any that did smth with formula. Here's a piece of code obfuscated by ProGuard 4.8 and decompiled by JAD:

private String d(String paramString) {
   long l = Long.valueOf(paramString).longValue();
   int i = (int)Math.ceil(Math.pow((l + 1L) / 3L, 1.5D));
   String str = String.valueOf(i);

   return str;
}

As you can see ProGuard did nothing with formula. We can not afford to use commercial obfuscators like Zelix KlassMaster.
2. I was thinking to try JET Excelsior (but it appears that java 7 apps're not supported yet). In addition I don't think it would be appreciated by my boss.
3. I also thought about using some wrappers like launch4j, but I don't know whether it's hard or not to extract the .jar from it.
4. Then I thought about writing an external lib in C and using JNI. But it seems that competitors would be able just to use that library.
5. The good solution IMO is to write decryption functions in ASM and paste it directly to java code like we can do this is C. Unfortunately, this is not possible.
6. The encryption of classes is pointless to use.
I understand that everything could be decompiled/disassembled, I just want to make it a little bit harder than just run JAD and get it at once.

Please advise me

Dmitry Stril
  • 1,385
  • 4
  • 16
  • 34
  • 4
    how about putting that at server and making webservice call ? – jmj Jan 17 '13 at 08:46
  • They are not awefully difficult functions why dont you reimplement them and then obfuscate? – Karthik T Jan 17 '13 at 08:46
  • 3
    Security through obscurity is a Very Bad Idea. If you are trying to encrypt data, you should strongly consider using a well-known, open encryption algorithm so that even if people do decompile the program they still can't break the security. – templatetypedef Jan 17 '13 at 08:48
  • If you ever need to publish any programs to end-users, I am afraid there is no way to prevent the end-user from cracking your program. You can just make it (much) more difficult, but yet, still crackable if one really wants to. – Alvin Wong Jan 17 '13 at 08:51
  • Well, [dongles](http://en.wikipedia.org/wiki/Dongle) could be used to run practically impossible to obtain algorithms on the user-side, but they're not economically feasible for most applications. – enobayram Jan 17 '13 at 08:57
  • @JigarJoshi The problem is that the XML files are very big. There're a lot of records in them. It would take a lot of time to make a call to web-service for each record. Furthermore updating database (where decrypting is used) must be possible in offline mode. – Dmitry Stril Jan 17 '13 at 09:01
  • @AlvinWong How can I make cracking it more difficult in my case? – Dmitry Stril Jan 17 '13 at 09:13
  • If you're encrypting / decrypting an integer, why not use something like RSA? Decompilation would give the person your public key, and you keep the private key to yourself. – Teepeemm Dec 09 '13 at 14:27

2 Answers2

2

When you are thinking of writing the formula in asm/c/c++ and then access it via JNI, this means to represent the formula in a different instruction set. Instead of using a hardware instruction set, you can invent your own, and embed an interpreter for it in in your code. This has disadvantage of being less performant, but has advantage of using uncommon instruction set, so competitors should first reconstruct your home-made instruction set from the bytecode of the interpreter. You can design you instruction set to be even less understandable than that of x86.

Then, you can apply this idea recursively: write the interpreter in another interpreted instruction set etc.

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38
0

You cannot hide the formula from someone determined to find it.

Obfuscating the Java code does nothing as the .class file can be decompiled and the algorithm extracted relatively easily.

The best you could do is implement the formula in C/C++ and link it in via JNI. But even with that approach someone could decompile the C++ and with a little effort reverse engineer the process.

You could possibly hide it by spreading it out among several unrelated methods that must all get called during processing, if your application has a structure that provides the opportunity to do so.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
  • I would be satisfied if competitors had to decompile C/C++ code, but wouldn't they be able just to link that library to their own code and pass all data to it? – Dmitry Stril Jan 17 '13 at 09:10
  • 1
    So what you want to achive: hide the algorithm, or prevent users from using it? – Alexei Kaigorodov Jan 17 '13 at 10:12
  • @AlexeiKaigorodov I want to make it harder to decrypt those XMLs. To hide the algorithm so that one couldn't write a decryption script in 10 minutes looking on the decompiler's output. On the other hand I want to complicate the usage of my decryption code (e.g. native library). – Dmitry Stril Jan 17 '13 at 13:06
  • I've got an idea! 1. The decryption functions would be implemented in a native (.dll in my case) library. Then I'll obfuscate it a little (not to reduce calculation performance) on a machine code level. This will solve the problem of hiding the algorithm to a sufficient extent. – Dmitry Stril Jan 17 '13 at 15:06
  • 2. The next problem is to prevent usage of my DLL by malefactors. At every call (or every N calls) to decrypt(...) function in DLL there (in that func) would be a call back to one of the fields or functions in the java class. The result of this call would be compared to some constant value in the native library. If the result is expected then return decrypted value, else - return -1. – Dmitry Stril Jan 17 '13 at 15:07