qt 调用gmssl

下载地址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

这库把人当日本人整啊,有谁知道原因可以留言解惑一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值