• Qt编写密钥生成器+使用demo(开源)


    在很多商业软件中,需要提供一些可以试运行的版本,这样就需要配套密钥机制来控制,纵观大部分的试用版软件,基本上采用以下几种机制来控制。
    1:远程联网激活,每次启动都联网查看使用时间等,这种方法最完美,缺点是没法联网的设备就歇菜了。
    2:通过获取本地的硬盘+CPU等硬件的编号,做一个运算,生成一个激活码,超过半数的软件会采用此方法,缺点是不能自由控制软件的其他参数,比如软件中添加的设备数量的控制。
    3:设定一个运行到期时间+数量限制+已运行时间的密钥文件,发给用户配套软件使用,缺点是如果仅仅设置的是运行到期时间,用户可以更改电脑时间来获取更长的使用时间,在电脑不联网的情况下。
    本demo采用抛砖引玉的形式,用第三种方法来实现,密钥文件采用最简单的异或加密,可以自行改成其他加密方法。

    完整代码下载地址:https://download.csdn.net/download/feiyangqingyun/10975625

    核心代码:

     1 #include "frmmain.h"
     2 #include "ui_frmmain.h"
     3 #include "qmessagebox.h"
     4 #include "qfile.h"
     5 
     6 frmMain::frmMain(QWidget *parent) : QWidget(parent), ui(new Ui::frmMain)
     7 {
     8     ui->setupUi(this);
     9     this->initForm();
    10 }
    11 
    12 frmMain::~frmMain()
    13 {
    14     delete ui;
    15 }
    16 
    17 void frmMain::initForm()
    18 {
    19     QStringList min;
    20     min << "1" << "5" << "10" << "20" << "30";
    21     for (int i = 1; i <= 24; i++) {
    22         min << QString::number(i * 60);
    23     }
    24 
    25     ui->cboxMin->addItems(min);
    26     ui->cboxMin->setCurrentIndex(1);
    27     ui->dateEdit->setDate(QDate::currentDate());
    28 
    29     for (int i = 5; i <= 150; i = i + 5) {
    30         ui->cboxCount->addItem(QString("%1").arg(i));
    31     }
    32 }
    33 
    34 QString frmMain::getXorEncryptDecrypt(const QString &data, char key)
    35 {
    36     //采用异或加密,也可以自行更改算法
    37     QByteArray buffer = data.toLatin1();
    38     int size = buffer.size();
    39     for (int i = 0; i < size; i++) {
    40         buffer[i] = buffer.at(i) ^ key;
    41     }
    42 
    43     return QLatin1String(buffer);
    44 }
    45 
    46 void frmMain::on_btnOk_clicked()
    47 {
    48     bool useDate = ui->ckDate->isChecked();
    49     bool useRun = ui->ckRun->isChecked();
    50     bool useCount = ui->ckCount->isChecked();
    51 
    52     if (!useDate && !useRun && !useCount) {
    53         if (QMessageBox::question(this, "询问", "确定要生成没有任何限制的密钥吗?") != QMessageBox::Yes) {
    54             return;
    55         }
    56     }
    57 
    58     QString strDate = ui->dateEdit->date().toString("yyyy-MM-dd");
    59     QString strRun = ui->cboxMin->currentText();
    60     QString strCount = ui->cboxCount->currentText();
    61     QString key = QString("%1|%2|%3|%4|%5|%6").arg(useDate).arg(strDate).arg(useRun).arg(strRun).arg(useCount).arg(strCount);
    62 
    63     QFile file(QApplication::applicationDirPath() + "/key.db");
    64     file.open(QFile::WriteOnly | QIODevice::Text);
    65     file.write(getXorEncryptDecrypt(key, 110).toLatin1());
    66     file.close();
    67     QMessageBox::information(this, "提示", "生成密钥成功,将 key.db 文件拷贝到对应目录即可!");
    68 }
    69 
    70 void frmMain::on_btnClose_clicked()
    71 {
    72     this->close();
    73 }

    使用demo封装类代码:

      1 #include "appkey.h"
      2 #include "qmutex.h"
      3 #include "qfile.h"
      4 #include "qtimer.h"
      5 #include "qdatetime.h"
      6 #include "qapplication.h"
      7 #include "qmessagebox.h"
      8 
      9 AppKey *AppKey::self = NULL;
     10 AppKey *AppKey::Instance()
     11 {
     12     if (!self) {
     13         QMutex mutex;
     14         QMutexLocker locker(&mutex);
     15         if (!self) {
     16             self = new AppKey;
     17         }
     18     }
     19 
     20     return self;
     21 }
     22 
     23 AppKey::AppKey(QObject *parent) : QObject(parent)
     24 {
     25     keyData = "";
     26     keyUseDate = false;
     27     keyDate = "2017-01-01";
     28     keyUseRun = false;
     29     keyRun = 1;
     30     keyUseCount = false;
     31     keyCount = 10;
     32 
     33     timer = new QTimer(this);
     34     timer->setInterval(1000);
     35     connect(timer, SIGNAL(timeout()), this, SLOT(checkTime()));
     36     startTime = QDateTime::currentDateTime();
     37 }
     38 
     39 void AppKey::start()
     40 {
     41     //判断密钥文件是否存在,不存在则从资源文件复制出来,同时需要设置文件写权限
     42     QString keyName = qApp->applicationDirPath() + "/key.db";
     43     QFile keyFile(keyName);
     44     if (!keyFile.exists() || keyFile.size() == 0) {
     45         QMessageBox::critical(0, "错误", "密钥文件丢失,请联系供应商!");
     46         exit(0);
     47     }
     48 
     49     //读取密钥文件
     50     keyFile.open(QFile::ReadOnly);
     51     keyData = keyFile.readLine();
     52     keyFile.close();
     53 
     54     //将从注册码文件中的密文解密,与当前时间比较是否到期
     55     keyData = getXorEncryptDecrypt(keyData, 110);
     56     QStringList data = keyData.split("|");
     57 
     58     if (data.count() != 6) {
     59         QMessageBox::critical(0, "错误", "注册码文件已损坏,程序将自动关闭!");
     60         exit(0);
     61     }
     62 
     63     keyUseDate = (data.at(0) == "1" ? true : false);
     64     keyDate = data.at(1);
     65     keyUseRun = (data.at(2) == "1" ? true : false);
     66     keyRun = data.at(3).toInt();
     67     keyUseCount = (data.at(4) == "1" ? true : false);
     68     keyCount = data.at(5).toInt();
     69 
     70     //如果启用了时间限制
     71     if (keyUseDate) {
     72         QString nowDate = QDate::currentDate().toString("yyyy-MM-dd");
     73         if (nowDate > keyDate) {
     74             QMessageBox::critical(0, "错误", "软件已到期,请联系供应商更新注册码!");
     75             exit(0);
     76         }
     77     }
     78 
     79     //如果启用了运行时间显示
     80     if (keyUseRun) {
     81         timer->start();
     82     }
     83 }
     84 
     85 void AppKey::stop()
     86 {
     87     timer->stop();
     88 }
     89 
     90 void AppKey::checkTime()
     91 {
     92     //找出当前时间与首次启动时间比较
     93     QDateTime now = QDateTime::currentDateTime();
     94     if (startTime.secsTo(now) >= (keyRun * 60)) {
     95         QMessageBox::critical(0, "错误", "试运行时间已到,请联系供应商更新注册码!");
     96         exit(0);
     97     }
     98 }
     99 
    100 QString AppKey::getXorEncryptDecrypt(const QString &data, char key)
    101 {
    102     //采用异或加密,也可以自行更改算法
    103     QByteArray buffer = data.toLatin1();
    104     int size = buffer.size();
    105     for (int i = 0; i < size; i++) {
    106         buffer[i] = buffer.at(i) ^ key;
    107     }
    108 
    109     return QLatin1String(buffer);
    110 }
    111 
    112 bool AppKey::checkCount(int count)
    113 {
    114     if (keyUseCount) {
    115         if (count >= keyCount) {
    116             QMessageBox::critical(0, "错误", "设备数量超过限制,请联系供应商更新注册码!");
    117             return false;
    118         }
    119     }
    120 
    121     return true;
    122 }
  • 相关阅读:
    EF 学习代码
    VS10 调试 新功能
    高级编程 实验代码
    事务 代码
    ADO.NET的新功能:MARS(Multiple Active Result Set) 及 异步执行命令
    Log4Net
    获得CheckBoxList最后一个被操作的项
    在存储过程中用事务
    ASP.NET服务端添加客户端事件
    GridView遍历各行的控件和控件事件
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/10435337.html
Copyright © 2020-2023  润新知