下载地址https://github.com/guanzhi/GmSSL/tree/v3.1.1
在qt使用上述版本进行sm4加解密时,发现调用sm4_cbc_encrypt和sm4_cbc_decrypt会出现随机崩溃问题。后经测试发现,加解密结果数组需要分配的更大一些才能解决问题。
#include "gmsslManager.h"
#include <QByteArray>
#include <QCryptographicHash>
#include <QDebug>
//extern "C"{
#include "gmssl/sm4.h"
//}
GmsslManager::GmsslManager()
{
getKey();
//上传地址
QString m_strCloudUrl = "";
//ak
QString m_strAK = "";
//sk
QString m_strSK = "";
//桶
QString m_strBucket = "";
//加密obs云数据
// QByteArray tempCloudUrl = sm4Encrypt(m_strCloudUrl.toUtf8());
// // qDebug() << "tempCloudUrl:" << tempCloudUrl.toHex();
// QByteArray tempAk = sm4Encrypt(m_strAK.toUtf8());
// // qDebug() << "tempAk:" << tempAk.toHex();
// QByteArray tempSk =sm4Encrypt(m_strSK.toUtf8());
// // qDebug() << "tempSk:" << tempSk.toHex();
// QByteArray tempBucket = sm4Encrypt(m_strBucket.toUtf8());
// // qDebug() << "tempBucket" << tempBucket.toHex();
}
GmsslManager::~GmsslManager()
{}
void GmsslManager::getKey()
{
QString strBase = "#cdtJyy2025";
QByteArray salt = strBase.toUtf8();
// 使用SHA-256生成32字节哈希
QByteArray hash = QCryptographicHash::hash(salt, QCryptographicHash::Sha256);
m_strKey = hash.left(16);
m_strIv = hash.right(16);
// 转换为十六进制字符串
QString hexKey = m_strKey.toHex();
QString hexIv = m_strIv.toHex();
qDebug() << "key:" << hexKey;
qDebug() << "iv:" << hexIv;
}
QByteArray GmsslManager::sm4Encrypt(const QByteArray &plaintext)
{
if (m_strKey.size() != 16 || m_strIv.size() != 16) {
qDebug() << "Error: Key and IV must be 16 bytes";
return QByteArray();
}
qDebug() << ".1...";
// 设置加密密钥
SM4_KEY sm4_key;
sm4_set_encrypt_key(&sm4_key, reinterpret_cast<const unsigned char*>(m_strKey.constData()));
// PKCS7填充
int block_size = 16;
int fill_len = block_size - (plaintext.size() % block_size);
// 显式处理整除情况
if (fill_len == 0)
fill_len = block_size;
int plaintext_len = plaintext.size();
int padded_len = plaintext_len + fill_len;
memset(m_plaintext, 0, MAX_LEN);
memset(m_padded, 0, MAX_LEN);
memcpy(m_padded, plaintext.constData(), plaintext_len);
// 填充最后一个字节的值
memset(m_padded + plaintext_len, fill_len, fill_len);
// 加密
sm4_cbc_encrypt(
&sm4_key,
reinterpret_cast<const unsigned char*>(m_strIv.constData()), // 固定IV
m_padded,
padded_len,
m_plaintext
);
qDebug() << ".4... ,padded_len: " << padded_len;
QByteArray plaintext_temp(reinterpret_cast<const char*>(m_plaintext), padded_len);
// qDebug() << "plaintext_temp: " << plaintext_temp.toHex();
qDebug() << "plaintext_temp size:" << plaintext_temp.size();
int end_index = plaintext_temp.size() - 1;
while (end_index >= 0 && plaintext_temp.at(end_index) == '\0') {
--end_index;
}
// 如果所有字符都是零,则有效长度为0
if (end_index < 0) {
plaintext_temp = QByteArray(); // 清空数据
} else {
// 截取有效数据(从开头到第一个非零字符的位置+1)
plaintext_temp = plaintext_temp.left(end_index + 1);
}
qDebug() << "ciphertext:" << plaintext_temp.toHex();
// 返回密文
return plaintext_temp;
// return QByteArray();
}
QByteArray GmsslManager::sm4Decrypt(const QByteArray &ciphertext)
{
// 检查输入和密钥
if (ciphertext.size() % 16 != 0) {
qWarning() << "Invalid ciphertext length";
return QByteArray();
}
if (m_strKey.size() != 16 || m_strIv.size() != 16) {
qWarning() << "Key and IV must be 16 bytes!";
return QByteArray();
}
// 设置解密密钥
SM4_KEY sm4_key;
sm4_set_decrypt_key(&sm4_key, reinterpret_cast<const unsigned char*>(m_strKey.constData()));
memset(m_ciphertext, 0, MAX_LEN);
qDebug() << "ciphertext size:" << ciphertext.size();
// 解密
// QByteArray decrypted(ciphertext.size(), 0);
sm4_cbc_decrypt(
&sm4_key,
reinterpret_cast<const unsigned char*>(m_strIv.constData()),
reinterpret_cast<const unsigned char*>(ciphertext.constData()),
ciphertext.size(),
m_ciphertext
);
qDebug() << "entry ciphertext_temp";
QByteArray ciphertext_temp(reinterpret_cast<const char*>(m_ciphertext), ciphertext.size());
qDebug() << "ciphertext_temp size:" << ciphertext_temp.size();
int end_index = ciphertext_temp.size() - 1;
while (end_index >= 0 && ciphertext_temp.at(end_index) == '\0') {
--end_index;
}
// 如果所有字符都是零,则有效长度为0
if (end_index < 0) {
ciphertext_temp = QByteArray(); // 清空数据
} else {
// 截取有效数据(从开头到第一个非零字符的位置+1)
ciphertext_temp = ciphertext_temp.left(end_index + 1);
}
qDebug() << "ciphertext:" << ciphertext_temp.toHex();
// 去除填充
int pad_len = static_cast<unsigned char>(ciphertext_temp.back());
if (pad_len > 16 || pad_len < 1)
{
qWarning() << "Invalid padding";
return QByteArray();
}
return ciphertext_temp.left(ciphertext_temp.size() - pad_len);
}
#ifndef GMSSLMANAGER_H
#define GMSSLMANAGER_H
#include <QObject>
#include <QByteArray>
#define MAX_LEN 4096
class GmsslManager : public QObject {
Q_OBJECT
public:
GmsslManager();
~GmsslManager();
QByteArray sm4Encrypt(const QByteArray &plaintext);
QByteArray sm4Decrypt(const QByteArray &ciphertext);
private:
void getKey();
private:
QByteArray m_strKey;
QByteArray m_strIv;
QByteArray strSalt = "";
unsigned char m_plaintext[MAX_LEN] = {0};
unsigned char m_ciphertext[MAX_LEN] = {0};
unsigned char m_padded[MAX_LEN] = {0};
};
#endif // GMSSLMANAGER_H
这库把人当日本人整啊,有谁知道原因可以留言解惑一下。