首页 > 其他分享 >QT使用OpenSSL的接口实现RSA2的签名和验签

QT使用OpenSSL的接口实现RSA2的签名和验签

时间:2024-02-22 18:11:27浏览次数:37  
标签:加密 QT 和验 RSA OpenSSL char 签名 data unsigned

QT使用OpenSSL的接口实现RSA2的签名和验签

加密和签名在RSA加密算法中是两个不同的概念,虽然它们都涉及RSA密钥对的使用,但目的和应用场景有所不同。

  1. 加密 (encrypt/decrypt):
    • 加密:使用接收方的公钥对数据进行加密,只有拥有相应私钥的接收方才能解密数据。
    • 解密:使用接收方的私钥对加密数据进行解密,从而获得原始数据。
    • 加密用于保护数据的机密性,确保只有授权的人能够解密和读取数据。
  2. 签名 (sign/verify):
    • 签名:使用发送方的私钥对数据进行签名,产生一个数字签名。
    • 验证签名:使用发送方的公钥对数字签名进行验证,以确保数据的完整性和认证发送方身份。
    • 签名用于验证数据的完整性和真实性,确保数据在传输过程中没有被篡改。

在RSA加密算法中,加密和签名使用了相同的RSA密钥对,但是应用场景和目的不同。加密是为了保护数据的机密性,而签名是为了验证数据的完整性和真实性。

所以,虽然在技术上可以使用RSA密钥对进行加密和签名,但是在实际应用中,通常会根据具体的需求和安全要求来选择是使用加密还是签名功能。

#include <QCoreApplication>
#include <QDebug>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

// 加密函数
QByteArray encryptData(const QByteArray &data, RSA *publicKey) {
    int rsaLen = RSA_size(publicKey);
    unsigned char *encryptBuffer = new unsigned char[rsaLen];
    int result = RSA_public_encrypt(data.size(), reinterpret_cast<const unsigned char*>(data.constData()), encryptBuffer, publicKey, RSA_PKCS1_PADDING);
    if (result == -1) {
        qWarning() << "Encryption failed.";
        return QByteArray();
    }
    return QByteArray(reinterpret_cast<char*>(encryptBuffer), result);
}

// 解密函数
QByteArray decryptData(const QByteArray &data, RSA *privateKey) {
    int rsaLen = RSA_size(privateKey);
    unsigned char *decryptBuffer = new unsigned char[rsaLen];
    int result = RSA_private_decrypt(data.size(), reinterpret_cast<const unsigned char*>(data.constData()), decryptBuffer, privateKey, RSA_PKCS1_PADDING);
    if (result == -1) {
        qWarning() << "Decryption failed.";
        return QByteArray();
    }
    return QByteArray(reinterpret_cast<char*>(decryptBuffer), result);
}

RSA* createRSAFromPEM(const char* key, bool isPublicKey) {
    BIO *bio = BIO_new_mem_buf((void*)key, -1);
    if (bio == NULL) {
        qWarning() << "Failed to create BIO";
        return NULL;
    }

    RSA *rsa = NULL;
    if (isPublicKey) {
        rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
    } else {
        rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
    }

    BIO_free(bio);
    return rsa;
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
#if 0
    // 初始化 OpenSSL
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    // 生成RSA密钥对
    RSA *rsaKeyPair = RSA_generate_key(2048, RSA_F4, NULL, NULL);
    if (!rsaKeyPair) {
        qWarning() << "Failed to generate RSA key pair.";
        return 1;
    }
    // 获取公钥
    BIO *bioPub = BIO_new(BIO_s_mem());
    PEM_write_bio_RSAPublicKey(bioPub, rsaKeyPair);
    char *pubKeyBuffer;
    long pubKeyLength = BIO_get_mem_data(bioPub, &pubKeyBuffer);
    qDebug() << "Public Key: " << QByteArray(pubKeyBuffer, pubKeyLength);

    // 获取私钥
    BIO *bioPriv = BIO_new(BIO_s_mem());
    PEM_write_bio_RSAPrivateKey(bioPriv, rsaKeyPair, NULL, NULL, 0, NULL, NULL);
    char *privKeyBuffer;
    long privKeyLength = BIO_get_mem_data(bioPriv, &privKeyBuffer);
    qDebug() << "Private Key: " << QByteArray(privKeyBuffer, privKeyLength);

    // 待签名的数据
    const char *data = "Hello, world!";
    int dataSize = strlen(data);

    // 签名
    unsigned char signature[256]; // 2048 bit key size
    unsigned int signatureLength;
    if (RSA_sign(NID_sha256, (const unsigned char*)data, dataSize, signature, &signatureLength, rsaKeyPair) != 1) {
        qWarning() << "Failed to sign data.";
        return 1;
    }

    qDebug() << "Signature: " << QByteArray(reinterpret_cast<char*>(signature), signatureLength).toBase64();

    // 验证签名
    if (RSA_verify(NID_sha256, (const unsigned char*)data, dataSize, signature, signatureLength, rsaKeyPair) != 1) {
        qDebug() << "Signature is invalid!";
    } else {
        qDebug() << "Signature is valid!";
    }



    // 释放资源
    RSA_free(rsaKeyPair);
    BIO_free(bioPub);
    BIO_free(bioPriv);
    EVP_cleanup();
#endif

    /*

        支付宝的RSA2签名算法,支付宝开放平台SDK(https://docs.open.alipay.com/54)封装的签名工具类进行签名,一般的流程如下:

        签名 (RSA2 Sign):
            使用商户私钥对数据进行签名,生成数字签名。
            将数字签名与数据一起发送给支付宝或其他服务端。
        验证签名 (RSA2 Verify):
            支付宝或服务端使用商户提供的公钥对接收到的数据和签名进行验证。
            验证签名的有效性,以确保数据的完整性和真实性。

        在这种情况下,商户通常会使用支付宝提供的公钥对支付宝返回的数据进行验签,以确保数据的完整性和真实性,防止数据被篡改
    */
    // 商户提供的公钥和私钥
    const char *pubKeyStr = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArtwVzIpLvzzGxQ074EYCIyNj0k16YukrF27rEu7JFndms6FWWzLwX3QxTiQSN6tfbEwV5K67H5cCc4yesOJWdVA3ft023+V2I3hDS2jdRvQU5Rwju4mUisi12/aE5c1N6jkxpjzDGiUNYdwHEHzj+9awBlMusJ3B2U1fZDO5hoU39bxWJ9xgsEOmKT1VJBYeteIAyf0jwyeDBxIfw15NU+H31QRS4xbCDJ4DPKn3jjpvfBd/6h6fFT1Yj/FHbvzfabRZjnEAciNhUj+cOw6O5bYKnyNcNt1bjvhGBSVc3p+FaUKfkdGwNOA+haXraN+F+BBLuyTapSReawQo/BErIQIDAQAB\n-----END PUBLIC KEY-----";
    const char *privKeyStr = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCu3BXMiku/PMbFDTvgRgIjI2PSTXpi6SsXbusS7skWd2azoVZbMvBfdDFOJBI3q19sTBXkrrsflwJzjJ6w4lZ1UDd+3Tbf5XYjeENLaN1G9BTlHCO7iZSKyLXb9oTlzU3qOTGmPMMaJQ1h3AcQfOP71rAGUy6wncHZTV9kM7mGhTf1vFYn3GCwQ6YpPVUkFh614gDJ/SPDJ4MHEh/DXk1T4ffVBFLjFsIMngM8qfeOOm98F3/qHp8VPViP8Udu/N9ptFmOcQByI2FSP5w7Do7ltgqfI1w23VuO+EYFJVzen4VpQp+R0bA04D6Fpeto34X4EEu7JNqlJF5rBCj8ESshAgMBAAECggEAStXGPpOxd1b7ern/NizAHWm3/vlJt6sy1gSSdrfbN9JCEf6qhr12QmPn9hlZ8plVbXPiqsxdKVfnpKw5/lnfxrVeCt2B7rC1rth5dHyctxEfIC663Dg1anAb5NfMaM1E20k/BnZayYWyBH+2RkgtCksHaq2O/eeGXwnOGYRJklgZnO8inITJiSnnvuVbN9W+JvHCTcuHjKp/YOAXBJGAWDsuBbIaaeYAlXhrzSeUvBlQSljp7JZyauQ3hTXDZzAJ9HYergWMWkg/iCo6iOw5NulkNtiWosTO+A8wWHFgN+vok8itIDyXMpNCcZBz8EPDug/dBH1L2yPp+nln+YGvQQKBgQD7cf7BwgtlTqtEeLDtqMrhqCqcU+e8N4w7DHj2VzuYFnpTIHXqn4SWSP0gjF/os04NtHcEMIX8l8Ihtl4iu6ivvcvTjf0s1/gD2BD8m08EHACi9bf4if/3Q7tBTzgiRasFbS9WNDprycp9uKweB+zByPp+rYahJoWJyUd3M0U5CwKBgQCyBvJNdtW+8Ph27jOrHyMGLK07SIpUfGZz1O0PYrYoqj33WnOJKIz2y26jQiXS8nPvi/XgAEYiQkbD+uVIXGgJXoJFH8+78i/Ne42q/GtCniqR3SUrWRUD8GvRrLXyzytnmX1yLJSSHeICw7/Gp48iQCN2tOFlz/bX2/lsPrSAAwKBgGoACJHOJ9exbmoTJyNJgR3YMv5sMMkb8bYC8AuJgsn+z9qzWIJsdQyWAH/0LYp/7GvCpFnTyuhNYb2sj8q8qcRMktzAgvagpSGZuK+FGa51z57jT4crRgkLOKmzp8pq7EoBWW9R3T8Ldp3BeG3AkYKwI0m8BYFyJ+GKROJvbsM5AoGAA1J73RQ1ou2ORXHmhu/60FevF+cfpbn4k3rKvbnC2nlq1J3cgBfAoa5kLynB2PDrVvIOsZJvvJ3uAiRBeRs4Wcxos++HCePYHoaKu0Ego0qeUsCEvA1ahgtLh8soThKtpa5ImAPa9esW16RdhNCFrEb0Inf3qNW7roWNXwbAiY8CgYEA7B4NzyR47a2/QBHU7y20JpgLTkhwCHQRsmdqcuLXKQxM3+Twe3HHy7VV9JmL6XBo3yPP9ArmpbiP8z0XGainXR977eAmBALX55HBWvoNU0xzASKbMjEIHjOMa7KHl3cA1OkQMNHfk5x3gFt8io9ChTlMdbQEES3elg3ITkELnNI=\n-----END PRIVATE KEY-----";

    // 从字符串中加载公钥和私钥
    RSA *publicKey = createRSAFromPEM(pubKeyStr, true);
    RSA *privateKey = createRSAFromPEM(privKeyStr, false);

    // 加密和解密测试
    QByteArray originalData = "Hello, RSA2!";
    QByteArray encryptedData = encryptData(originalData, publicKey);
    QByteArray decryptedData = decryptData(encryptedData, privateKey);

    qDebug() << "Original Data: " << originalData;
    qDebug() << "Encrypted Data: " << encryptedData.toBase64();
    qDebug() << "Decrypted Data: " << decryptedData;

    // 待签名的数据
    const char *data = "Hello, world!";
    int dataSize = strlen(data);
    // 签名
    unsigned char signature[256]; // 2048 bit key size
    unsigned int signatureLength;
    if (RSA_sign(NID_sha256, (const unsigned char*)data, dataSize, signature, &signatureLength, privateKey) != 1) {
        qWarning() << "Failed to sign data.";
        return 1;
    }

    qDebug() << "Signature: " << QByteArray(reinterpret_cast<char*>(signature), signatureLength).toBase64();

    // 验证签名
    if (RSA_verify(NID_sha256, (const unsigned char*)data, dataSize, signature, signatureLength, publicKey) != 1) {
        qDebug() << "Signature is invalid!";
    } else {
        qDebug() << "Signature is valid!";
    }

    // 释放资源
    RSA_free(publicKey);
    RSA_free(privateKey);
    EVP_cleanup();

    return app.exec();
}

标签:加密,QT,和验,RSA,OpenSSL,char,签名,data,unsigned
From: https://www.cnblogs.com/huanyinglvtuan/p/18027903

相关文章

  • Qt 图例类QLegend详解
    概述在Qt绘制图表时,图例并不是由QChart类所管理的,而是交给单独的QLegend类。QLegend类负责图例的绘制(包括颜色、线型、字体等),它与图表类QChart的关系是attach和detach。实例参考官方实例:X:\Qt\Qt5.9.0\Examples\Qt-5.9\charts\legend运行效果:功能详解设置图例标......
  • Qt 设置QPushButton背景色
    刚开始编写的设置背景色代码用的是QPalette类:1QPalettepalette1=ui->pushButton->palette();2palette1.setColor(QPalette::ButtonText,Qt::red);//设置字体颜色为红色3palette1.setColor(QPalette::Button,Qt::green);//设置背景颜色为绿色4ui->pushButton->setPalette......
  • Qt QWindowsWindow::setGeometryDp: Unable to set geometry问题
    总结原因:由于子窗口和父窗口的大小关系不健康,导致父窗口resize失败,失败后会自定义大小解决方法:首先,修改父窗口尺寸,保证其大小可以容纳子部件,可以使用setFixSize()之类的函数修改父窗口尺寸。其次,一定要保证修改父窗口尺寸的函数是放在窗口布局代码之前,如图,我的setIn......
  • Qt 颜色对话框QColorDialog弹出时应用程序输出栏出现QWindowsWindow::setGeometry: Un
    引言在项目中点击按钮,弹出颜色选择对话框,但同时应用程序会在应用程序输出一栏中显示QWindowsWindow::setGeometry:Unabletosetgeometry180x30+345+311(frame:202x86+334+266)onQWidgetWindow/"QColorDialogClassWindow"on"\\.\DISPLAY1".Resultinggeometry:5......
  • qt vs 引用第三方lib
    项目目录,plug是资源文件,ZL.Main是根目录(发布后需要把plug复制在debug中exe同目录 一:该目录填include目录,可以相对路径可以绝对路径 二:该目录填lib目录,可以相对路径可以绝对路径 三:该项填lib文件名,有几个填写几个 第四:配置平台管理器 ......
  • MQTT协议及其使用案例
    MQTT概述MQTT是基于TCP/IP协议栈构建的异步通信消息协议,是一种轻量级的发布、订阅信息传输协议。可以在不可靠的网络环境中进行扩展,适用于设备硬件存储空间或网络带宽有限的场景。使用MQTT协议,消息发送者与接收者不受时间和空间的限制。Docker部署MQTT(采用docker-compose.y......
  • qtcpsocket连接状态
      QTcpSocketsocket;//连接到远程主机socket.connectToHost("remoteHost",1234);//获取连接状态QAbstractSocket::SocketStatesocketState=socket.state();//根据连接状态进行相应处理if(socketState==QAbstractSocket::UnconnectedState){//未连......
  • Qt程序执行报错:"This application failed to start because not Qt platform plugin c
    Qt编译的exe程序执行时报错:出现以上错误的原因是由于的系统环境路径缺失或者exe程序目录下缺少对应的dll导致。以上为缺少对应的Qtplatformplugin。在Qt的安装目录下将platforms整个目录拷贝到exe所在目录下,即可执行。如果提示缺少对于的xxx.dll直接将对应缺失......
  • 给 PyQt5 登录添加记住用户密码功能,并优化一些内容
    使用PyQt5(PySide2)+SQLAlchemy做一个登录注册页(七)本文将介绍自己用PyQt5+SQLAlchemy做的一个登录注册页,使用邮箱接收验证码,本文介绍是前后端未分离的实现方式,后续将出一个前后端分离的,你可以将PyQt5改为PySide2以获得更宽松的开源协议本文由于涉及到的代码较多,将会是一......
  • openssh漏洞修复之升级openssh与openssl
    下载Openssh和Opensslwgetftp://mirrors.sonic.net/pub/OpenBSD/OpenSSH/portable/wgethttps://www.openssl.org/source/openssl-1.1.1h.tar.gz安装Openssltar-zxfopenssl-1.1.1h.tar.gzcdopenssl-1.1.1h./config--prefix=/usr/local/openssl-1.1.1-dsharedmake......