2

I have to license a java application and want to code a quick implementation, the scheme I came up with is:

  1. The Application calculates a string X which we assume to be the md5 sum of the computer's mac address, the current date and some other information.

  2. the application returns a string Y equal to the last 16 digits of X to the user

  3. the user contacts the Software Support office giving Y and the office encrypts Y using AES with a secret key and returns a string Z equal to the last 16 digits of the encrypted Y

  4. the user inputs Z in the application and this checks that Z is equal to its own Z which is calculated the same way as at the Software Support. If the two are the same the software unlocks.

Now I would like to know whether two assumptions are reasonably safe or not:

  1. Assume a cracker knows how Y is calculated and can calculate it for its own copy of the software and uses this Y to request a Z to the support center and unlock his copy of the software. Is it possible he will be able to calculate for every possible Y he wants a matching Z to unlock any copy of my software?

  2. Because my software contains the encryption key inside the application bytecode a cracker with enough knowledge can decompile the encryption key and create his own Z to unlock the program (assume I tried my best obfuscating the code). A solution would be to use public key cryptography, however this would be useless in my opinion because if a cracker is able to decode the compiled bytecode of the application he will totally bypass whatever encryption scheme I will put because in the end there will always be a part of the code checking for a condition and setting that condition always to true will bypass any encryption scheme I will come up with. is it true?

Mike Edward Moras
  • 18,161
  • 12
  • 87
  • 240
dendini
  • 123
  • 1
  • 3

2 Answers2

2

To begin with, let's assume that the attacker cannot extract the AES key from your software. That means the best they can do is a chosen-plaintext attack on AES: choose a block $Y$, request its encryption $Z$, repeat as many times as desired and try to use the results to figure out something useful about the encryption of other plaintext blocks.

Since AES is believed to be IND-CPA secure, i.e. indistinguishable from a random permutation under chosen plaintext attacks, this is not likely to work. If the attacker cannot somehow distinguish AES from a random permutation (which, if AES is as secure as it's assumed to be, they shouldn't be able to do), all they can do is try to compile a long list of plaintext/ciphertext pairs and hope that the key they want to crack is found in the list. But as long as you don't truncate the inputs too much, that isn't likely to happen either. (You don't specify what you mean by a "digit", but as long as one digit contains at least 4 bits, 16 digits amounts to at least 64 bits, which should be sufficient.)


However, that's all assuming that the attacker cannot just extract the AES key from the software. If they can, then creating their own license key generator will be trivial. Note that, from the attacker's perspective, extracting the AES key is much more useful than just modifying the software to disable the key check: knowing the AES key allows them to create valid license keys for any copy of the software on any platform, including future upgrades.

Extracting the key is also likely to be easier than modifying the code, especially if you use the standard system crypto library for your AES implementation. (As CodesInChaos notes, the attacker can just run the code under a debugger and log all system library calls it makes; the call to AESEncrypt() or whatever ought to stand out as a good target for a breakpoint.) Using your own obfuscated AES implementation could make it a bit harder, but that's not really guaranteed to work either: crypto code tends to look fairly distinctive when decompiled, and even if the attacker fails to realize that they're looking at AES, they could still just lift the code and its inputs wholesale.

Thus, if you don't want anyone to be able to write key generators for your software, I'd strongly suggest using digital signatures instead. If you don't want to do that, your other option is to just obfuscate the heck out of your code and accept the fact that a skilled and determined attacker will be able to reverse engineer it and write a license key generator. Or, you know, consider whether you really even need a license key in the first place.

Ilmari Karonen
  • 46,700
  • 5
  • 112
  • 189
2
  • embedding a symmetrical (AES) key in your software really is pointless - an attacker could easily extract the key and generate their own software license key, or worse, create a small program (a crack) that allows other users to generate their own license keys
  • I recommend RSA - generate 'Z' (as per your question) by signing the data 'Y' with a private key, and verify 'Z' with the corresponding public key, which can be safely embedded in the application. The public key can only be used to verify the authenticity of data signed with the private key — it cannot be used to create a valid signature by itself.
  • Regarding someone decompiling your software, that's really not related to software licensing, but it's a valid concern, albeit not one that can be mitigated by cryptography. That being said, any 'cracker' skilled and determined enough to decompile your software and make their own version is probably skilled enough to write their own software anyway (generally speaking).
hunter
  • 4,051
  • 6
  • 29
  • 42