方案简介
先使用glib对固件进行压缩;然后使用MD5对固件进行添加头部校验值;最后使用AES对固件进行加密。
MD5
MD5,全称Message Digest Algorithm 5,即信息摘要算法5,是一种被广泛使用的密码散列函数。它可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在RFC 1321标准中被加以规范。
MD5的功能(作为校验值)可以看这一篇:MD5数据加密方法
AES加密
AES加密,全称Advanced Encryption Standard,是一种对称的分组加密技术。它使用128位分组加密数据,每次加密16个字节,提供比WEP/TKIPS的RC4算法更高的加密强度。AES的加密码表和解密码表是分开的,并且支持子密钥加密,这种做法优于以前用一个特殊的密钥解密的做法。此外,AES算法支持任意分组大小,初始时间快,特别是它具有的并行性可以有效地利用处理器资源。
AES算法具有以下优点:
- 应用范围广:可以用来加密数据、电子邮件和网络传输,以保护隐私和网络数据的安全性。
- 等待时间短:相对于其他加密算法,AES加密速度较快。
- 相对容易隐藏:AES加密算法相对容易隐藏,不容易被破解。
- 吞吐量高:能够提供高吞吐量,适用于大规模的数据加密。
此外,AES加密的安全性非常高,它使用128位、192位或256位的密钥,可以抵抗各种类型的攻击,包括密码穷举攻击、密码分析攻击和密码拓展攻击。因此,AES加密算法被认为是目前世界上最安全、最先进的加密算法之一。
AES的具体功能及其实现原理可以参考这一篇:AES加密算法原理的详细介绍与实现
gzip
gzip是一个使用广泛的压缩程序,最早由Jean-loup Gailly和Mark Adler创建,用于UNⅨ系统的文件压缩。它可以用来压缩文件,压缩后的文件名通常会添加“.gz”的扩展名。gzip不仅可以用来压缩大的、较少使用的文件以节省磁盘空间,还可以和tar命令一起构成linux操作系统中比较流行的压缩文件格式。
zlib是一套通用的解压缩开源库,提供了内存(in-memory)压缩和解压函数,能检测解压出来的数据完整性,支持读写gzip(.gz)格式的文件。该库使用DEFLATE算法压缩数据部分,这是一种Huffman编码的加强。
本次研究的是在QT上面使用glib库。
glib库的简介和主要函数的功能可以看这一篇:第三方库介绍——zlib库
在QT中使用MD5、AES、glib
QT环境
必须使用MinGW来构建项目
MD5
使用QT内嵌的QCryptographicHash库,这个库提供了以下加密类型,这里只使用了MD5。
类型 |
值 |
描述 |
QCryptographicHash::Md4 |
0 |
Generate an MD4 hash sum |
QCryptographicHash::Md5 |
1 |
Generate an MD5 hash sum |
QCryptographicHash::Sha1 |
2 |
Generate an SHA-1 hash sum |
QCryptographicHash::Sha224 |
3 |
Generate an SHA-224 hash sum (SHA-2). Introduced in Qt 5.0 |
QCryptographicHash::Sha256 |
4 |
Generate an SHA-256 hash sum (SHA-2). Introduced in Qt 5.0 |
QCryptographicHash::Sha384 |
5 |
Generate an SHA-384 hash sum (SHA-2). Introduced in Qt 5.0 |
QCryptographicHash::Sha512 |
6 |
Generate an SHA-512 hash sum (SHA-2). Introduced in Qt 5.0 |
QCryptographicHash::Sha3_224 |
RealSha3_224 |
Generate an SHA3-224 hash sum. Introduced in Qt 5.1 |
QCryptographicHash::Sha3_256 |
RealSha3_256 |
Generate an SHA3-256 hash sum. Introduced in Qt 5.1 |
QCryptographicHash::Sha3_384 |
RealSha3_384 |
Generate an SHA3-384 hash sum. Introduced in Qt 5.1 |
QCryptographicHash::Sha3_512 |
RealSha3_512 |
Generate an SHA3-512 hash sum. Introduced in Qt 5.1 |
QCryptographicHash::Keccak_224 |
7 |
Generate a Keccak-224 hash sum. Introduced in Qt 5.9.2 |
QCryptographicHash::Keccak_256 |
8 |
Generate a Keccak-256 hash sum. Introduced in Qt 5.9.2 |
QCryptographicHash::Keccak_384 |
9 |
Generate a Keccak-384 hash sum. Introduced in Qt 5.9.2 |
QCryptographicHash::Keccak_512 |
10 |
Generate a Keccak-512 hash sum. Introduced in Qt 5.9.2 |
QCryptographicHash::Blake2b_160 |
15 |
Generate a BLAKE2b-160 hash sum. Introduced in Qt 6.0 |
QCryptographicHash::Blake2b_256 |
16 |
Generate a BLAKE2b-256 hash sum. Introduced in Qt 6.0 |
QCryptographicHash::Blake2b_384 |
17 |
Generate a BLAKE2b-384 hash sum. Introduced in Qt 6.0 |
QCryptographicHash::Blake2b_512 |
18 |
Generate a BLAKE2b-512 hash sum. Introduced in Qt 6.0 |
QCryptographicHash::Blake2s_128 |
19 |
Generate a BLAKE2s-128 hash sum. Introduced in Qt 6.0 |
QCryptographicHash::Blake2s_160 |
20 |
Generate a BLAKE2s-160 hash sum. Introduced in Qt 6.0 |
QCryptographicHash::Blake2s_224 |
21 |
Generate a BLAKE2s-224 hash sum. Introduced in Qt 6.0 |
QCryptographicHash::Blake2s_256 |
22 |
Generate a BLAKE2s-256 hash sum. Introduced in Qt 6.0 |
MD5的使用没有什么难点,这是QT做完的内容,直接使用就行。
///这个库需要在目标文件中包含
#include <QCryptographicHash>
--------------------------------------
QByteArray array; ///< 假定的源数据
--------------------------------------
QT中使用MD5加密:
QCryptographicHash hash(QCryptographicHash::Md5); ///< Md5加密
hash.addData(array.toHex()); ///< 添加数据
QByteArray retArray = hash.result(); ///< 加密后的数据
QT中使用MD5校验:
QCryptographicHash hash(QCryptographicHash::Md5); ///< Md5加密
hash.addData(array.toHex()); ///< 添加数据
QByteArray retArray = hash.result(); ///< 加密后的数据
其实就是将文件再次加密,最后将文件加密得到的MD5校验值与第一次加密的MD5值进行比较,如果相同则表示文件未被修改,主要用于验证文件的完整性。
AES
QT部署AES
QT中没有可以直接使用的AES加密库,需要外部开源的AES加密库,这里使用https://github.com/bricke/Qt-AES开源库,这个库需要复制两个文件到工程中,这个库具体的功能和使用开源查看Qt-AES加密库文章。
AES使用
///这个库需要在目标文件中包含
#include "qaesencryption.h"
使用AES对数据进行加密:
static QByteArray encodedText(QByteArray data)
{
if(data.isEmpty())
{
return 0;
}
/// keyLen_main、mode_main、padding_main、iv:全局变量
QAESEncryption encryption((QAESEncryption::Aes)keyLen_main,
(QAESEncryption::Mode)mode_main,
(QAESEncryption::Padding)padding_main);
//QString str = QString::fromUtf8(data);
//对源数据加密
QByteArray encoded = encryption.encode(data, keys_main, iv);
return encoded;
}
使用AES对数据进行解密
static QByteArray decodedText(QByteArray data)
{
if(data.isEmpty())
{
return 0;
}
/// keyLen_main、mode_main、padding_main、iv:全局变量
QAESEncryption encryption((QAESEncryption::Aes)keyLen_main,
(QAESEncryption::Mode)mode_main,
(QAESEncryption::Padding)padding_main);
//解密
QByteArray decodedText = encryption.decode(data, keys_main, iv);
return decodedText;
}
glib
glib是放置在了QT库中,
只需要在工程.pro文件中加入
LIBS += -lz
------------------------------------
并且在目标文件中加入头文件
#include <zlib.h>
在使用glib库时必须使用MinGW来构建工程,MSVC2019构建带有glib库的工程会报错。 使用glib时需要对其进行封装以确保直接使用 QByteArray 类型进行压缩(glib中的compress函数传入的参数是Bytef),具体的封装开源参考zlib库实现数据流的压缩与解压缩。
/**
* @brief 压缩数据
* @param postBody 数据(QByteArray类型)
* @return 压缩完成的数据
*/
static QByteArray GzipCompress(QByteArray postBody)
{
QByteArray outBuf;
int *errorCode = NULL;
/// ZlibCompress用于预测压缩后的数据大小
long outlength = ZlibCompress(outBuf,postBody,errorCode);
if(outlength != (-1))
{
return outBuf;
}
outBuf = postBody;
return outBuf;
}
/**
* @brief 解压缩
* @param src 目标数据(QByteArray)
* @return 解压缩的数据
*/
static QByteArray GZipUnCompress(QByteArray src)
{
QByteArray outBuffer;
int *errorCode = NULL;
long outlength = ZlibUncompress(outBuffer,src,errorCode);
if(outlength != (-1))
{
return outBuffer;
}
outBuffer = src;
return outBuffer;
}
ui设计
主界面
AES配置界面
主界面中点击工具栏 设置AES 即可跳转至AES配置界面。
验证(结果)
打开固件加密软件,点击主界面的浏览按钮打开选择固件窗口,在选择固件窗口中选中要加密的bin文件(实际可以加密任何文件,只需要将对应文件重命名为.bin后缀即可)。
选中下面的三个选项框(使用gzip、使用MD5、使用AES),并且点击工具栏的 设置AES 打开AES配置界面,在AES 密钥在线生成器中生成一个256bit的密钥(BuB6PiubJnKu4hDTnr4k0tIiI4v2HrgE),其余保持默认点击 AES配置 界面的 ok 按钮。
点击开始加密等待主界面下方显示输出结果即可,显示 加密完成 并且显示了输出文件位置和文件名称表示加密完成,并且在输出文件位置中可以找到一个 result.ldx 的文件,该文件比源文件缩小了1倍左右,并且已经被加密,使用Beyond Compare 4软件可以发现 rtthread.bin 与 result.ldx 文件内容不一致,表示压缩及加密完成。
接着验证解密功能,保持设置即不修改AES配置,只修改文件即可,点击浏览,选中刚刚生成的result.ldx文件点击解密,等待状态框输出解密完成和输出文件位置,在输出文件目录下可以找到一个restore.bin文件,将rtthread.bin与restore.bin文件使用Beyond Compare 4软件打开,可以看到rtthread.bin与restore.bin文件一致即表示加密解密功能完成无误。
至此结束。
备注
文章为原创,个人博客。
源码
https://gitee.com/ldxlxx/QT_bootloader/tree/master/