共享软件中注册部分的简单实现

2008-02-23 05:37:33来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

  现在,很多共享软件中使用注册码来实现对软件的保护。所谓注册码,就是一组和用户的某些特定信息(如用户名称、电脑硬件等等)相关的字符串。由于注册码传输起来比较简单,同时容易验证(相对于磁盘、光盘指纹等),因此现在注册码的应用越来越广泛,甚至一些商业软件,如Windows XP也使用了类似的机制(Microsoft称为Windows Product
Activation)。

  谈起注册码,就不能不提注册器。注册器是用来产生注册码的程式,其计算逻辑通常和受保护的应用程式一致。通过和受保护应用程式相同,或预先约定的计算逻辑得到的注册号,将决定受保护应用程式的行为,如显示“软件未注册”、禁用某些功能,或在“关于”对话框中显示注册者的姓名,等等。

  其中,最终用户通过某种方式提交其注册信息,例如他(或他所在的组织)的名字,甚至极端一些,提供某些能够确定某人身份的信息,如Pentium III CPU的CPU ID,硬盘的序列号,网卡的MAC地址等等。然后,注册服务器,或呼叫中央的服务人员根据用户提供的信息,计算一个注册号,并告诉最终用户。

  通常,由于人工操作可能造成差错,我们希望注册过程由电脑自动实现。但是这就带来了一个问题:用户凭什么相信我们的程式并不会泄漏他的个人隐私呢?针对这一问题,现在流行的做法是提供若干选项,其中包括电话注册,网络注册,连同平信注册等等,并把程式提交的内容告知用户。

  此外,某些和用户的电脑相关的信息,如配置等等,不宜使用明文传送。这一方面是由于用户可能不愿意将这些信息透露给我们,另一方面是以明文传送信息可能会导致第三方(如cracker)截获信息。现在比较流行的方法是把那些我们并无需,但却决定用户身份的信息用某种散列算法进行编码然后再发送。当然,在发送过程中我们能够使用SSL加密,或其他一些方法来确保安全,由于和本文的主要内容关系不大,在此不赘述,读者可参考相关书籍。

  需要保密的用户信息→ 散列算法 → 安全传输(如SSL) →服务器

  就笔者个人的经验,计算注册码和验证注册码使用不同的算法,能够在一定程度上提高注册过程的安全性。当然,任何安全措施都不可能确保不被解密,“世界上没有打不开的锁”,解密只是个时间问题,在构造注册码算法的时候,只要让解密代价大于软件价值即可,不必做得太复杂。

  作为用户而言,无论是用什么注册方式,他都不希望过于复杂。通过电脑直接注册的方式无疑是最方便的,但很多用户可能不愿意这样做。作为用户来说,通过电话注册这种方式,说出自己的注册ID(通常包括了产品ID、用户的名字等信息),连同输入注册码应该是各种注册方式中最麻烦的一种。因此,注册ID和注册码应该具备以下特点:

  (1)便于辨认、输入。注册码不是密码,没有必要是用大量的特别符号、大小写组合。因此,注册码和注册ID中不应该包含不同大小写的字母,连同容易混淆的数字(1-I,0-O,2-Z)。

  (2)具备查错能力。统计证实,输入注册码时,错序(如把1234输入成1243)、击键错误是最常见的错误。比较常用的方法是把注册码分成若干节,每节包括一个校验码,这样注册码就具备查错能力了。

  为了体现上面的需要,我构造了一个这样的算法:

  (1)计算输入的用户名,并按照下面的规则计算和:

  设结果为a,预置为0

  按顺序取用户名字符串的每一个字符的ASCII值,乘上位号,累加到a上。

  例如:

  J a s o n   L i
  1 2 3 4 5 6 7 8

  这样,a=(char)’J’ ((char)’a’)*2 ((char)’s’)*3 ...

  (2)将a、a²按照一定规则变换之后成为注册字符串。

  实现程式如下:

// reg.cpp : Demo program for Keygen
// By Jason Li, 2001. Written for FrontFree techonology network

#include <string>
#include <iostream>

using namespace std;

typedef int BOOL;

const BOOL TRUE=(1==1);
const BOOL FALSE=!TRUE;

// Define the magic string
const string sMagic="L5WXTUYJH7VMB4GA8SFKQN9E36RPDC";

string GetRegstr(string &sName){
string sResult="FFTN-";
long lSum=0;
long lSum1;
long lChksum;

register unsigned int i;

// Calculate the registration string
for(i=0;i<sName.length();i ){
lSum = sName.at(i) * (i 1);
}
// The checksum prevents accident input
lChksum=sMagic.at(lSum0);
sResult =sMagic.at(lSum0);
lSum1=lSum;
for(i=0;i<4;i ){
sResult =(char)((lSum) ’0’);
lChksum =((lSum) ’0’);
lSum/=10;
}
sResult =(sMagic.at(lChksum0));
sResult ="-";

lChksum=0;
lSum=lSum1*lSum1/3;
for(i=0;i<5;i ){
sResult =sMagic.at(lSum0);
lChksum =sMagic.at(lSum0)*((i%2) 1); // Sum even bytes twice
lSum/=7;
}
sResult =(sMagic.at(lChksum6));
sResult ="-";

lChksum=0;
lSum=lSum1*lSum1/5;
for(i=0;i<5;i ){
sResult =sMagic.at(lSum0);
lChksum =sMagic.at(lSum0)*((i%2) 1); // Sum even bytes twice
lSum/=11;
}
sResult =(sMagic.at(lChksum6));
sResult ="-";

lChksum=0;
lSum=lSum1*lSum1/7;
for(i=0;i<5;i ){
sResult =sMagic.at(lSum0);
lChksum =sMagic.at(lSum0)*((i%2) 1); // Sum even bytes twice
lSum/=17;
}
sResult =(sMagic.at(lChksum0));

return sResult;
}

int main(void){
string sName;
string sRegstr;

// Output the prompt for user
cout << "Registration Code Generator DEMO program version 1.00" << endl;
cout << "By Jason Li, 2001. For test purpose only." << endl;
cout << endl;

// Loop until the user name is legal to the algorithm
do{
// Get the user name
cout << "Enter the user’s name (5 chars min), followed by comma(,): ";
getline(cin, sName, ’,’);
}while(sName.length()<=5);

cout<<"User "<<sName;

sRegstr=GetRegstr(sName);

cout<<" has the registration string of "<<sRegstr;
cout<<endl;

return 0;
}

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: C程式研发经典实例之4

下一篇: 在单独线程中执行对象成员函数