Qt编写密钥生成器+使用demo(开源)
在很多商业软件中,需要提供一些可以试运行的版本,这样就需要配套密钥机制来控制,纵观大部分的试用版软件,基本上采用以下几种机制来控制。
1:远程联网激活,每次启动都联网查看使用时间等,这种方法最完美,缺点是没法联网的设备就歇菜了。
2:通过获取本地的硬盘+CPU等硬件的编号,做一个运算,生成一个激活码,超过半数的软件会采用此方法,缺点是不能自由控制软件的其他参数,比如软件中添加的设备数量的控制。
3:设定一个运行到期时间+数量限制+已运行时间的密钥文件,发给用户配套软件使用,缺点是如果仅仅设置的是运行到期时间,用户可以更改电脑时间来获取更长的使用时间,在电脑不联网的情况下。
本demo采用抛砖引玉的形式,用第三种方法来实现,密钥文件采用最简单的异或加密,可以自行改成其他加密方法。
完整代码下载地址:https://download.csdn.net/download/feiyangqingyun/10975625
核心代码:
#include "frmmain.h"
#include "ui_frmmain.h"
#include "qmessagebox.h"
#include "qfile.h" frmMain::frmMain(QWidget *parent) : QWidget(parent), ui(new Ui::frmMain)
{
ui->setupUi(this);
this->initForm();
} frmMain::~frmMain()
{
delete ui;
} void frmMain::initForm()
{
QStringList min;
min << "" << "" << "" << "" << "";
for (int i = ; i <= ; i++) {
min << QString::number(i * );
} ui->cboxMin->addItems(min);
ui->cboxMin->setCurrentIndex();
ui->dateEdit->setDate(QDate::currentDate()); for (int i = ; i <= ; i = i + ) {
ui->cboxCount->addItem(QString("%1").arg(i));
}
} QString frmMain::getXorEncryptDecrypt(const QString &data, char key)
{
//采用异或加密,也可以自行更改算法
QByteArray buffer = data.toLatin1();
int size = buffer.size();
for (int i = ; i < size; i++) {
buffer[i] = buffer.at(i) ^ key;
} return QLatin1String(buffer);
} void frmMain::on_btnOk_clicked()
{
bool useDate = ui->ckDate->isChecked();
bool useRun = ui->ckRun->isChecked();
bool useCount = ui->ckCount->isChecked(); if (!useDate && !useRun && !useCount) {
if (QMessageBox::question(this, "询问", "确定要生成没有任何限制的密钥吗?") != QMessageBox::Yes) {
return;
}
} QString strDate = ui->dateEdit->date().toString("yyyy-MM-dd");
QString strRun = ui->cboxMin->currentText();
QString strCount = ui->cboxCount->currentText();
QString key = QString("%1|%2|%3|%4|%5|%6").arg(useDate).arg(strDate).arg(useRun).arg(strRun).arg(useCount).arg(strCount); QFile file(QApplication::applicationDirPath() + "/key.db");
file.open(QFile::WriteOnly | QIODevice::Text);
file.write(getXorEncryptDecrypt(key, ).toLatin1());
file.close();
QMessageBox::information(this, "提示", "生成密钥成功,将 key.db 文件拷贝到对应目录即可!");
} void frmMain::on_btnClose_clicked()
{
this->close();
}
使用demo封装类代码:
#include "appkey.h"
#include "qmutex.h"
#include "qfile.h"
#include "qtimer.h"
#include "qdatetime.h"
#include "qapplication.h"
#include "qmessagebox.h" AppKey *AppKey::self = NULL;
AppKey *AppKey::Instance()
{
if (!self) {
QMutex mutex;
QMutexLocker locker(&mutex);
if (!self) {
self = new AppKey;
}
} return self;
} AppKey::AppKey(QObject *parent) : QObject(parent)
{
keyData = "";
keyUseDate = false;
keyDate = "2017-01-01";
keyUseRun = false;
keyRun = ;
keyUseCount = false;
keyCount = ; timer = new QTimer(this);
timer->setInterval();
connect(timer, SIGNAL(timeout()), this, SLOT(checkTime()));
startTime = QDateTime::currentDateTime();
} void AppKey::start()
{
//判断密钥文件是否存在,不存在则从资源文件复制出来,同时需要设置文件写权限
QString keyName = qApp->applicationDirPath() + "/key.db";
QFile keyFile(keyName);
if (!keyFile.exists() || keyFile.size() == ) {
QMessageBox::critical(, "错误", "密钥文件丢失,请联系供应商!");
exit();
} //读取密钥文件
keyFile.open(QFile::ReadOnly);
keyData = keyFile.readLine();
keyFile.close(); //将从注册码文件中的密文解密,与当前时间比较是否到期
keyData = getXorEncryptDecrypt(keyData, );
QStringList data = keyData.split("|"); if (data.count() != ) {
QMessageBox::critical(, "错误", "注册码文件已损坏,程序将自动关闭!");
exit();
} keyUseDate = (data.at() == "" ? true : false);
keyDate = data.at();
keyUseRun = (data.at() == "" ? true : false);
keyRun = data.at().toInt();
keyUseCount = (data.at() == "" ? true : false);
keyCount = data.at().toInt(); //如果启用了时间限制
if (keyUseDate) {
QString nowDate = QDate::currentDate().toString("yyyy-MM-dd");
if (nowDate > keyDate) {
QMessageBox::critical(, "错误", "软件已到期,请联系供应商更新注册码!");
exit();
}
} //如果启用了运行时间显示
if (keyUseRun) {
timer->start();
}
} void AppKey::stop()
{
timer->stop();
} void AppKey::checkTime()
{
//找出当前时间与首次启动时间比较
QDateTime now = QDateTime::currentDateTime();
if (startTime.secsTo(now) >= (keyRun * )) {
QMessageBox::critical(, "错误", "试运行时间已到,请联系供应商更新注册码!");
exit();
}
} QString AppKey::getXorEncryptDecrypt(const QString &data, char key)
{
//采用异或加密,也可以自行更改算法
QByteArray buffer = data.toLatin1();
int size = buffer.size();
for (int i = ; i < size; i++) {
buffer[i] = buffer.at(i) ^ key;
} return QLatin1String(buffer);
} bool AppKey::checkCount(int count)
{
if (keyUseCount) {
if (count >= keyCount) {
QMessageBox::critical(, "错误", "设备数量超过限制,请联系供应商更新注册码!");
return false;
}
} return true;
}
Qt编写密钥生成器+使用demo(开源)的更多相关文章
- 年底奉献-QT编写视频监管平台(开源)
忙忙碌碌又是一年,算算自己毕业四年半,一直在现在这家公司做研发外加总经理助理,研发起初用的VB.NET,而后全面转为C#,最后又全面转为QT,都是由于项目需要,算下来自己搞QT编程也已经四年了,201 ...
- Qt编写软件运行时间记录(开源)
在早期开发的软件中,尤其是初学者入门者写的软件,软件运行久了,难免遇到意外崩溃的时候,可是大部分的运行设备可能在现场客户那,需要记住每一次从软件启动后到软件意外关闭前的运行时间,需要记录的信息包括:编 ...
- Qt编写网络中转服务器(开源)
需求1:手机端或者其他端可以对设备进行回控,并查看设备各种运行状态,接收报警推送等.2:同时支持在局域网.广域网.互联网访问,尤其是互联网访问.3:权限控制,给定账号控制授权的设备,并自动拉取设备信息 ...
- Qt编写的开源帖子集合(懒人专用)
回顾自己学习Qt以来九年了,在这九年多时间里面,从本论坛学习不到不少的东西,今天特意整了一下自己开源过的资源的帖子,整理一起方便大家直接跳转下载,不统计不知道,一统计吓一跳,不知不觉开源了这么多代码, ...
- Qt编写自定义控件插件开放动态库dll使用(永久免费)
这套控件陆陆续续完善了四年多,目前共133个控件,除了十几个控件参考网友开源的代码写的,其余全部原创,在发布之初就有打算将动态库开放出来永久免费使用,在控件比较完善的今天抽了半天时间编译了多个qt版本 ...
- Qt编写自定义控件5-柱状温度计
前言 柱状温度计控件,可能是很多人练手控件之一,基本上都是垂直方向展示,底部一个水银柱,中间刻度尺,刻度尺可以在左侧右侧或者两侧都有,自适应分辨率改动,有时候为了美观效果,可能还会整个定时器来实现动画 ...
- Qt编写项目作品大全(自定义控件+输入法+大屏电子看板+视频监控+楼宇对讲+气体安全等)
一.自定义控件大全 (一).控件介绍 超过160个精美控件,涵盖了各种仪表盘.进度条.进度球.指南针.曲线图.标尺.温度计.导航条.导航栏,flatui.高亮按钮.滑动选择器.农历等.远超qwt集成的 ...
- Qt编写气体安全管理系统10-数据导出
一.前言 数据导出一般指导出到excel表格,可能有部分用户还需要导出到pdf,因为pdf基本上不可编辑,防止用户重新编辑导出的数据,excel可能绝大部分用过电脑的人都知道,广为流行,主要就是微软的 ...
- Qt编写自定义控件71-圆弧进度条
一.前言 现在web形式的图表框架非常流行,国产代表就是echart,本人用过几次,三个字屌爆了来形容,非常强大,而且易用性也非常棒,还是开源免费的,使用起来不要太爽,内置的各种图表和仪表盘等非常丰富 ...
随机推荐
- (原创)OpenStack服务如何使用Keystone (二)---部署和配置Keystone中间件
(一)Keystone端的操作 (二)如何在OpenStack服务上部署Keystone中间件 (三)详细配置keystonemiddleware 部署OpenStack时一般先安装Keystone服 ...
- Office在线预览及PDF在线预览的实现方式
原文链接:http://www.officeweb365.com/officetoview.html 一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office ...
- ckeditor4.2.1常用配置
常用的配置信息都放在根目录的config.js文件中,一些常用的配置项如下: 1.界面语言 //语言 config.language = 'zh-cn'; 2.字体添加中文 //字体 config.f ...
- UIImage 读取图片内存优化
在图片处理时,我们总会遇到一些内存优化的问题. 这里介绍的是其中一种内存优化处理方式. 场景: App 运行很卡,然后我用 Instruments 中的相关工具查看对象的内存占用情况,发现当图片加载 ...
- LinuxMint下的Orionode源码安装
1. Orionode介绍 Eclipse-orion是Eclipse项目下面的一个子项目,orion是一个在在线版的代码编辑环境.其介绍参考http://wiki.eclipse.org/Orion ...
- UNIX环境编程学习笔记(28)——多线程编程(三):线程的取消
lienhua342014-11-24 1 取消线程 pthread 提供了pthread_cancel 函数用于请求取消同一进程中的其他线程. #include <pthread.h> ...
- 【转】maven同时使用maven-surefire-report-plugin和maven-surefire-plugin默认将执行两次test
https://issues.apache.org/jira/browse/SUREFIRE-753 Here the pom.xml snippet how i configured the rep ...
- redhat enterprise edition 6.8:禁止ipv6后,nfs文件系统无法挂载:no such device
如题:谨记. 附注:如何禁止ipv6? 方法一 第一种方法是通过 /etc/sysctl.conf 文件对 /proc 进行永久修改. 换句话说,就是用文本编辑器打开 /etc/sysctl.conf ...
- eclipse中开发js会卡,去掉.project中的validate即可
注释掉 <buildCommand> <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> & ...
- javascript的特殊条件语句
摘要: 由于javascript语言的特殊性导致它有很多特殊的条件判断,下面我列出了一些特殊的条件判断语句和他们对应的结果. if(condition) { console.log(true); ...