Register a program for a particular system in C#

[Register a program]

This example demonstrates a fairly simple technique that you can use to register a program for a particular system. A determined hacker could circumvent it, but for most programs it won’t be worth the effort.

The idea is simple. When it starts, the program gets the system’s disk drive serial number, encrypts it, and compares the result to a value stored on the computer. If the value matches, then the program is registered and starts normally.

If the value doesn’t match or if no value is yet saved on the computer, then the program displays a registration form giving the user a Product ID (the disk serial number) and asking the user to email this to Customer Support. Customer Support encrypts the serial number and sends it back for the user to enter into the registration form. The form then saves that value so the program can start normally in the future.

The following code shows how the main customer program checks whether it is properly registered.

// If the program isn't registered, exit.
private void Form1_Load(object sender, EventArgs e)
{
    // An arbitrary number to identify this program.
    const UInt32 program_id = 2267918298;

    if (!IsRegistered(program_id, false)) this.Close();
}

This code simply calls the IsRegistered method, passing it a program ID. The program ID is an arbitrary number used to differentiate among different programs that might use the same registration procedure.

The following code shows how the IsRegistered method works.

// Return true if the program is properly registered.
private bool IsRegistered(UInt32 program_id, bool default_value)
{
    StringBuilder volume_name = new StringBuilder(1024);
    StringBuilder file_system_name = new StringBuilder(1024);
    UInt32 serial_number, max_component_length;
    FileSystemFeature file_system_flags;

    // Get the startup directory's drive letter.
    // Get the drive where the program is running.
    FileInfo file_info = new FileInfo(Application.StartupPath);
    string drive_letter = file_info.Directory.Root.Name;

    // Get the information. If we fail, return the default value.
    if (!GetVolumeInformation(drive_letter, volume_name,
        volume_name.Capacity, out serial_number,
        out max_component_length, out file_system_flags,
        file_system_name, file_system_name.Capacity))
    {
        return default_value;
    }

    // Encrypt the serial number to get the product key.
    UInt32 product_key = Encrypt(program_id, serial_number);

    // If this matches the saved product key,
    // then the program is registered.
    if (Properties.Settings.Default.ProductKey == product_key)
        return true;

    // It's not registered properly.
    // Display the registration form.
    RegistrationForm frm = new RegistrationForm();
    frm.txtProductNumber.Text = serial_number.ToString();
    if (frm.ShowDialog() == DialogResult.Cancel) return false;

    // See if the product key matches.
    UInt32 entered_key = 0;
    try
    {
        entered_key = UInt32.Parse(frm.txtProductKey.Text);
    }
    catch
    {
    }
    if (entered_key == product_key)
    {
        Properties.Settings.Default.ProductKey = entered_key;
        Properties.Settings.Default.Save();
        return true;
    }

    // No match. Give up.
    MessageBox.Show("Incorrect product key.", "Invalid Key",
        MessageBoxButtons.OK, MessageBoxIcon.Error);
    return false;
}

The code uses the GetVolumeInformation API function to get information about the disk containing the program’s startup path. It then encrypts the disk’s serial number to get a product key. If that value matches the value stored in the ProductKey program setting, the program is registered so the method returns true.

(To create the ProductKey setting at design time, open the Project menu and select Properties. On the Settings tab, create a new setting named ProductKey with type uint.)

If the encrypted serial number doesn’t match the ProductKey setting, the code displays a RegistrationForm. If the user enters a product key on that form and clicks OK, the program parses the value and compares it to the encrypted serial number. If the values match, then the user has entered the correct product key, so the function saves it and returns true.

The following code shows how the Encrypt method encrypts a UInt32.

// Simple encryption and decryption.
private UInt32 Encrypt(UInt32 seed, UInt32 value)
{
    Random rand = new Random((int)seed);
    return (value ^ (UInt32)(UInt32.MaxValue * rand.NextDouble()));
}

This method creates a new Random object, initializing it from a seed parameter. By using the same seed (in this case, the program ID), different programs can initialize the random number generator to the same state.

The function generates a random number between 0.0 and 1.0 and multiplies it by the largest possible UInt32 value. It then uses the XOR operator to combine that value with the value it is encrypting.

(Note that this method also decrypts. If you pass it an encrypted value and the seed that was used to encrypt it, it will generate the same pseudo-random number and XOR it with the encrypted value. That restores the original value. Note also that this property isn’t necessary for this program. The program never decrypts any value.)

[Register a program]

The final piece to the puzzle is the KeyMaker program that customer support uses to generate product keys. This program simply takes an entered Program ID and Product ID (emailed to customer support by the customer). It calls the same Encrypt method, passing it the program ID (specific to the program) as the seed and the product ID (emailed by the customer) as the value to encrypt. The result is the product key, which customer support emails to the customer.

There are a few improvements you could make to this method.

  • You could use stronger encryption. If you’re really worried that hackers will break open your code, however, then you should consider stronger methods for verifying customers, such as making the program validate itself with a Web Service every time it runs.
  • You could obfuscate the product ID so the user can’t notice that it’s just the disk serial number.
  • You could reformat the product ID and product key so they form groups of letters instead of a simple long number.
  • You could try using the serial number of the computer’s CPU instead of the disk.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in cryptography, programs, system, tools and tagged , , , , , , , , , , , , . Bookmark the permalink.

13 Responses to Register a program for a particular system in C#

  1. jitendraSharma says:

    can i use strings instead of Uint32 or Uint64 than how change kindly suggest me

  2. Indranil Chatterjee says:

    Sir can you send me the above program codes in vb.net.

    • RodStephens says:

      Sorry but I don’t have a VB.NET version. If you download the example program (click the Download button at the bottom of the post), you should be able to convert it into VB. The structure of the languages is very similar. They just have different syntax.

      • Indranil Chatterjee says:

        Thanks for the reply Sir.
        I have converted it successfully to VB.NET, and all its ok.
        I have a question that if i have a Product Key say 061360510 and User’s Product ID say 1086143370 then how can i get the Product ID.
        Because I run CustomerProgram in other system which generates the above mentioned User’s Product ID, but that system was already registered with that Product Key which i mentioned above.
        I am very much thankful to you if you help me on this…..

        • RodStephens says:

          How you would get the product ID will depend on how the program is generating those values. One method would use some sort of cryptographic method so you could not get the product ID from the customer ID. Another approach would be to store the customer and product IDs in a database so you could look them up later. Many system don’t know the product ID until the customer registers the product.

          • Indranil Chatterjee says:

            Let me clarify sir, i have windows form based application developed in visual basic, when i install the application a first window appears for Registration where it shows the HDD No as customer product ID like your program and i will send that hdd no to the company and they will provide the key. thats why i share the product ID and product key. I figure out they use same procedure like your program…

          • RodStephens says:

            Sorry, I think I still don’t understand what you’re asking.

            Do you mean you have the key and you need to figure out the ID from that? If you’re using cryptography, then you probably cannot recover the ID from the key. If you think you will need to do that, then you should store the ID and key in a database when the user registers the program.

            Or if you use a method such as the disk serial number, then you could have the user run the registration program again. It will fetch the serial number, which is the ID. Or I may be completely missing your question. Sorry.

  3. Indranil Chatterjee says:

    Thank you sir for the reply…
    Now i can understand…clearly

  4. Indranil Chatterjee says:

    Respected Sir,
    I need help on how can i change the datagridview cell value by double click on that cell.
    Let say cell contain value ‘N’ when i double click it will change to ‘Y’ .

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.