I've read over 10 similar questions and am still confused how to properly protect my JavaFX software from reverse-engineering. I understand it is never 100% possible to prevent an attack, especially in Java, and that ProGuard or similar can obfuscate to an extent, but a dedicated person could reverse it. I also understand that I should minimize annoying legit customers - while maintaining enough security to deter those edge cases into purchasing.
I've read here and here that I should use the server to perform all sensitive, valuable functions and data manipulation, such as license validation. I've constructed a PHP login system and have it integrated into my code using PostgreSQL. I'm in the process of migrating all important code to the server and using REST to return the response from the server. The client code will be a skeleton in the end, connecting all of the juicy server calls.
Right now when a user starts my app it checks for a license file on their system and if one exists, hashes the contents and compares them to my database. If there isn't a license file then they're prompted for username/pass which is hashed and compared to my database. This works fine except that I feel it's pointless.
The first link above says the server shouldn't return a simple boolean because
If you have [the server] returning just a boolean, it will be very easy for people to just edit their hosts file (on windows at least) and have small server running that always returns true. Have it return some kind of specific password generated from a random key you send it. I.e. in the data you send, include a random string, then hash it and send back the hash. Then check the hashes match.
Question:
What difference does it make if my code returns a simple boolean or uses a random string - or even checks with the server at all if an attacker can simply de-obfuscate and delete the validation conditional. For instance, if my source code contains:
if(validateUsingServer(String license_details){
// grant access
}
then somebody could de-obfuscate and replace it with
if(1==1){
// grant access
}
The method validateUsingServer
could do all sorts of hashing tricks but if the attacker can just remove those conditionals from the source code entirely, then what benefit does a server provide?
I've implemented jBCrypt into my code, which hashes either (i) the license file contents or (ii) the username/password entered and adds a random string to it which is generated using:
... {
String random_String = org.apache.commons.codec.binary.Base64.encodeBase64String(getNextSalt());
} ...
The server then extracts this random string, hashes it, and returns the hash only if the validation information is correct. The client meanwhile also hashes it and compares it to the server's response. This seems no stronger than a boolean since both can be replaced in the source code and recompiled.
Am I missing something? Perhaps this is the extent of protection Java can do, and if an attacker actually does replace all my validation conditionals with true
then they're essentially just bypassing access to a skeleton architecture, which relies on legitimate server access to perform anything substantial.
If you're going to claim this is a duplicate, please specifically reference the sentence which answers my confusion. Thank you kindly.