QT防止自研软件被复制的基本操作(二)

news2024/11/20 1:45:08

参考一

自研软件为了防止被人任意复制传播,需要设置注册使用模式。基本原理:通过计算机的特异性编号,加上自己的编码,使用加密算法算出一个生成码。

一、计算机的特异性编号

硬盘的编号:最后一块硬盘的编号就行(有些计算机可能有多块硬盘);

CPU的编号;

网卡的编号;最后一块网卡的MAC地址就行;

BIOS的编号;

获取系统的安装日期;

1.1 函数示例

#include <QProcess>
 
 
QString getWMIC(const QString &cmd)
{
    //获取硬盘的序列号:wmic diskdrive get serialnumber
    //获取cpu的序列号:wmic cpu get processorid
    //获取网卡的MAC地址:wmic nicconfig get macaddress
    //查询BIOS序列号:wmic bios get serialnumber
    //查询操作系统安装时间:wmic os get installdate

    //QString cmd="wmic cpu get processorid";
    QProcess p;
    p.start(cmd);
    p.waitForFinished();
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    QStringList list = cmd.split(" ");
    result = result.remove(list.last(), Qt::CaseInsensitive);
    result = result.replace("\r", "");
    result = result.replace("\n", "");
    result = result.simplified();

    return result;
}

1.2 工程化处理

获取的这些序列号都很长,而且不同windows版本的电脑,wmic命令可能不同,所以需要进行工程化处理。

(1)各类序列号只取最后一块的;

(2)各类序列号只取后4位,但是:MAC地址取后2位,系统安装时间取前8位;

(3)对于无效查询,将其跳过,但是:如果所有的查询都无效,直接禁止使用软件。

1.3 示例代码

//函数:读取计算机硬件信息
QString KeyGen::GetPCMsg(void)
{
    //获取硬盘的序列号:wmic diskdrive get serialnumber
    QString tempStr=getWMIC("wmic diskdrive get serialnumber");
    QString pwd1 = tempStr.right(4); // 截取字符串的右边字符

    //获取cpu的序列号:wmic cpu get processorid
    tempStr=getWMIC("wmic cpu get processorid");
    QString pwd2 = tempStr.right(4); // 截取字符串的右边字符

    //获取网卡的MAC地址:wmic nicconfig get macaddress
    tempStr=getWMIC("wmic nicconfig get macaddress");
    QString pwd3 = tempStr.right(2); // 截取字符串的右边字符

    //查询BIOS序列号:wmic bios get serialnumber
    tempStr=getWMIC("wmic bios get serialnumber");
    QString pwd4 = tempStr.right(4); // 截取字符串的右边字符

    //查询操作系统安装时间:wmic os get installdate
    tempStr=getWMIC("wmic os get installdate");
    QString pwd5 = tempStr.left(8); // 截取字符串的右边字符

    return pwd1+pwd2+pwd3+pwd4+pwd5;
}

二、加密算法

使用Qt自带的MD5算法。

#include <QCryptographicHash>//加密所需

// MD5 加密
QString MD5_encryption(const QString &data)
{
    QCryptographicHash md5(QCryptographicHash::Md5);    //使用MD5加密
    md5.addData(data.toUtf8(),data.size());   // 添加数据
    QByteArray bArry = md5.result();    //获取MD5加密后的密码
    QString md5_data;
    md5_data.append(bArry.toHex());

    return md5_data;
}

三、验证是否注册

验证注册号:读取ini文件,和程序计算的结果进行对比。

3.1 main.cpp文件

#pragma execution_character_set("utf-8")

#include "mainwindow.h"
#include <QApplication>
#include "keygen.h"
#include <QMessageBox>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    if(KeyGen::verifyKey())
    {
        //验证成功
        w.show();
        return a.exec();
    }else{
        //验证不成功
        QMessageBox::warning(NULL, "警告","该软件还未注册,请联系软件开发师注册使用!");
        return 0;
    }
}

3.2 keygen.h文件

#ifndef KEYGEN_H
#define KEYGEN_H

#include <QProcess>//获取计算机信息所需
#include <QCryptographicHash>//加密所需
#include <QDebug>//打印日志所需
#include <QSettings>//读取配置文件所需
#include <QDir>//读取配置文件所需

QString getWMIC(const QString &cmd);
// MD5 加密
QString MD5_encryption(const QString &data);

class KeyGen
{

public:
    KeyGen();
    ~KeyGen();

    //函数:读取计算机硬件信息
    static QString GetPCMsg(void);

    //函数:生成注册码
    static QString generateKey(QString);

    //函数:验证注册码
    static bool verifyKey();
};

//构建函数
KeyGen::KeyGen()
{
}

//析构函数
KeyGen::~KeyGen()
{
}

//函数:读取计算机硬件信息
QString KeyGen::GetPCMsg(void)
{
    //获取硬盘的序列号:wmic diskdrive get serialnumber
    QString tempStr=getWMIC("wmic diskdrive get serialnumber");
    QString pwd1 = tempStr.right(4); // 截取字符串的右边字符

    //获取cpu的序列号:wmic cpu get processorid
    tempStr=getWMIC("wmic cpu get processorid");
    QString pwd2 = tempStr.right(4); // 截取字符串的右边字符

    //获取网卡的MAC地址:wmic nicconfig get macaddress
    tempStr=getWMIC("wmic nicconfig get macaddress");
    QString pwd3 = tempStr.right(2); // 截取字符串的右边字符

    //查询BIOS序列号:wmic bios get serialnumber
    tempStr=getWMIC("wmic bios get serialnumber");
    QString pwd4 = tempStr.right(4); // 截取字符串的右边字符

    //查询操作系统安装时间:wmic os get installdate
    tempStr=getWMIC("wmic os get installdate");
    QString pwd5 = tempStr.left(8); // 截取字符串的右边字符

    return pwd1+pwd2+pwd3+pwd4+pwd5;
}

//函数:生成注册码
QString KeyGen::generateKey(QString data)
{
    data="XXXX"+data+"XXXX";
    return MD5_encryption(data);
}

//函数:验证注册码
bool KeyGen::verifyKey()
{
    //读取注册表文件License.ini
    QString importfilepath=QDir::currentPath()+"/License.ini";
    QSettings *mConfigIni = new QSettings(importfilepath, QSettings::IniFormat);
    QString mKey_Local=mConfigIni->value("Key").toString();
    qDebug()<<mKey_Local;

    //读取系统配置并生成注册码
    QString tempStr=GetPCMsg();
    QString mKey_Now=generateKey(tempStr).left(8);
    qDebug()<<mKey_Now;

    //判断
    if(mKey_Local==mKey_Now)
    {
        return true;
    }else{
        return false;
    }
}

QString getWMIC(const QString &cmd)
{
    //获取硬盘的序列号:wmic diskdrive get serialnumber
    //获取cpu的序列号:wmic cpu get processorid
    //获取网卡的MAC地址:wmic nicconfig get macaddress
    //获取主板的序列号:wmic baseboard get serialnumber
    //查询BIOS序列号:wmic bios get serialnumber
    //查询操作系统安装时间:wmic os get installdate

    //QString cmd="wmic cpu get processorid";
    QProcess p;
    p.start(cmd);
    p.waitForFinished();
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    QStringList list = cmd.split(" ");
    result = result.remove(list.last(), Qt::CaseInsensitive);
    result = result.replace("\r", "");
    result = result.replace("\n", "");
    result = result.simplified();

    return result;
}

// MD5 加密
QString MD5_encryption(const QString &data)
{
    QCryptographicHash md5(QCryptographicHash::Md5);    //使用MD5加密
    md5.addData(data.toUtf8(),data.size());   // 添加数据
    QByteArray bArry = md5.result();    //获取MD5加密后的密码
    QString md5_data;
    md5_data.append(bArry.toHex());

    return md5_data;
}

#endif // KEYGEN_H

四、注册机

void MainWindow::on_pushButton_clicked()
{
    QString tempStr=ui->lineEdit->text();
    if(tempStr!=NULL)
    {
        ui->lineEdit_2->setText(KeyGen::generateKey(tempStr).left(11));
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1642018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux的基础入门(2)

环境变量 在Shell中&#xff0c;正确的赋值语法是没有空格的&#xff0c;即变量名数值。所以&#xff0c;正确的方式是&#xff1a; tmpshy 这样就将变量tmp赋值为"shy"了。 注意&#xff1a;并不是任何形式的变量名都是可用的&#xff0c;变量名只能是英文字母、…

开源AI名片商城小程序:打造卓越客户体验,引领留存与增长新潮流

在快速变化的商业环境中&#xff0c;如何有效地吸引并留住客户已成为每个企业面临的重要课题。为此&#xff0c;我们精心打造了一款创新的解决方案——开源AI名片商城小程序&#xff0c;它将内容培育、社交互动、产品展示与购买功能融为一体&#xff0c;为您的客户带来前所未有…

PS超美古风毛笔字体300款,PS毛笔字体笔触与笔刷素材

一、素材描述 本套PS素材&#xff0c;大小1.66G&#xff0c;2个压缩文件。 二、素材目录 &#xff08;一&#xff09;、PS毛笔字体笔触与笔刷素材.rar&#xff08;163.5M&#xff09; &#xff08;二&#xff09;、PS超美古风毛笔字体300款.rar&#xff08;1.5G&#xff09…

2.1 上海雷卯电子PLC

PLC&#xff08;可编程逻辑控制器&#xff09;像是工厂自动化系统的“大脑”&#xff0c;负责监控和控制各种生产过程。PLC 能够精确地协调各类设备的操作&#xff0c;实现生产流程的自动化和优化。通过编程&#xff0c;它可以根据不同的生产需求灵活调整控制逻辑&#xff0c;提…

【数据结构】这里有一份KMP算法优化的详细攻略,不要错过哦!!!

KMP算法优化 导读一、C语言实现next数组1.1 next数组的底层逻辑1.2 串的数据类型的选择1.3 函数三要素1.3.1 查漏补缺——数组传参1.3.2 小结 1.4 函数主体1.4.1 通过模拟实现1.4.1.1 算法思路1.4.1.2 代码实现1.4.1.3 算法测试 1.4.2 算法的缺陷1.4.3 算法优化1.4.3.1 算法思路…

蛇鹭优化算法(SBOA)-2024年4月SCI新算法-公式原理详解与性能测评 Matlab代码免费获取

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原理简介 一、初始化阶段 二、蛇鹭的捕猎…

CSS精灵图、字体图标、HTML5新增属性、界面样式和网站 favicon 图标

精灵图 为什么要使用精灵图 一个网页中往往会应用很多小的背景图像作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度,因此&#xff0c;为了有效地减少服务…

C++校招八股

c类的访问权限与继承方式 公有成员在任何地方都可以被访问&#xff0c;包括类的外部和派生类。受保护成员在类的内部和派生类中可以被访问&#xff0c;但在类的外部不可访问。 私有成员只能在类的内部访问&#xff0c;包括类的成员函数和友元函数&#xff0c;不允许在类的外部…

应用分层和企业规范

目录 一、应用分层 1、介绍 &#xff08;1&#xff09;为什么需要应用分层&#xff1f; &#xff08;2&#xff09;如何分层&#xff1f;&#xff08;三层架构&#xff09; MVC 和 三层架构的区别和联系 高内聚&#xff1a; 低耦合&#xff1a; 2、代码重构 controlle…

【软件测试】测试用例设计方法

1. 等价类划分法1.1. 等价类划分法的定义1.2. 有效等价类和无效等价类1.3. 等价类划分法实例分析 2. 边界值分析法2.1. 边界值分析法的定义2.2. 边界点2.3. 边界值法实例分析 3. 判定表法3.1. 如何用判定表法设计测试用例3.2. 判定表法实例分析 4. 正交表法4.1. 什么是正交表4.…

模拟实现memcpy,memmove,memset,memcmp

memcpy void * memcpy ( void * destination, const void * source, size_t num ); 使用注意事项&#xff1a; 从source的位置向后复制num个字节数据到destination所指向的内存位置中。 这个函数遇到如果源空间和⽬标空间出现重叠&#xff0c;就得使⽤memmove函数处理。 …

纯血鸿蒙APP实战开发——自定义路由栈管理

介绍 本案例将介绍如何使用路由跳转返回时获取到来源页的模块名以及路径名&#xff0c;在实际场景中同一页面通常会根据不同来源页展示不同的UI。 使用说明 无特殊使用说明&#xff0c;其他使用说明参考动态路由的相关说明 实现思路 路由来源页的实现 新增来源页字段 ex…

【刷题篇】动态规划-二维费用的背包问题(十二)

文章目录 1、一和零2、盈利计划3、组合总和 Ⅳ4、不同的二叉搜索树(卡特兰数) 1、一和零 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#x…

vue快速入门(五十三)使用js进行路由跳转

注释很详细&#xff0c;直接上代码 上一篇 新增内容 几种常用的路由跳转方式演示 源码 App.vue <template><div id"app"><div class"nav"><!-- router-link 自带两个高亮样式类 router-link-exact-active和router-link-active区别&a…

AI代理架构的发展:从单一到多代理系统的演进及其影响分析

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

数字逻辑之“逻辑门电路”

一、基础知识 1、正逻辑和负逻辑 &#xff08;1&#xff09;基本的逻辑规定 1——“真”0——“假” &#xff08;2&#xff09;正逻辑和负逻辑 在实际的数字系统中&#xff0c;用数字信号&#xff08;逻辑电平U1&#xff0c;U2&#xff09;表示“真&#xff08;1&#xf…

FloodFill-----洪水灌溉算法(DFS例题详解)

目录 一.图像渲染&#xff1a; 代码详解&#xff1a; 二.岛屿数量&#xff1a; 代码详解&#xff1a; 三.岛屿的最大面积&#xff1a; 代码详解&#xff1a; 四.被围绕的区域&#xff1a; 代码详解&#xff1a; 五.太平洋大西洋水流问题&#xff1a; 代码详解&#x…

[leetcode] B树是不是A树的子结构

给定两棵二叉树 tree1 和 tree2&#xff0c;判断 tree2 是否以 tree1 的某个节点为根的子树具有 相同的结构和节点值 。 注意&#xff0c;空树 不会是以 tree1 的某个节点为根的子树具有 相同的结构和节点值 。 示例 1&#xff1a; 输入&#xff1a;tree1 [1,7,5], tree2 [6,…

Docker-compose部署LTC同步节点

1、下载ltc程序包&#xff0c;litecoin下载地址 下载页 mkdir /data/docker-compose/ltc cd /data/docker-compose/ltc https://github.com/litecoin-project/litecoin/releases/download/v0.21.3/litecoin-0.21.3-x86_64-linux-gnu.tar.gz2、编写dockerfile和bitcoin.conf b…

M2M vs. IoT?

有任何关于GSMA\IOT\eSIM\RSP\业务应用场景相关的问题&#xff0c;欢迎W: xiangcunge59 一起讨论, 共同进步 (加的时候请注明: 来自CSDN-iot). 连接设备已经开辟了创造价值和解决重大世界问题的广泛机会&#xff0c;例如可持续发展。 今天&#xff0c;我们网络设备的方式可…