In all honesty, what you're trying to do is pointless. However much time it takes you to write a validation/encryption/key system, estimate roughly half that for someone to break it. Even if you encrypt the final executable. However, as a delaying measure or a way to decrease the chance of people getting premium support for stolen copies, it will help. Also for simple tracking of buyers. Or for fun. :p
Anyway, there are a few ways you can handle it.
A lot of software uses name (and possibly company) string(s) and a hash function to generate a key. This has the advantage of being constant (as long as the name is the same, the hash is, and so the key is). It is also a very simple system, especially if you use a well-known hash such as MD5.
hash = md5(name);
Some fancier apps use an internal function to generate a validation code of some sort, and when you combine that and the given name, you can create (and send back) a hash.
validCode = getCode(name);
hash = myHash(name ^ validCode);
A few use a system-based code (Windows is a good example), where it samples bits of hardware and builds an identifier from that. If you can get ahold of the processor name or speed, or anything else, you can run something like that. The only problem is system changes can render a code invalid, so you can either warn your users (and give away part of the process) or let them find out accidentally (not good).
sysID = processor_name() | ram_Speed();
hash = md5(sysID & name);
You can use any combination of hash functions, data gets, string inputs, boolean operations, etc. One thing to consider is you don't need to be able to reverse the process. As long as you can replicate it with the same results (any good hash function can), you can check the hashed results against each other and make sure it's valid. The more you put in, the more complicated it'll be, but the harder it'll be to crack.
Hopefully that helps with your question.