序列号生成器和解码器

来源:互联网 发布:什么是软件协会 编辑:程序博客网 时间:2024/04/30 01:42

/********************************************************************
*程序开发环境,DOS16下编译运行.请用WIN-TC,TC2.0等16位核心的编译器.
*作者KEN
*QQ:328266362
*编写时间:2006.12.02
*
*作用:1.序列生成器.  getkeysn(日期,次数,序列字符串(返回))
*     2.序列号解码器 ungetkeysn(序列号字符串,&日期,&次数)
*     两个函数的出错返回1,正确返回0;
*其它函数为内部函数,请不要直接调用,以免出错.
*序列号由snkey字符串产生.
*k_  变量是干挠值
*改变snkey序列,就可变化出不同的序列号.
*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <dos.h>

char  snkey[200]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//int k_year=0,k_mon=0,k_day=0,k_usetime=0,k_p0=0;
int k_year=6759,k_mon=12,k_day=19,k_usetime=9,k_p0=4;   //干扰值,防止猜解.

int main(int argc, char *argv[])
{
 
  char usestr[200];
  char keysn[500];
  int i;
  int usetime;
  struct date d;
  struct date un_d;
  int un_usetime;
  char t='9';
  srand(time(NULL));
  getdate(&d);
  d.da_year=2007;
  d.da_mon=7;
  d.da_day=16;
  usetime=78;
  //strcpy(usestr,"OMMSNOMONM");

  printf("year=%d,mon=%d,day=%d,time=%d/n",d.da_year,d.da_mon,d.da_day,usetime);
  if (getkeysn(d,usetime,keysn))
  {
    printf("date error!");
    getch();
    exit(0);
  }
  //strcpy(keysn,"BCOM-MTTN-NSVV-BCFY");
  printf("%s/n",keysn);
  if (ungetkeysn(keysn,&un_d,&un_usetime)==0)
    printf("%d %d %d %d/n",un_d.da_year,un_d.da_mon,un_d.da_day,un_usetime);
  else
    printf("key error!");

  getch();
  return 0;
}

//XXXX-XXXX-XXXX-XXXX
//返回值等1代表出错.
ungetkeysn(char key[],struct date *d,int *usetime)
{ //根据keygen算法解密!
  char unkey[200];
  char keytmp[200];
  char part1[3];
  char part2[11];
  char part3[5];
  char xystr[5];
  char c_year[5];
  char c_mon[3];
  char c_day[3];
  char c_usetime[3];
  int i;
  int p;  //序列的加密值
  ungekey(key,unkey);
  if (strlen(unkey)!=16) return 1;  //序列号格式不正确.
  getstr(unkey,0,2,part1);
  getstr(unkey,2,10,part2);
  getstr(unkey,12,4,part3);
  strcpy(keytmp,part1);
  strcat(keytmp,part2);
  xykey(keytmp,xystr);
  if (strcmp(xystr,part3)!=0)
  {
   //printf("error");
   return 1; //检验值失败就返回错误值.
  }
  unkeygen2(part1,k_p0,part1);
  p=atoi(part1);
  //printf("/nbe part1=%s,part2=%s p=%d",part1,part2,p);
  unkeygen2(part2,p,part2);
  //printf("af part2=%s",part2);
  getstr(part2,0,4,c_year);
  getstr(part2,4,2,c_mon);
  getstr(part2,6,2,c_day);
  getstr(part2,8,2,c_usetime);
  (*d).da_year=atoi(c_year)-k_year;
  (*d).da_mon=atoi(c_mon)-k_mon;
  (*d).da_day=atoi(c_day)-k_day;
  *usetime=atoi(c_usetime)-k_usetime;
  //printf("part2=%s",part2);
  //printf("%d %d %d %d/n",d.da_year,d.da_mon,d.da_day,usetime);
if ((*d).da_year>2099 ||
    (*d).da_year<1980 ||
    (*d).da_mon>12    ||
    (*d).da_mon<1     ||
    (*d).da_day>31    ||
    (*d).da_day<1     ||
    *usetime<1      ||
    *usetime>90)
{
  //d.da_year=d.da_mon=d.da_day=usetime=0;
  return 1;                        //序列号数值不正确.
}
  return 0;

}

getkeysn(struct date d,int usetime,char keysn[])
{
  char part1[3],part2[11],part3[12];
  char sntmp[200];
  char usestr[13];
  unsigned  int i,n,p,sntmplen;
  char c_year[5],c_mon[3],c_day[3],c_usetime[3];
//检查输入的合法性,非法输入的参数,返回非零.
if (d.da_year>2099 ||
    d.da_year<1980 ||
    d.da_mon>12    ||
    d.da_mon<1     ||
    d.da_day>31    ||
    d.da_day<1     ||
    usetime<1      ||
    usetime>90)
    return 1;

  itoa10((d.da_year+k_year),c_year);
  itoa10(d.da_mon+k_mon,c_mon);
  itoa10(d.da_day+k_day,c_day);
  itoa10(usetime+k_usetime,c_usetime);
  strcpy(usestr,c_year);
  strcat(usestr,c_mon);
  strcat(usestr,c_day);
  strcat(usestr,c_usetime);
  //printf("usestr=%s/n",usestr);
//生成序列号:
//[变化值(2位,加密函数返回后,再加密的型式)][日期+次数(8位日期+2位次数,加密形式)][前10位的校验值]

  //得到part1
  p=rnd(strlen(snkey)-11);          //通过p的值,变化数字在snkey上的值.
  //p=0;
  itoa10(p,part1);
  //printf("p=%d,part1=%s",p,part1);
  keygen2(part1,k_p0,part1);
  //printf("p=%d,part1=%s/n",p,part1);
 //--------------------------

  //得到part2
  keygen2(usestr,p,part2);
  //---------------------------

  //得到part3
  strcpy(sntmp,part1);
  strcat(sntmp,part2);
  xykey(sntmp,part3);  //计算part1+part2的校验值,存入part3);
  //----------------------------

  strcpy(keysn,part1);
  strcat(keysn,part2);
  strcat(keysn,part3);
  gekey(keysn,keysn);

  return 0;


//----------------------------------------------------------------
//以下的函数是内部函数,不对外调用,只对主函数getkeysn,ungetkeysn调用.
//----------------------------------------------------------------

 

//输入原始字符,变化值
//输出变化值
keygen2(char usestr[],int p,char keysn[])
{
  int i,n;
  int m;
  m=strlen(usestr);
  for (i=0;i<m;i++)
   {
     n=usestr[i]-48;
     keysn[i]=snkey[n+p];
   }
   if (usestr!=keysn) keysn[i]='/0';
}

unkeygen2(char key[],int p,char unkey[])
{
  int i;
  int snn;
  char tmp[]="/0/0";
  for (i=0;i<strlen(key);i++)
  {
    *tmp=key[i];
    snn=getsnn(tmp);
    if (snn==-1) return 1; //错误返回
    unkey[i]=snn+48-p;
   }
  if (key!=unkey) unkey[i]='/0';
}

//内部调用涵数,返回密码列序的序号
int getsnn(char *key)
{
  int i;
  int snn=-1;     //return -1 is wrong!
  for (i=0;i<strlen(snkey);i++)
  {
    if (*key==snkey[i])
    {
     snn=i;
     break;
    }
  }
  return snn;
}
 

//这是个随机函数,可以产出一个由0到n的随机数.
//请在main()里先加入以下两句.以产生不同的数
//time_t t;
//srand((unsigned) time(&t));

int rnd(int n)
{
  return rand() % n;
}


int itoa10(int p,char char10[])
{
itoa(p,char10,10); 
if (p<10)
  {

    strcat(char10,"0");     //补零
    strrev(char10);         //串反转
  }
}

int gekey(char key[],char newkey[])
{
  char keytmp[200];
  int key_len,i,tn;
  key_len=strlen(key);
  tn=0;
  for (i=0,tn=0;i<key_len;i++)
  {
    keytmp[tn]=key[i];
    tn++;
    if (i % 4==3 && i< key_len-1) {keytmp[tn]='-';tn++;}
  }
  keytmp[tn]='/0';
  strcpy(newkey,keytmp);
}

/*------------------------------------------
功能:将一个

-------------------------------------------*/
int ungekey(char key[],char newkey[])
{
  char keytmp[200];
  int key_len,i,tn;
  key_len=strlen(key);
  tn=0;
  for (i=0,tn=0;i<key_len;i++)
   {
    if (key[i]!='-')
     {
       keytmp[tn]=key[i];
       tn++;
     }
   }
  keytmp[tn]='/0';
  strcpy(newkey,keytmp);
}

//
int getstr(char str[],int beginn,int getn,char newstr[])
{
  int i;
  int newn=0;
  for (i=beginn,newn=0;i<beginn+getn;i++,newn++)
   {
     newstr[newn]=str[i];
   }
   newstr[newn]='/0';
}


int xykey(char key[],char newkey[])
//计算一个字符串的校验值,返回一个新字符串作校验值
{
  int keylen,i;
  unsigned long k=0;
  keylen=strlen(key);
  k=0;
  for (k=0,i=0;i<keylen;i++)
      k+=(key[i]-47)*(key[i]-47);
  itoa(k,newkey,10);          //校验值=各位数-47的乘积
  getstr(newkey,0,4,newkey);
  keygen2(newkey,k_p0,newkey);
}

原创粉丝点击