Search code examples
vb.netsecurityencryptionlicensingcopy-protection

A licensing system for my (WinForms) application. Would this be secure enough? (Within reason)


I have researched on each element or system that I am willing to implement into a generic software licensing system for my soon-to-be apps (irrelevant, as this should work, or be usable on all of my applications).

I have created a DLL with my licensing class in it. It is as follows:


(1)

I have applied the InternalsVisibleTo() attribute main class (with child classes), which makes all of the internal classes, and their methods, which are declared Friend, visible to external assemblies with the sepcified PublicKey.

I have made the reference to the app name, and it's PublicKey. (Both the licensing, and the external assembly, are signed with the same key (.snk file)

(2)

All (where possible) members, properties etc. are delcared Friend or Private or just Dim...ed .

(3)

My licensing class has a String variable; declared:

Private Shared _Key As String = "H58N2-00V93"

This variable is the special password, if you will, of my DLL, and is required to access the methods in my DLL.

There is also a Public String variable (let's call it "AccessKey"), which should be initialized with the main class, like so:

Dim licDLL As New LicensingAssemblyName.LicensingMainClass With {.AccessKey="H58N2-00V93"}

(4)

Then, I have a Function (let's call it "CheckKey"), which checks whether the Public, initialized variable ("AccessKey" is equal to the pre-defined, Friend key ("_Key"), whereupon an exception will be thrown, if they are not equal - preventing method from continued/used.

(5)

At each first line of every Sub, Function etc., I have inserted a call to this function.


These are just the 'security' measures I've taken to prevent external assemblies from using my DLL in another app, to perhaps exploit the system or generate keys.

Now for the licensing measures.


(1)

I have a key generator (very basic), which generates codes upon a given format (Like: "#-$" for a number, a dash, followed by a letter.)

I have included an encryption class in this program, which uses Rijndaenal, and applies salt.

I have set the key generator to encrypt each separate key upon generation, then append it to a new line of a file, which we'll call "my_licenses.txt".

I use the same password for each one (obviously). It is quite long, and includes many different characters (if that makes ANY difference). I considered this to be a secure way since I didn't think ANYONE could decrypt a string without the password, until I was told by another programmer, who advised against using plain text encryption as a method to secure these keys. Please help me with this.

(2)

In my licensing DLL, I have a declaration:

Friend Shared Function IsKeyValid(ByVal KeyDB As String, ByVal Key As String) As Boolean

This function decrypts each key in the file (the specified database, using the same pass code used when encrypting them in the key generation program).

Then I do a For Each, Next loop to, determining whether the specified "Key" value equals any in the key 'database', "my_licenses.txt". But here's the catch.

I have an Function which returns a unique code for the computer it's running on (using hardware IDs etc.). This Function helps me protect against the use of the same key on multiple computers (unless I implement a system for allowing this, limited times) and is required as the last 5 characters of the "Key".

After checking, this Function returns a value of the result (True or False).


Finally (phew), each assembly (the licensing one, and any external ones which utilize it) are obfuscated -and likewise signed (all assemblies, with the same key (.snk) file)- by CodePlex's Confuser (A free, and highly recommended obfuscator for .NET).

I hope this hasn't been too long/not detailed enough/difficult to understand. (If so, tell me what you don't understand).

This is my first post/question of any kind, so be nice. Also thank you for reading.

I hope you can help.

And just to confirm, my question is this: Would this system be secure enough to protect against the average hacker?

P.S. I am only a beginner, so answers for a beginner would be especially appreciated ;)

*UPDATE: I have actually reduced the length of this question, and improved its understandability (believe it or not). So this is the best I can do.


Solution

  • That's an insane wall of text so you kind of lost me. And, to be honest I stopped reading seriously when I saw you had a hardcoded key inside the binary that you plan to distribute... But there are two questions you ought to ask yourself:

    1. Is your application likely to be so successful that there is sufficient demand for it so that people with the appropriate skillset will be inclined to reverse it and release a keygen and/or pirated version?

    2. And wouldn't your time be better spent adding cool features to the application instead of licensing code which does nothing to improve the application itself?

    Don't get me wrong. I'm all for people getting paid for their work and I don't object to people licensing their software; as a matter of fact, one of the projects I worked on was a custom licensing engine which was tracking a little over 100,000 licenses last I checked. But make sure that if you decide to implement licensing that the effort you put into it doesn't exceed the effort you put into the actual software you're licensing.


    With all that said, here's what I would do:

    • Generate a lot of licensing keys (using whatever format you want)
    • Hash those keys using something like SHA-256 or SHA-512.
    • Create an array (using whatever syntax is appropriate to your language of choice) that contains the key hashes.
    • Include the array inside your application.

    With that setup, to verify a license, all you need to do is:

    • Hash the input using the same algorithm as before.
    • Iterate the array, comparing it with the result of the hash. If they match, the key is licensed. If they don't, continue.
    • If you get to the end of the table the key is not licensed.
    • Do not immediately exit the application if the key isn't licensed. Instead set a flag that prevents the use of important commands (e.g. "Save") or set a timer for 60 seconds plus a random number of to exit the application.

    Compile and then digitally sign your application with Authenticode. Have the application itself validate the signature to try and discourage casual tampering.

    If you are so inclined, you could even encrypt the hashes, although that is unlikely to help against the sort of attack that someone would mount against this scheme.

    To be clear: this is not bulletproof (then again, no licensing mechanism is) and it's possible for someone sufficiently skilled to break it in a number of ways. But it's almost certainly going to be more than good enough for your project.