• 用C#.NET编写软件注册机


    验证注册码是保护软件产品产权的常用手段。一般过程如下,

    1、  软件发行者收集用户特有的信息;

    2、  根据用户特有的信息,使用注册机生成注册码并把注册码发给客户;

    3、  向软件导入注册码,由软件自己验证注册码的正确性。

    这个过程是如何实现的呢? 我写了一个简单的实现,供大家研究。因为是初次进入这个编程领域,希望高手们给我更多的指导。

    第一步利用用户的机器名生成客户特有的认证码

    代码如下:

     

    1>> MD5CryptoServiceProvider provider1;

    2>> byte[] array1;

    3>> string text1;

    4>> string text2;

    5>> byte num1;

    6>> byte[] array2;

    7>> int num2;

    8>> provider1 = new MD5CryptoServiceProvider();

    9>> array1 = provider1.ComputeHash(Encoding.Default.GetBytes(Environment.MachineName));

    10>> text1 ="ENTOPYMICROSYSTEMSDEVINIMMUHENDISLIK231456789ACD23456789AEFABGHJKLMNPRSTUVWYZXAHMETALIAKKASHAKANESKICI";

    11>> text2 = string.Empty;

    12>> array2 = array1;

    13>> for (num2 = 0; (num2 < array2.Length); num2 = (num2 + 1))

    14>> {

    15>> num1 = array2[num2];

    16>> text2 = string.Concat(text2, text1.Substring((num1 % text1.Length), 1));

    17>> }

    18>> this.txtMachineCode.Text = text2.Substring(0, 10);

    首先,我们把用户机器上得到的机器名字串用MD5计算出一个哈希值,参见第9行。

    比如,如果MachineName = “WORKGROUP”的话, 我们得到了一个16字节的整数数组:array1{61,2,205,140,186,38,191,108,238,218,125,4,55,81,100,215}。

    然后,我们分别使用16个整数,到密码字典(第10行,text1就是一个密码字典)中找到对应的字符,然后把找到的这16字符连成字符串,就得到了认证码。

    注意点:

    1、  这里的密码字典的定义方法很容易被反编译,大家可以使用其它更隐蔽的方法;

    2、  密码字典的长度有限,我这里使用了模除,参见第16行;

    3、  本例中只使用了16位认证码的前10位“GTN1L1AMIT”,参见第18行;

    最后,用户把他的10位认证码“GTN1L1AMIT”和其它的信息(用户ID:gujinsong, 用户名:gujinsong, 注册类型:0, 公司名: china, 生成时间: 2008/12/8 17:20:32)一起发给了软件发行者。

    第二步,软件发行者在收到用户的信息后,按照下面的代码生成了注册码:

    1>> stream1 = new MemoryStream();

    2>> formatter1 = new BinaryFormatter();

    3>> formatter1.Serialize(stream1, this.txtMachineCode.Text);

    4>> formatter1.Serialize(stream1, this.txtUserId.Text);

    5>> formatter1.Serialize(stream1, cboLicenseType.SelectedIndex);

    6>> formatter1.Serialize(stream1, txtUserName.Text);

    7>> formatter1.Serialize(stream1, txtCompany.Text);

    8>> formatter1.Serialize(stream1, System.DateTime.Now);

    9>> array1 = stream1.ToArray();

    10>> provider1 = new RC2CryptoServiceProvider();

    11>> provider1.KeySize = 128;

    12>> provider1.GenerateKey();

    13>> provider1.GenerateIV();

    14>> array2 = provider1.IV;

    15>> array3 = provider1.Key;

    16>> transform1 = provider1.CreateEncryptor();

    17>> stream1 = new MemoryStream();

    18>> stream2 = new CryptoStream(stream1, transform1, System.Security.Cryptography.CryptoStreamMode.Write);

    19>> try

    20>> {

    21>>      stream2.Write(array1, 0, array1.Length);

    22>>      stream2.FlushFinalBlock();

    23>>      array4 = stream1.ToArray();

    24>> }

    25>> finally

    26>> {

    27>>      stream1.Close();

    28>>      stream2.Close();

    29>> }

    30>> stream1 = new MemoryStream();

    30>> formatter1.Serialize(stream1, array4);

    31>> formatter1.Serialize(stream1, array3);

    32>> formatter1.Serialize(stream1, array2);

    33>> this.txtLicenseCode.Text = Convert.ToBase64String(stream1.ToArray());

    首先,把从用户处得到的信息按照一定的顺序串行到二进制流中,见代码行2~8。其中txtMachineCode.Text是用户的10位验证码“GTN1L1AMIT”。

    然后,使用RC2加密算法加密这个二进制流。之所以要使用RC2,是因为加密后的密文需要解密,见代码行9~18。这里的密钥,是由RC2CryptoServiceProvider 随即生成的,见代码行11~15。这个密钥最终以明文的形式与秘文一起组成注册码,并发送给用户,见代码行30~32。本例中我们得到的注册码如下:

    >> AAEAAAD/////AQAAAAAAAAAPAQAAAAgBAAACKXfIynazb8FfhVCcacGIX3xxY9X7gis1H48K+WXLzX3erjqisWuGa21BbiMX

    >> G7PWGAGBke91WzmAYwqK/vtDbAt25rXNIqhIr5dVamAG/JOelvekZGyORjHjghQ9hnefxKyISKxdFtpA+nlLtAM4CX4AJv6L0Yu

    >> khiiRx4ritOrrZ+8WVLV+HSmyOImOgyAHCY6FCkbsmiYyYLEvzVttMO+8p23AMY+Vg9ZrpDzMHIC9dbxIcxLfWFuII6e8OG1z0IF

    >> Utf/8uNkT9v/1Uf5q1v0BxVYMIdAdAUszpAqSYr2DecAgotLom2oFGifZLpc4NbWhazNff8ZxGwYrgp8iD4QjSUi2pTXrCwABAA

    >> AA/////wEAAAAAAAAADwEAAAAQAAAAAkwbbXFGqXhtB67KVQTACxwLAAEAAAD/////AQAAAAAAAAAPAQAAAAgAAAACs

    >> p9HYZ0Bl6oL

    注意点:

    1、  因为软件还需要用密钥来解密密文,所以密钥必须明文传递,我还没有想到更好的方法;

    2、  我们可以混淆密钥在注册码中的位置,加大破解的难度;

    3、  生成的注册码中没有换行符。

    第三步,导入注册码。

    用户输入注册码时,软件需要验证注册码的真伪。基本上有两种方法:

    1、  用密钥解密密文,从而验证用户的注册信息;

    这种方法只需要在软件中加入解密代码就可以了,但是他的弊端很多。破解者只要能伪装解密后的信息就可以了。

    2、使用密钥,重复生成注册码的过程,后与软件发行者提供的注册码比较,就可以了。这里就不再提供重复的代码了

  • 相关阅读:
    代码
    (转载)计算机的二进制起源
    表的新建
    SQL约束
    包装类
    GUID(转载)
    Android九宫格解锁自定义控件(附源码)
    Android滑动页面返回(自定义控件)
    Android高仿QQ消息滑动删除(附源码)
    Android跟踪球-手势移动图片-自定义控件(附源码)
  • 原文地址:https://www.cnblogs.com/GmrBrian/p/3267074.html
Copyright © 2020-2023  润新知