views:

212

answers:

6

For a requirement to generate per-PC license keys, I need some code which will return a stable and (near) unique key on any PC. It doesn't have to be guaranteed unique, but close. It does need to be reasonably stable though, so that a given PC always generates the same result unless the hardware is substantially changed.

This is for a Windows application, using wxWidgets but a Win32 or other option is fine.

I was thinking about MAC address but what about laptops which can routinely disable the network card in power-saving mode? I came across GetCurrentHwProfile but it doesn't quite look like what I want?

+2  A: 

One idea I had a while back for this is to use CryptProtectData as a way to identify a machine. Behind-the-scenes in that API, Microsoft has done what you're looking for. I never tested it though and I'm curious if it's actually viable.

Basically you would encode a constant magic value with CryptProtectData with CRYPTPROTECT_LOCAL_MACHINE, and the result is your machine ID.

tenfour
That's pretty interesting. We might try it, if we do I'll post back.
John
A: 

For a pretty brain dead test I am using the ProductID code of the OS and the computer name - both extracted from the registry. Not really secure, but its all pretend security anyway.

edit

To answer John's question about what keys I am reading:

SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductID

SYSTEM\CurrentControlset\Control\ComputerName\ComputerName\ComputerName

Peter M
We tried this once but found that many corporate machines (cloned machines), or warezed machines, share the license code; it made this solution completely not viable.
tenfour
@tenfour - I agree totally that this is a stupid measure. But I am playing security theatre with my "product" so it doesn't deserve anything more than that. I remember when I looked into it last that even USB keys are being spoofed now.
Peter M
Wouldn't the Windows license mean it breaks if they upgrade the OS? But anyway, can you expand on your answer with the specific keys you access, or the code you use?
John
@John .. My "product" is an industry specific niche solution so I am always working 1 on 1 with the customers. So upgrades etc are not an issue - if they have a problem they'll come to me. As for the registry keys .. I'll have to kill you now :D
Peter M
@Peter M: thanks. Our situation is similar, it's a specialist product not one sold freely. So I guess we could provide new license keys if this happened.
John
+1  A: 

I would just go with the MAC address method; when the wireless / LAN cards are turned off they still show up in Network Connections. You should therefore still be able to get the MAC.

Consider this: Any time you'd be able to contact your webserver or whatever you're cataloging these IDs with, the user is going to have to have some form of network card available.

Oh, and you might be able to use CPU serial number of the customer's computer supports it.

Billy ONeal
Both can be spoofed. You won't be able to get the MAC addressed used by the client if it goes through a router to reach the server (which is most likely to be the case).
Bruno
I think the software runs directly on the client machines, so it would be possible to get the MAC address.
@Bruno - I'd say that any bit of information that is writable can be spoofed. As for getting the MAC address, a local program on the PC can extract it and then forward that on as data to the licensing system
Peter M
Sure, but that can be tweaked quite easily before the local program reads it. It's of course much easier to do on a virtual machine, but that can be done with actual hardware too.
Bruno
Don't care about spoofing. However we need to get this code when app starts, to validate the license file... not just when it goes online
John
Please, for any technique you mention like CPU id, give an example or a link.
John
@John: How could you validate the license file and verify that it is on that unique machine without a list of all machines? Anyway, you can get CPU serial number from WMI : http://msdn.microsoft.com/en-us/library/aa394373(VS.85).aspx IIRC.
Billy ONeal
@Billy: not sure I understand the question. Since we don't have the app web-enabled, the idea is on installation it will spit out a machine-specific code for them to email support. Support then generate a license file using this code which is sent back to user, who just drops it in the right folder. When the app starts, it checks the license is valid against the machine-specific key in some fashion
John
+1  A: 

If you want something a bit harder to spoof than whatever the machine itself can tell you, you'll probably need to provide a USB dongle dedicated for this purpose (not just a flash drive).

Bruno
@Bruno - when I looked a few years ago even USB keys were being hinted at as not being secure. But it all comes down to $$ - how much money you invest in security vs the cost to the people cracking it (plus how much it is worth to them).
Peter M
Yes, nothing is 100% secure, it's a matter of risk assessment indeed.
Bruno
I suggested this but client won't go for it. Info from the PC is fine, not worried about spoofing - but it needs to not change when they turn off WiFi or whatever.
John
I suspect most laptops have a wired network card. You could try read the MAC address from it, even if it's not used or the cable is not connected.
Bruno
A: 

How about using the serial number of the harddisk where windows is installed?

The function GetVolumeInformation() will give you such serial number. To access the ID assigned by the harddisk vendor instead of the ID assigned by Windows, you can use the Win32_PhysicalMedia Class.

To determine the drive where windows is installed, you could expand the variable %windir" by using the function ExpandEnvironmentStrings()

Another option, if your architecture allows, is to use UuidCreate() to generate a random GUID at installation time and save it permanently in the registry. This GUID can then be used as the ID as long as the registry remains. A new registry database is generally considered as a new installation.

A third option is to have a well-known server assigning the IDs. Upon starting up, the software could look up for the ID in the registry and if not found, would contact the server and supply it with its MAC address, hostname, harddisk serial number, Machine SID and any number of indentifyable information (keys).

The server then determines if the client is already registered or not based on the information given. The server could have a relaxed policy and for example only require most of the keys for a match, so that the mechanism would work even in the event of a complete wipe out of the registry and if part (but not all) of the hardware was replaced.

Fabio Fernandes
A: 

How about using the serial number of a CPU. I remember Microsoft used to provide an api for this that would run the necessary assembler code and give you back all sorts of info about the CPU including serial number. Not sure if it'd work with AMD chips or not, I think it was intel specific.

Surely CPU Id is secure and static enough!!

toby