QT上位机开发(加密和解密)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        加密和解密是我们在软件开发中经常遇到的一种情形。最早的时候,加密是用在军事上面。现在由于各个行业、各个公司之间的竞争也非常激烈,因此有必要利用加密方法来保证自己软件的数据不被破解。此外,加解密还有一个重要的应用场合,那就是软件的有效期,这部分很多时候也是加密特定的文件,最后被软件加载和解密使用的。

        不过可惜的是,目前为止在qt上面没有看到比较好的加解密库。还在window平台提供类类似的加解密api,也可以用来进行数据处理。

1、创建基本的qt widget环境

        首先我们可以创建一个基本的widget环境,主要是用来生成编译环境比较方便。

2、代码说明

        本次文中引用的代码主要来自这篇文章,大家可以参考一下原来作者的思路和想法。

https://blog.csdn.net/weixin_41077112/article/details/132753791

3、算法流程

        如果用windows api进行数据数据的加解密,其实流程不算复杂。一般来说,先利用CryptAcquireContext创建一个HCRYPTPROV,再创建一个HCRYPTKEY。后期利用HCRYPTKEY进行数据的加密和解密动作。所有操作都做完,如果没有其他的工作,还需要把

前面资源释放一下。

int main()
{
	HCRYPTPROV hCryptProv = NULL;
	HCRYPTKEY hKey = NULL;
	BYTE* pDataToEncrypt = (BYTE*)"Hello, World!";
	BYTE* pEncryptedData = NULL;
	DWORD encryptedDataLen = 0;
	BYTE* pDecryptedData = NULL;
	DWORD decryptedDataLen = 0;

	//Get the handler of Crypt Service Provider(CSP)
	if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, 0)) {
		printf("CryptAcquireContext failed: %d\n", GetLastError());
		return 1;
	}

	//Generate AES key
	if (!CryptGenKey(hCryptProv, CALG_AES_256, 0, &hKey)) {
		printf("CryptGenKey failed: %d\n", GetLastError());
		CryptReleaseContext(hCryptProv, 0);
		return 1;
	}

	//Encrypt data
	if (EncryptData(hKey, pDataToEncrypt, strlen((char*)pDataToEncrypt) + 1, &pEncryptedData, &encryptedDataLen)) {
		printf("Data encrypted successfully.\n");
		printf("Encrypted data: ");
		for (DWORD i = 0; i < encryptedDataLen; i++)
		{
			printf("%02X", pEncryptedData[i]);
		}
		printf("\n");

		//Decrypt data
		if (DecryptData(hKey, pEncryptedData, encryptedDataLen, &pDecryptedData, &decryptedDataLen)) {
			printf("Decrypted data: %s\n", pDecryptedData);
			free(pDecryptedData);
		}

		free(pEncryptedData);
	}

	//Clean resources
	CryptDestroyKey(hKey);
	CryptReleaseContext(hCryptProv, 0);

	return 0;
}

4、数据加密

        数据加密的过程主要采用了CryptEncrypt函数,大家可以参考下,

#include <windows.h>
#include <wincrypt.h>
#include <iostream>

// encrypt data here
BOOL EncryptData(HCRYPTKEY hKey, BYTE* pData, DWORD dataLen, BYTE** ppEncryptedData, DWORD* pEncryptedDataLen)
{
	*pEncryptedDataLen = dataLen + 16;
	*ppEncryptedData = (BYTE*)malloc(*pEncryptedDataLen);
	ZeroMemory(*ppEncryptedData, *pEncryptedDataLen);
	if (*ppEncryptedData == NULL)
	{
		printf("Memory allocation failed.\n");
		return FALSE;
	}

	memcpy(*ppEncryptedData, pData, dataLen);
	if (!CryptEncrypt(hKey, NULL, TRUE, 0, *ppEncryptedData, &dataLen, *pEncryptedDataLen))
	{
		printf("CryptEncrypt failed: %d\n", GetLastError());
		free(*ppEncryptedData);

		if (GetLastError() == ERROR_MORE_DATA)
		{
			*pEncryptedDataLen = dataLen + 1;
			*ppEncryptedData = (BYTE*)malloc(*pEncryptedDataLen);
			ZeroMemory(*ppEncryptedData, *pEncryptedDataLen);
			if (*ppEncryptedData == NULL)
			{
				printf("Memory allocation failed again.\n");
				return FALSE;
			}
			memcpy(*ppEncryptedData, pData, dataLen);
			if (!CryptEncrypt(hKey, NULL, TRUE, 0, *ppEncryptedData, &dataLen, *pEncryptedDataLen))
			{
				printf("CryptEncrypt failed again: %d\n", GetLastError());
				free(*ppEncryptedData);
				return FALSE;
			}
		}
		else
		{
			return FALSE;
		}
	}

	*pEncryptedDataLen = dataLen;
	return TRUE;
}

5、数据解密

        数据解密,则引用了另外一个api,即CryptDecrypt。

BOOL DecryptData(HCRYPTKEY hKey, BYTE* pEncryptedData, DWORD encryptedDataLen, BYTE** ppDecryptedData, DWORD* pDecryptedDataLen)
{
	*ppDecryptedData = (BYTE*)malloc(encryptedDataLen);
	ZeroMemory(*ppDecryptedData, encryptedDataLen);
	if (*ppDecryptedData == NULL)
	{
		printf("Memory allocation failed.\n");
		return FALSE;
	}

	memcpy(*ppDecryptedData, pEncryptedData, encryptedDataLen);
	*pDecryptedDataLen = encryptedDataLen;
	if (!CryptDecrypt(hKey, NULL, TRUE, 0, *ppDecryptedData, pDecryptedDataLen))
	{
		printf("CryptDecrypt failed: %d\n", GetLastError());
		free(*ppDecryptedData);
		return FALSE;
	}

	return TRUE;
}

6、测试和验证

        上面三部分代码,大家如果放到一个文件里面,其实就可以开始编译验证了。单步调试即可。主要的验证方法,就是确认加密前和加密后的数据是否一致即可。当然,这个demo还有一个很大的不足,就是目前为止,生成的key没有导出来,每次都是重新创建。

        实际应用中,对于生成的key,一般需要用CryptExportKey和CryptImportKey进行导出和导入处理一下。有兴趣的同学可以继续把这部分代码补充上,让整体的功能更加完善一点。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kafka的安装、管理和配置

Kafka的安装、管理和配置 1.Kafka安装 官网: https://kafka.apache.org/downloads 下载安装包,我这里下载的是https://archive.apache.org/dist/kafka/3.3.1/kafka_2.13-3.3.1.tgz Kafka是Java生态圈下的一员&#xff0c;用Scala编写&#xff0c;运行在Java虚拟机上&#xf…

不会 python 语言没关系,GPT 会呀

在日常办公或者是编程过程中&#xff0c;经常要处理一些琐碎的任务。就拿编程来说&#xff0c;假如你现在收到一个任务&#xff0c;要提取源代码中所有的字符串&#xff0c;进行国际化。 一般来说&#xff0c;很多软件开发工具提供了国际化方案&#xff0c;比如 QT&#xff0c;…

x-cmd pkg | fx - Warp 支持的 JSON 查看和处理工具

目录 简介首次用户功能特点类似工具与竞品进一步探索 简介 fx 是一款由专为 JSON 定制的双用途命令行工具&#xff0c;提供基于终端的 JSON 查看器和 JSON 处理实用程序。虽然 JSON 查看器是用 Go 编写的&#xff0c;并且无需外部依赖即可运行&#xff0c;但 JSON 处理工具是用…

openGauss学习笔记-196 openGauss 数据库运维-常见故障定位案例-强制结束指定的问题会话

文章目录 openGauss学习笔记-196 openGauss 数据库运维-常见故障定位案例-强制结束指定的问题会话196.1 强制结束指定的问题会话196.1.1 问题现象196.1.2 处理办法 openGauss学习笔记-196 openGauss 数据库运维-常见故障定位案例-强制结束指定的问题会话 196.1 强制结束指定的…

实验室服务器升级

cuda、python、pytorch 版本兼容查看顺序及网站 任务&#xff1a; 在一个有GPU的电脑上安装pytorch时选择合适版本。 简述&#xff1a; 安装 pytorch 时&#xff0c;若要使用 GPU&#xff0c;需要考虑与 CUDA&#xff0c;python 的版本兼容情况。推荐考虑顺序&#xff1a;CUD…

NUS CS1101S:SICP JavaScript 描述:四、元语言抽象

原文&#xff1a;4 Metalinguistic Abstraction 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 …魔法就在于文字——Abracadabra&#xff0c;开门&#xff0c;以及其他——但一个故事中的魔法词在另一个故事中并不神奇。真正的魔法是理解哪些词起作用&#xff0c;何时…

Jenkins创建maven项目

Jenkins创建maven项目 环境准备 如果在项目没有看到maven&#xff0c;需要下载插件 本机需要有maven&#xff0c;并且maven配置过国内镜像&#xff0c;否则很大概率插件下不下来&#xff0c;如果有docker之前没有配置过需要进入docker手动配置。 需要在全局中配置maven的set…

Kubernetes (十一) 存储——Secret配置管理

一. 简介 从文件创建 echo -n admin > ./username.txt echo -n westos > ./password.txt kubectl create secret generic db-user…

力扣(leetcode)第606题根据二叉树创建字符串(Python)

606.根据二叉树创建字符串 题目链接&#xff1a;606.根据二叉树创建字符串 给你二叉树的根节点 root &#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对 “()” 表示&…

【大数据】Flink 详解(九):SQL 篇 Ⅱ

本系列包含&#xff1a; 【大数据】Flink 详解&#xff08;一&#xff09;&#xff1a;基础篇【大数据】Flink 详解&#xff08;二&#xff09;&#xff1a;核心篇 Ⅰ【大数据】Flink 详解&#xff08;三&#xff09;&#xff1a;核心篇 Ⅱ【大数据】Flink 详解&#xff08;四…

第十六章 i18n国际化

第十六章 i18n国际化 1.什么是i18n国际化2.i18n国际化三要素介绍3.i18n国际化基础示例4.通过请求头实现国际化5.通过语言类型选择实现国际化6.通过JSTL标签库fmt实现国际化 1.什么是i18n国际化 2.i18n国际化三要素介绍 3.i18n国际化基础示例 如果我要准备一个国际化的信息&…

测试工程师能否作为一份「终身职业」?30岁+怎么办?

【讨论】测试工程师可否作为一份终生的职业&#xff1f; 这是我在论坛看到的一个讨论&#xff0c;你的答案是什么呢&#xff1f; 我希望大家能认真思考后给出一个属于自己的答案&#xff0c;无论你是新手入门&#xff0c;还是资深专家。回答这个问题请不要凭一腔热血&#xff…

网络服务之DHCP

目录 一、DHCP是什么&#xff1f; 1、DHCP就是动态主机配置协议 2、DHCP的作用&#xff1a; 3、DHCP是应用层协议 二、DHCP的优点 三、DHCP的分配过程 1、自动分配&#xff1a;分配到一个ip地址后永久使用 2、手动配置&#xff1a;由DHCP服务器管理员专门指定ip地址&am…

ArchVizPRO Interior Vol.8 URP

ArchVizPRO Interior Vol.8 URP是一个在URP中制作的建筑可视化项目。这是一个完全可导航的现代公寓,包括一个带开放式厨房的客厅、休息区、两间卧室和两间浴室。从头开始构建每一个细节,这个室内有130多件家具和道具、自定义着色器和4K纹理。所有家具和道具都非常详细,可以在…

使用CentOS搭建高性能静态HTTP服务器

在互联网应用中&#xff0c;静态内容是广泛存在的&#xff0c;例如HTML页面、图片、视频等。为了提供高效、稳定和安全的静态内容服务&#xff0c;我们可以使用CentOS来搭建高性能的静态HTTP服务器。 1. 选择合适的软件 Nginx和Apache是两个流行的HTTP服务器软件。Nginx以其高…

如何定义核心场景用例?

首先我们解决两个问题&#xff1a; 1.什么是场景测试&#xff1f;2.什么是核心场景&#xff1f; 1、什么是场景测试&#xff1f; &#x1f3af; 1.1&#xff1a;什么是场景 事件触发时的情景形成了场景。场景必不可少的几个要素&#xff1a;环境、人、时间、行为。简而言之&…

javascript_forEach中使用异步函数执行顺序问题,错误原因+解决思路

javascript_forEach中使用异步函数执行顺序问题&#xff0c;错误原因解决思路 start 最近在写异步逻辑的时候&#xff0c;经常会使用 async/await。有些时候需要执行异步逻辑的函数比较多&#xff0c;就习惯用 forEachasync/await 去处理函数了。在测试的过程中会发现&#x…

Opencv实验合集——实验九:姿势估计

在上一章节(相机校准)&#xff0c;你已经找到了相机矩阵&#xff0c;畸变系数等等参数。给出一个图案图像&#xff0c;我们便可以利用上面的信息用于计算其姿势&#xff0c;或者物体在空间中位于何处&#xff0c;比如如何旋转&#xff0c;如何移动等等问题。对于一个平面物体&a…

【数据结构】二叉树问题总结

目录 1.二叉树前序遍历&#xff0c;中序遍历和后序的实现 2.层序遍历 3.求二叉树中的节点个数 4.求二叉树中的叶子节点个数 5.求二叉树的高度 6.求二叉树第k层节点个数 7.二叉树查找值为x的节点 8.单值二叉树 9.二叉树最大深度 10.翻转二叉树 11. 检查两颗树是否相同…

Redis介绍

一、 Redis介绍 1. NoSQL的引言 NoSQL(Not Only SQL )&#xff0c;意即不仅仅是SQL, 泛指非关系型的数据库。Nosql这个技术门类,早期就有人提出,发展至2009年趋势越发高涨。 2. 为什么是NoSQL 随着互联网网站的兴起&#xff0c;传统的关系数据库在应付动态网站&#xff0c;…