2025年QT设置软件使用期限

QT设置软件使用期限一 设计思路 程序启动 每次启动软件时会读取注册文件 若不存在则提示输入激活码 进行注册 若文件存在 则解析文件验证文件合法性 计算剩余使用期限 程序激活 为了使每个激活码仅对应一个用户 机器 我们的激活码应当绑定设备 因此应包含 MAC 地址信息 激活界面

大家好,我是讯享网,很高兴认识大家。

一、设计思路

程序启动

每次启动软件时会读取注册文件,若不存在则提示输入激活码,进行注册。若文件存在,则解析文件验证文件合法性,计算剩余使用期限。

程序激活

二、激活码生成端(厂家端)

生成端界面如下

在这里插入图片描述
讯享网
由一个机器码输入框、一个有效期输入框、一个激活码生成框以及生成按钮组成。
厂家需要输入用户给出的机器码,输入要赋予的有效期限,点击按钮就能生成激活码。
机器码的获取在 验证端(客户端) 中会提及。

(1)密码表

下方为用随机数生成的密码表,建议大家自己重新生成密码表。

uint8_t pwd[256]={ 
   23,95,39,51,15,49,18,20,78,45,24,4,74,113,100,123, 0,37,34,121,127,108,25,37,37,56,20,75,34,8,112,87, 19,117,101,4,24,35,82,107,93,51,95,108,28,33,88,6, 23,26,25,65,84,56,62,33,120,1,65,87,47,51,39,43, 78,23,41,43,95,26,76,50,121,96,75,8,13,24,23,115, 40,99,123,72,52,87,5,81,117,115,42,38,59,26,38,94, 105,28,6,87,18,75,93,107,101,62,19,18,7,37,89,73, 23,92,12,59,46,48,59,10,70,7,81,59,43,77,95,107, 72,66,67,59,48,106,126,120,31,80,105,99,127,9,96,72, 70,27,47,67,32,80,33,64,112,56,13,27,10,71,63,63, 100,59,91,8,1,65,9,35,14,90,71,90,123,37,21,47, 16,62,110,69,39,55,75,30,113,122,53,73,22,29,111,29, 114,89,27,85,76,84,52,85,76,62,26,60,109,90,44,21, 20,46,115,108,19,35,58,55,55,78,27,49,12,69,105,74, 109,91,90,108,127,95,76,53,53,112,74,72,79,26,109,102, 21,10,25,68,67,17,29,22,59,80,39,97,120,104,0,109}; 

讯享网

(2)生成激活码

讯享网QString getActivationCode(QString machineCode,ing yxq)//machineCode机器码,yxq有效期:天 { 
    QString sj=QDate::currentDate().toString("yyMMdd");//当前日期,由此也说明了激活码仅当天有效 //中间为激活码生成算法,不必深究 QString Activation; for(int j=0;j<6;j++) { 
    int tempCode; tempCode=pwd[machineCode.mid(j*2,2).toInt(nullptr,16)]<<sj.mid(j,1).toInt(); Activation.append(tenToHexL(tempCode)); } QString Activation2; for(int k=0;k<5;k++) { 
    int tempCode2; tempCode2=Activation.mid(4*k+4,4).toInt(nullptr,16)>>tenToBin(sj.mid(4,2).toInt()).mid(k,1).toInt(); Activation2.append(tenToHexL(tempCode2)); } Activation2.append(Activation.mid(0,4)); Activation2.remove("00"); //激活码生成算法 //此处开始为激活码带有有效期信息的部分 QString str_yxq =tenToHexL(yxq+pwd[sj.mid(4,2).toInt()]).remove(0,1); int jy = yxq ^ pwd[sj.mid(4,2).toInt()]; str_yxq.append(tenToHexL(jy).remove(0,1)); Activation2.append(str_yxq); //有效期信息部分 return Activation2 } 

三、验证端(客户端)

(1)获取机器码

机器码生成方法如下,其中pwd密码表应与生成端相同。

QString getMachineCode() { 
    QString text; //获取非00-00-00-00-00-00的mac地址 QRegExp regmac("00.00.00.00.00.00"); foreach(QNetworkInterface interface,QNetworkInterface::allInterfaces()){ 
    text = interface.hardwareAddress(); if(text.indexOf(regmac)>=0) continue; else break; } //以mac地址为序号获取密码表相应值 QString machineCode; for(int i=0;i<6;i++){ 
    machineCode.append(text.mid(0,2)); text.remove(0,3); } return machineCode; } 

(2)首次激活

用户首次启动应用时为未激活状态(即未读取到注册文件),此时需要输入厂家提供的激活码进行注册。

2.1 首次激活/生成注册文件

讯享网void Widget::on_pushButton_2_clicked()//激活按钮 { 
    QString code = ui->lineEdit->text(); QString tail = code.mid(code.length()-6,6);//code:QString激活码 tail:激活码后六位,包含有效期信息 //验证激活码有效性 QString machineCode = getMachineCode(); QString sj=QDate::currentDate.toString("yyMMdd"); QString Activation; for(int j=0;j<6;j++) { 
    int tempCode; tempCode=pwd[machineCode.mid(j*2,2).toInt(nullptr,16)]<<sj.mid(j,1).toInt(); Activation.append(tenToHexL(tempCode)); } QString Activation2; for(int k=0;k<5;k++) { 
    int tempCode2; tempCode2=Activation.mid(4*k+4,4).toInt(nullptr,16)>>tenToBin(sj.mid(4,2).toInt()).mid(k,1).toInt(); Activation2.append(tenToHexL(tempCode2)); } Activation2.append(Activation.mid(0,4)); Activation2.remove("00"); if(code.mid(0,code.length()-10)!=Activation2) return ;//激活码无效,可以根据需求设定函数返回值,返回激活失败原因,我这里偷懒就直接在按钮里了 //验证有效期部分 QString tail = code.mid(code.length()-3,3); int h = tail.toInt(nullptr,16); int iyxq = h ^ pwd[sj.mid(4,2).toInt()];//逆解出有效期 QString str_yxq =tenToHexL(iyxq+pwd[sj.mid(4,2).toInt()]).remove(0,1); if(str_yxq!=code.mid(code.length()-6,3)) return ;//激活码无效,有效期部分校验失败 //写注册文件 QFileInfo fileinfo("PassCode.dat"); if(!fileinfo.exists()){ 
    QFile file("PassCode.dat"); file.open(QIODevice::WriteOnly); QDataStream out(&file); QByteArray ba; ba.resize(15); for(int i=0;i<12;i++){ 
    ba[i]=code.mid(2*i,2).toInt(nullptr,16); } ba[12]=tail.mid(0,2).toInt(nullptr,16); ba[13]=tail.mid(2,2).toInt(nullptr,16); ba[14]=tail.mid(4,2).toInt(nullptr,16); out<<(QByteArray)ba; out<<(QDate)QDate::currentDate();//date:QDate激活日期 file.flush(); file.close(); } } 

(3)后续启动检验

程序每次启动都会检验有无注册文件,若无则执行上面的首次激活步骤,若有,则对文件数据进行校对

3.1 校对注册文件

int Widget::checkHasActivate() { 
    QFileInfo fileinfo("PassCode.dat"); if(!fileinfo.exists()){ 
    return 0;//无注册文件,返回有效期0天,执行首次激活流程 } else{ 
    QFile file("PassCode.dat"); file.open(QIODevice::ReadOnly); QDataStream in(&file); QByteArray ba; QDate date; QString code; in >> ba; in >> date; for(int i=0;i<12;i++){ 
    int a=ba[i]; code.append(tenToHexS(a));//tenToHexS()方法为十进制转为两个字符的十六进制 } code.remove("00"); code.append(tenToHexS(ba[12])); code.append(tenToHexS(ba[13])); code.append(tenToHexS(ba[14])); int yxq = checkActivationCode(code,date);//checkActivationCode为上述的验证激活码算法,返回有效期 if(yxq==3840)//永久 return 3840; yxq = yxq-date.daysTo(QDate::currentDate()); if(yxq<=0||date.daysTo(QDate::currentDate())<0){ 
    file.remove();//若有效期到期,或者检测到用户通过更改当前日期来延长有效期,则删除注册文件 //再次启动后需要执行首次激活 return 0; } return yxq; } } 

3.2 激活码验证算法 checkActivationCode

讯享网int checkActivationCode(QString code, QDate date) { 
    QString machineCode = getMachineCode(); QString sj=date.toString("yyMMdd"); QString Activation; for(int j=0;j<6;j++) { 
    int tempCode; tempCode=pwd[machineCode.mid(j*2,2).toInt(nullptr,16)]<<sj.mid(j,1).toInt(); Activation.append(tenToHexL(tempCode)); } QString Activation2; for(int k=0;k<5;k++) { 
    int tempCode2; tempCode2=Activation.mid(4*k+4,4).toInt(nullptr,16)>>tenToBin(sj.mid(4,2).toInt()).mid(k,1).toInt(); Activation2.append(tenToHexL(tempCode2)); } Activation2.append(Activation.mid(0,4)); Activation2.remove("00"); if(code.mid(0,code.length()-10)!=Activation2) return 0; QString tail = code.mid(code.length()-3,3); int h = tail.toInt(nullptr,16); int iyxq = h ^ pwd[sj.mid(4,2).toInt()]; QString str_yxq =tenToHexL(iyxq+pwd[sj.mid(4,2).toInt()]).remove(0,1); if(str_yxq!=code.mid(code.length()-6,3)) return 0; else return iyxq; } 

四、补充上述代码中缺少的一些函数

QString Widget::tenToHexL(int ten) { 
    QString a="0ABCDEF"; QString res; if(ten>255) { 
    res=a.at(ten/4096); res.append(a.at(ten/256%16)); res.append(a.at(ten/16%16)); res.append(a.at(ten%16)); } else { 
    res="00"; res.append(a.at(ten/16)); res.append(a.at(ten%16)); } return res; } QString Widget::tenToHexS(int ten) { 
    QString s = "0ABCDEF"; QString res; res.append(s.at(ten/16)); res.append(s.at(ten%16)); return res; } QString Widget::tenToBin(int ten) { 
    QString res; for(int i=0;i<5;i++) { 
    res.prepend(QString::number(ten%2)); ten=ten/2; } return res; } 

五、源代码下载

源码下载

小讯
上一篇 2025-01-11 15:23
下一篇 2025-03-09 11:14

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/11982.html