2

I am trying to create a registration code for my C# 2.0 desktop application, which is a pay-per-use application. The registration code must hide an int value within it (the int value represents the number of uses for the application).

To generate the code from my machine, I have a separate application that uses Name, Random Number and the # of uses as the inputs. For example:

Name:  BOBSMITH  
Random number:  51728  
Number of Uses: 50  
Concatenated String: BOBSMITH_51728_50

If I do a hash on the Concatenated String (for example an MD5 hash) I get a 32 hex string (I'll call it the Reg Code) similar to: ABCD 1234 EFGH 5678 IJKL 9012 MNOP 3456

Now, on my users' side of things, when they are registering the application, I need to verify the Reg Code AND determine the # of uses from the Reg Code/Name/Random Number. So the user will enter these values:

Name: BOBSMITH  
Random Number: 51728  
Reg Code: ABCD 1234 EFGH 5678 IJKL 9012 MNOP 3456 

My question: How can my application determine (based only on the Name, Random Number and Reg Code):

  • That the registration Code is correct
  • The # of uses that were initally given from my machine

One simple idea I have thought of is to generate a Hash based on only the Name and Random Number (let's call it code A) and then add the # of uses to this hash (code B). For example:

Code A: ABCD 1234 EFGH 5678 IJKL 9012 MNOP **1184**  
Code B: ABCD 1234 EFGH 5678 IJKL 9012 MNOP **11B6**

If we subtract Code A from Code B, we get 50. Hence, my user would enter these values:

Name:BOBSMITH  
Random Number: 51728  
Reg Code: ABCD 1234 EFGH 5678 IJKL 9012 MNOP 11B6  (Code B)  

To verify the Reg Code and # of uses (from the user side), my application would take the hash of Name & Random Number, which would give the same value as Code A. I would then subtract the Code A from the Reg Code that the user entered and see that the difference is 50. Hence, I would know to give the user 50 uses. This solution seems too insecure, however. I would appreciate anyone's suggestions.

janisz
  • 6,292
  • 4
  • 37
  • 70
  • 7
    You probably want to encrypt rather then hash. Then you can dencrypt the value using your program. – Trisped Dec 05 '12 at 20:17
  • 1
    @Trisped Yeah. A hash is as smart as those animals that hide stuff for the winter so well they do not know anymore where it is. I wonder how the OP thinks he "decodes" the hash without a rainbow table. – TomTom Dec 05 '12 at 20:21
  • 6
    Use public private key. Just sign or encrypt the key with your private key and then validate or decrypt with your public key. – paparazzo Dec 05 '12 at 20:21
  • 1
    There should be enough "registration" schemes, no need to invent your own. – Maarten Bodewes Dec 05 '12 at 20:23

3 Answers3

4

TL;DR version: It's impossible. "Pay-per-use" and "desktop application" don't mix.


Is hiding the number actually the goal, or are you assuming that hiding it somehow helps prevent tampering? (Are you trying to not show the consumer how many uses they've paid for? Sounds dishonest.) You can verify that the value hasn't been tampered with by using a message authentication code, even when the number is stored in plain sight, since changes will invalidate the MAC.

This still won't solve your problem, however. It does you no good to protect the number of uses purchased if the user can tamper with the counter of how many have been used. In the simplest attack, the user can simply enter the same registration code onto a second computer, to double the number of uses. And this counter has to be incremented by the software running on the user's computer, so he necessarily possesses all the information needed to update it.

Even if you stored the counter on some secure central server under your control (which also removes the problem of protecting the allowed use count), you still can't prevent the user from patching out the part of the software that calls home. The only thing you can do is host the software in the cloud, so you can count the number of uses without the user cooperating.

See the #1 Law of Software Licensing.

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Have them enter both name and uses, and use hmac(name+uses+secret) as your key. – Cory Nelson Dec 05 '12 at 20:51
  • @Cory: Then "secret" needs to be present on the end-user computer. A proper MAC using asymmetric cryptography solves that problem, but doesn't stop the user from resetting the "used" count, thus guaranteeing that "used < allowed" forever. – Ben Voigt Dec 05 '12 at 20:52
0

The very definition of a secure hash disallows any possibility of getting a number back.

But that doesn't mean you can hash everything else, and then hide the number of in your hash code another way. You example of adding a number on the end of the hash can work, however if you do that I would also recommend you also compute a check sum from the resulting value and append it to the code to make tampering for difficult.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Checksums are design to secure against random errors, not malice. You'd still suffer from "XOR your license code with AABBCC in order to get 128 additional uses"-style attacks, which adjust both value and checksum. – Ben Voigt Dec 05 '12 at 20:55
  • Depends on the kind of checksum – Joel Coehoorn Dec 05 '12 at 21:28
0

Hashes are one-way only, so you won't be able to get back anything you hash. Encryption is two-way so you will be able to get back anything you encrypt.

To prevent someone changing the encrypted number, you will need authentication as well. Either use AES-GCM (which includes authentication) or else either AES-CTR or AES-CBC (which don't include authentication) together with HMAC-SHA-256 for the authentication.

Computer security is not easy. A lot of the problems have been solved, but the solutions are not always simple. Apparently minor errors can cause major security holes.

rossum
  • 15,344
  • 1
  • 24
  • 38