QT使用OpenSSL的接口實現RSA的加密解密
首先介紹下命令台下openssl工具的簡單使用:
- 生成一個密鑰:
openssl genrsa -out test.key 1024
這里-out指定生成文件的。需要注意的是這個文件包含了公鑰和密鑰兩部分,也就是說這個文件即可用來加密也可以用來解密。后面的1024是生成密鑰的長度。
- openssl可以將這個文件中的公鑰提取出來:
openssl rsa -in test.key -pubout -out test_pub.key
-in指定輸入文件,-out指定提取生成公鑰的文件名。至此,我們手上就有了一個公鑰,一個私鑰(包含公鑰)。現在可以將用公鑰來加密文件了。
- 我在目錄中創建一個hello的文本文件,然后利用此前生成的公鑰加密文件:
openssl rsautl -encrypt -in hello -inkey test_pub.key -pubin -out hello.en
-in指定要加密的文件,-inkey指定密鑰,-pubin表明是用純公鑰文件加密,-out為加密后的文件。
- 解密文件:
openssl rsautl -decrypt -in hello.en -inkey test.key -out hello.de
-in指定被加密的文件,-inkey指定私鑰文件,-out為解密后的文件。
OpenSSL> genrsa -out rsa_private_key.pem 1024
Generating RSA private key, 1024 bit long modulus
....+++++
.................+++++
e is 65537 (0x10001)
OpenSSL> genrsa -out rsa_private_key.pem 1024
Generating RSA private key, 1024 bit long modulus
..............+++++
..........................................+++++
e is 65537 (0x10001)
OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
writing RSA key
OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -out pkcs8_rsa_private_key.pem -nocrypt
OpenSSL> rsautl -encrypt -in hello.txt -inkey rsa_public_key.pem -pubin -out hello.en
OpenSSL> rsautl -decrypt -in hello.en -inkey rsa_private_key.pem -out hello.de
QT代碼實現
test1.pro
QT += core
QT -= gui
CONFIG += c++11
TARGET = test1
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp \
# rsasignature.cpp \
rsa.cpp
LIBS += ../windows/x86/bin/libeay32.dll
LIBS += ../windows/x86/bin/ssleay32.dll
INCLUDEPATH += $$quote(../windows/x86/include/)
HEADERS += \
# rsasignature.h \
rsa.h
DESTDIR = $$PWD/
main.cpp
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include "rsa.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
/*公鑰加密,私鑰解密 測試案例*/
QString strPlainData_before = QString::fromLocal8Bit("12dsadas雲123345612dsadas12dsadas雲123345612dsadas12dsadas雲123345612dsadas12dsadas雲123345612dsadas12dsadas雲213123");
QString strPubKey = "";
QString strPriKey = "";
QString strEncryptData = "";
QString strPlainData = "";
rsa *m_rsa = new rsa();
QFile file("./rsa_public_key.pem");
file.open(QIODevice::ReadOnly);
strPubKey = file.readAll();
QFile file1("./rsa_private_key.pem");
file1.open(QIODevice::ReadOnly);
strPriKey = file1.readAll();
strEncryptData = m_rsa->rsaPubEncrypt(strPlainData_before,strPubKey);
qDebug() << ("strEncryptData:"+strEncryptData);
strPlainData = m_rsa->rsaPriDecrypt(strEncryptData, strPriKey);
qDebug() << ("strPlainData:"+strPlainData);
file.close();
file1.close();
return a.exec();
}
rsa.h
#ifndef RSA_H
#define RSA_H
#include <QString>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#define BEGIN_RSA_PUBLIC_KEY "BEGIN RSA PUBLIC KEY"
#define BEGIN_RSA_PRIVATE_KEY "BEGIN RSA PRIVATE KEY"
#define BEGIN_PUBLIC_KEY "BEGIN PUBLIC KEY"
#define BEGIN_PRIVATE_KEY "BEGIN PRIVATE KEY"
#define KEY_LENGTH 1024
class rsa
{
public:
rsa();
~rsa();
QString rsaPubEncrypt(const QString &strPlainData, const QString &strPubKey);
QString rsaPriDecrypt(const QString &strDecryptData, const QString &strPriKey);
};
#endif // RSA_H
rsa.cpp
#include "rsa.h"
rsa::rsa()
{
}
rsa::~rsa()
{
}
QString rsa::rsaPubEncrypt(const QString &strPlainData, const QString &strPubKey)
{
QByteArray pubKeyArry = strPubKey.toUtf8();
uchar* pPubKey = (uchar*)pubKeyArry.data();
BIO* pKeyBio = BIO_new_mem_buf(pPubKey, pubKeyArry.length());
if (pKeyBio == NULL) {
return "";
}
RSA* pRsa = RSA_new();
if (strPubKey.contains(BEGIN_RSA_PUBLIC_KEY)) {
pRsa = PEM_read_bio_RSAPublicKey(pKeyBio, &pRsa, NULL, NULL);
}
else {
pRsa = PEM_read_bio_RSA_PUBKEY(pKeyBio, &pRsa, NULL, NULL);
}
if (pRsa == NULL) {
BIO_free_all(pKeyBio);
return "";
}
int nLen = RSA_size(pRsa);
char* pEncryptBuf = new char[nLen];
//加密
QByteArray plainDataArry = strPlainData.toUtf8();
int nPlainDataLen = plainDataArry.length();
int exppadding=nLen;
if(nPlainDataLen>exppadding-11)
exppadding=exppadding-11;
int slice=nPlainDataLen/exppadding;//片數
if(nPlainDataLen%(exppadding))
slice++;
QString strEncryptData = "";
QByteArray arry;
for(int i=0; i<slice; i++)
{
QByteArray baData = plainDataArry.mid(i*exppadding, exppadding);
nPlainDataLen = baData.length();
memset(pEncryptBuf, 0, nLen);
uchar* pPlainData = (uchar*)baData.data();
int nSize = RSA_public_encrypt(nPlainDataLen,
pPlainData,
(uchar*)pEncryptBuf,
pRsa,
RSA_PKCS1_PADDING);
if (nSize >= 0)
{
arry.append(QByteArray(pEncryptBuf, nSize));
}
}
strEncryptData += arry.toBase64();
//釋放內存
delete pEncryptBuf;
BIO_free_all(pKeyBio);
RSA_free(pRsa);
return strEncryptData;
}
QString rsa::rsaPriDecrypt(const QString &strDecryptData, const QString &strPriKey)
{
QByteArray priKeyArry = strPriKey.toUtf8();
uchar* pPriKey = (uchar*)priKeyArry.data();
BIO* pKeyBio = BIO_new_mem_buf(pPriKey, priKeyArry.length());
if (pKeyBio == NULL) {
return "";
}
RSA* pRsa = RSA_new();
pRsa = PEM_read_bio_RSAPrivateKey(pKeyBio, &pRsa, NULL, NULL);
if (pRsa == NULL) {
BIO_free_all(pKeyBio);
return "";
}
int nLen = RSA_size(pRsa);
char* pPlainBuf = new char[nLen];
//解密
QByteArray decryptDataArry = strDecryptData.toUtf8();
decryptDataArry = QByteArray::fromBase64(decryptDataArry);
int nDecryptDataLen = decryptDataArry.length();
int rsasize=nLen;
int slice=nDecryptDataLen/rsasize;//片數
if(nDecryptDataLen%(rsasize))
slice++;
QString strPlainData = "";
for(int i=0; i<slice; i++)
{
QByteArray baData = decryptDataArry.mid(i*rsasize, rsasize);
nDecryptDataLen = baData.length();
memset(pPlainBuf, 0, nLen);
uchar* pDecryptData = (uchar*)baData.data();
int nSize = RSA_private_decrypt(nDecryptDataLen,
pDecryptData,
(uchar*)pPlainBuf,
pRsa,
RSA_PKCS1_PADDING);
if (nSize >= 0) {
strPlainData += QByteArray(pPlainBuf, nSize);
}
}
//釋放內存
delete pPlainBuf;
BIO_free_all(pKeyBio);
RSA_free(pRsa);
return strPlainData;
}