I'm working on a piece of software written in VB.NET for Windows machines (mainly Windows Server). I have some understanding of cryptography and security, but I want some good old fashioned peer review on the method I'll be using to license and activate the software.
This method needs to work offline so the software can be installed on computers that aren't connected to the internet. For computers that are connected to the internet I will probably do more checks to insure the license is valid.
In general my offline licensing plan is:
- Executable is embedded with the licensing server's asymmetric public key
- Upon sale of the program, a license key is generated.
- Key is stored in the license server database along with its limitations (e.g. which version of the program it licenses and what features it includes)
(I may also tie this to a user account)
- License key is given to the user at sale
- Have the user enter the license key on the intended computer
- Generate a recreatable hardware key from the motherboard and/or other components' MAC address to uniquely identify the computer which will run the software
- Generate an "activation file" that contains: the hardware ID, license key and software version number
- Copy activation file to an internet-connected machine and upload it to the licensing server (via a website or something)
- Licensing server checks to see that the license key has not been used and that it is valid for that version of the software
- If accepted, licensing server generates a "license file" containing the hardware ID of the now registered computer along with the limitations of the license
- This license file is signed by "encrypting" it using the license server's private key (not for secrecy of the message, but to verify origin)
- The license file is copied back over to the offline machine and put in the proper place
- License Check:
- When the program starts and before it uses certain features, the program uses the embedded public key to "decrypt" the license file (which would verify the source)
- The programs checks to see that the hardware key inside the file matches the hardware key it generates from the machine
- The program checks that its version and the feature(s) being requested are included in the license
Reasons I think this works:
- Since the license key is only generated once sold, the number of "guessable" unactivated keys that exist will be relatively small
- Hardware key is registered with the license server along with the license key so that it wont accept the same license again for a different machine
- License file is signed by the licensing server's private key, so the embedded public key can be used to prevent spoofed license files
- The license file contains the hardware ID that was used to obtain it, so it can't be copied to another machine
Weaknesses I am aware of:
- Having to copy the activation and license files to/from the computer (when it isn't connected to the internet) could be a bit of a hassle.
- Is it even possible to generate a reliable hardware ID if the program is being installed on a VM?
- The embedded public key in the executable could potentially be swapped out to allow for license file spoofing
- The software version number in the executable could potentially be modified somehow to allow it to use licenses intended for a previous version
- The code itself could potentially be modified to bypass the license checks
- Anyone intending to move the software to another computer would require a new license key (not that I would necessarily make them buy a new key)
Is there any advantage to an arithmetically generated key vs a purely random one? I know some keys have digits that add up to other digits so you can easily spot an obviously fake or mistyped key, but doesn't that just limit the number of actual keys valid keys and so make it easier (statistically) to guess a real one?
I would appreciate anyone who can punch holes in the security of the above.
I would also appreciate any recommendations regarding license key length, the process of generating hardware IDs (and how I would do so on a VM) and any way I could discourage or make it difficult for someone to tamper with the executable to modify the license check code or public key.