【Qt】QCryptographicHash 设置密钥(Key)
QCryptographicHash
本身不能设置密钥(Key)。
它是一个用于计算非密钥型加密哈希的函数,其设计目的和 HMAC 或加密算法完全不同。
下面我详细解释为什么,以及如何正确地实现你可能想要的功能。
1. QCryptographicHash
的核心功能:无密钥哈希
QCryptographicHash
的核心功能是接受输入数据(如一个字符串或文件内容),然后输出一个固定长度的、唯一的哈希值(摘要)。相同的输入永远产生相同的输出。
- 输入:数据 (Data)
- 输出:哈希值 (Hash/Digest)
- 特点:不需要密钥。任何人都可以用这个类计算出相同数据的相同哈希值。
它的典型用途是:
- 验证文件下载是否完整(计算下载文件的 SHA256 并与官方提供的哈希值对比)。
- 生成数据的唯一标识符。
- 用于数字签名流程的一部分(签名是使用私钥对数据的哈希值进行加密,而不是直接加密数据本身)。
2. 如果你需要“带密钥的哈希”,你需要的是 HMAC
当你想要验证一段数据不仅完整,而且来自可信的来源(即拥有密钥的人)时,就需要用到密钥。这就是 HMAC 的用途。
- 输入:数据 (Data) + 密钥 (Secret Key)
- 输出:消息认证码 (MAC)
- 特点:必须要有密钥。只有拥有相同密钥的人才能计算出相同的 MAC 值。
它的典型用途是:
- API 请求认证:客户端使用密钥对请求参数生成一个签名(HMAC),服务器用同样的密钥验证签名,从而确认请求是合法的、未被篡改。
- JSON Web Tokens (JWT):JWT 的签名部分就是使用 HMAC 生成的。
- 任何需要同时保证完整性和真实性的场景。
3. 如何在 Qt 中实现 HMAC(带密钥的哈希)
Qt 提供了专门的类 QMessageAuthenticationCode
来计算 HMAC。你应该使用这个类,而不是 QCryptographicHash
。
示例:使用 QMessageAuthenticationCode
计算 HMAC-SHA256
#include <QMessageAuthenticationCode>
#include <QDebug>int main() {// 你的原始消息QByteArray message = "Important data: user=123, action=delete";// 你的密钥(必须保密!)QByteArray secretKey = "MySuperSecretKey123!";// 选择哈希算法(这里以 SHA256 为例)QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;// 计算 HMACQMessageAuthenticationCode hmacCalculator(hashAlgorithm);hmacCalculator.setKey(secretKey); // 设置密钥hmacCalculator.addData(message); // 添加数据QByteArray result = hmacCalculator.result(); // 计算最终结果QByteArray hmacHex = result.toHex(); // 转换为十六进制字符串,便于传输和存储qDebug() << "Message:" << message;qDebug() << "HMAC (hex):" << hmacHex;// 输出类似: "HMAC (hex): a1b2c3d4e5f6..."// --- 验证端 --- //// 当接收方收到消息和这个HMAC后,可以用同样的密钥和算法重新计算一次HMAC。// 如果计算出的HMAC与发送来的完全一致,则证明消息是完整且真实的。return 0;
}
4. 一个常见的混淆:加密 (Encryption) vs. 哈希 (Hashing)
你可能还会想问:“那我可以用它来加密密码吗?” 答案是:不能,而且这是两个截然不同的概念。
-
哈希 (Hashing with
QCryptographicHash
)- 单向的:无法从哈希值还原出原始数据。
- 目的:验证完整性、生成指纹。
- 例如:SHA256, MD5。
-
加密 (Encryption)
- 双向的:使用密钥将明文变为密文,也可以使用密钥(或配对密钥)将密文还原为明文。
- 目的:保密性,防止信息被未授权者读取。
- 例如:AES, RSA。
对于密码存储,正确的做法是使用密码学哈希函数,但必须是专门为密码设计的(如 bcrypt, PBKDF2),而不是 QCryptographicHash
这种通用哈希。Qt 中可以使用 QPasswordDigestor
(详见我上一个回答)。
总结
| 你的需求 | 应该使用的 Qt 类 | 说明 |
| :— | :— | :— |
| 计算数据的哈希值(校验文件完整性) | QCryptographicHash
| 无密钥,通用哈希计算。 |
| 计算带密钥的哈希(API签名,消息认证) | QMessageAuthenticationCode
(HMAC) | 需要密钥,用于验证真实性和完整性。 |
| 加密/解密数据(保证数据机密性) | 需要使用加密库(如 Qt 的 QSslSocket
相关功能或第三方库) | 需要密钥,双向过程。 |
| 安全地存储用户密码 | QPasswordDigestor
(Qt >= 5.12) | 使用慢哈希算法(如 PBKDF2),内含盐值和迭代次数。 |
结论:
QCryptographicHash
没有设置密钥的功能。 如果你需要用到密钥,你的真实需求很可能是:
- 消息认证 -> 使用
QMessageAuthenticationCode
(HMAC)。 - 加密数据 -> 使用加密库(如 AES)。
- 哈希密码 -> 使用
QPasswordDigestor
。