The license generation method isn't really that important, as long as it's non-trivial. The trick is how your client verifies that the license is correct.
Let's say you do something like this:
BOOL verifyLicense (char* licenseKey)
{
BOOL result = false;
if(strlen(licenseKey) > 128)
return false;
char* url = (char*)malloc(1024);
sprintf(url, "%s%s", LicenseServerBaseURL, licenseKey);
char* response = http_get(url);
if (strcmp(response, "OK") == 0)
result = true;
free(result);
free(url);
}
This is pretty simple - we do some basic checks on the license key, create a URL that contains the license key, then do a HTTP GET to the server to check the license. If it returns "OK" we accept it.
The problem with this is that anyone can disassemble the client:
...
push 06f2011c ; address of url string
call http_get ; http_get(url)
mov ebx, eax ; store a copy of the result address
push 04830040 ; ASCII "OK"
push eax ; address of response string
call msvcrt.strcmp ; strcmp(response, "OK")
test eax, eax ; if( ^ == 0 )
jnz exit ; skip if branch if non-zero
mov eax, 1 ; result = true
exit:
push ebx
call msvcrt.free ; free(result)
push 06f2011c
call msvcrt.free ; free(url)
ret
All I have to do is alter the jnz exit
to a series of nop
instructions, so the jump is never taken and the result is always true. That way, any license key is accepted. Even better, I could simply modify the start of the method to immediately set eax
to 1 and return, so it never even bothers to ask your server for license validation.
So, how do we solve this problem? Unfortunately for you, we can't. You're running into the DRM problem, which essentially states that if you hand someone some data, they can always change it. No matter how much you obfuscate your code, it's possible for the user to eventually reverse engineer it and work out how to make changes, or extract data. If you encrypt content, you eventually have to have the key on the system in order to decrypt it, so there's always a way for the user to extract that key and decrypt the content permanently.
The best you can do is make it difficult, which involves a lot of time and effort. Eventually your software will be cracked and end up on a torrent site somewhere. It sucks for developers using this kind of business model, but it's the world we live in. My suggestion is that you go down one of two routes:
Create a basic licensing system that works, and accept the fact that some people will pirate it. Serve your real customers by spending your development time actually making improvements to the software, rather than implementing and maintaining draconian DRM systems.
Alter your entire development and business paradigm, so that your product is a service rather than a software application. SaaS has been very successful, since it's (practically) impossible to pirate services, and the model allows you to make real-time changes to your codebase, and perform analytics on usage.
If you go for option 1, don't involve a server for validation. It adds complexity, provides no added security, brings some privacy concerns, and makes it impossible for your users to use your software if your licensing server is down. Just stick with something simple, e.g. a hash of the username and a secret value on the client side. It's trivial to break, but it gives a minimum barrier to piracy.