https://blog.youkuaiyun.com/Sagittarius_Warrior/article/details/53502359
本文主要讲解License Generator的实现,总体设计请参考前一篇文章。
一、导出导入库
License Generator是采用QT实现的,它需要导入前面的加解密DLL。导入库的设计如下:
#ifndef AES_DLL_H
#define AES_DLL_H
#ifdef AES_IMPORT
#define AES_API extern "C" __declspec(dllexport)
#else
#define AES_API extern "C" __declspec(dllimport)
#endif
#include <string>
using std::string;
class IEncryptor
{
public:
virtual void SetKey(unsigned char * key, unsigned char * iv, int length) = 0;
// encrypt the plainText and generate a file, the plainText should be a string with '\0' end
virtual bool EncryptString2File(const char * plainText, const char * outFilename) = 0;
// decyrpt the file and output the recover, you may calculate the size of the file and allocate the space for recover
virtual bool DecryptFile2String(const char * decFilename, char * recoverText) = 0;
};
AES_API IEncryptor* CreateEncryptor();
AES_API void ReleaseEncryptor(IEncryptor* pEncryptor);
typedef IEncryptor* (*pfnCreateEncryptor)();
typedef void (*pfnReleaseEncryptor)(IEncryptor*);
#endif // AES_DLL_H
它主要包括两个导出函数,和一个接口类。这两个导出函数主要复杂管理类对象,主要功能还是在这个接口类中。
这个接口类提供了三个接口:
1)设置加解密的密匙;
2)加密字符串并生成加密文件;
3)将加密文件解密,并输出字符串;
二、初始化
我将加密库的载入和密匙的设置放到MainWindow的构造函数中,如下:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_library("EncryptorDll.dll"),
m_pEncryptor(nullptr)
{
ui->setupUi(this);
QString currentDate = (QDate::currentDate()).toString("yyyy/MM/dd");
QString Deadline = (QDate::currentDate().addMonths(1)).toString("yyyy/MM/dd");
ui->lineEdit_6->setText(currentDate);
ui->lineEdit_7->setText(Deadline);
ui->lineEdit_8->setText(currentDate);
unsigned char key[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0A, 0x0B,0x0C,0x0D,0x0E,0x0F,0x10};
//AES::DEFAULT_KEYLENGTH
unsigned char iv[] = {0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08, 0x07,0x06, 0x05,0x04,0x03,0x02,0x01,0x10};
int keysize = 16;
m_library.load();
if (m_library.isLoaded())
{
pfnCreateEncryptor pCreate = (pfnCreateEncryptor)m_library.resolve("CreateEncryptor");
if (pCreate)
{
m_pEncryptor = pCreate();
m_pEncryptor->SetKey(key,iv,keysize);
}
}
}
加解密DLL库载入成功后,会解析出导入函数“CreateEncryptor”,然后调用该函数,创建真正的加解密类对象,并设置密匙。
三、预览
下面是“Preview”控件的响应函数
void MainWindow::on_btnPreview_clicked()
{
QString strPlain{"f0f0,"};
int count = 8;
QLabel* arrLabel[8] = {ui->label_1,ui->label_2,ui->label_3,ui->label_4,
ui->label_5,ui->label_6,ui->label_7,ui->label_8};
QLineEdit* arrLine[8] = {ui->lineEdit_1,ui->lineEdit_2,ui->lineEdit_3,ui->lineEdit_4,
ui->lineEdit_5,ui->lineEdit_6,ui->lineEdit_7,ui->lineEdit_8};
for (int i = 0; i < count; ++i)
{
strPlain += arrLabel[i]->text();
strPlain += arrLine[i]->text();
strPlain += ',';
}
strPlain += "0f0f";
ui->plaintext->setPlainText(strPlain);
}
四、加密和解密
下面是加密和解密按键的响应函数
void MainWindow::on_btnEncrypt_clicked()
{
string plainText = ui->plaintext->toPlainText().toStdString();
string fileName = ui->lineEdit_3->text().toStdString() + ".license";
if (m_pEncryptor->EncryptString2File(plainText.c_str(), fileName.c_str()))
{
ui->ciphertext->setPlainText("Encrypt succeed!");
}
else
{
ui->ciphertext->setPlainText("Encrypt failed!");
}
}
void MainWindow::on_btnDecrypt_clicked()
{
string fileName = ui->lineEdit_3->text().toStdString() + ".license";
QFileInfo fileInfo(fileName.c_str());
char * recover = new char[fileInfo.size()];
if (m_pEncryptor->DecryptFile2String(fileName.c_str(), recover))
{
ui->recovertext->setPlainText(QString(recover));
}
else
{
ui->recovertext->setPlainText(QString("Recover failed!"));
}
}
五、补充说明
原始的Cryptoo++库,推荐用静态库的方式嵌入程序,但是,我之前一直没在Qt中尝试成功过“静态库”的加载,甚至“动态链接库的非Load加载方式”也多次尝试失败。因此,逼得我设计除了“Interface Class”的方式,并在Qt中用QLibrary加载VS生成的DLL。
今天,我偷闲又试验了一把“Qt非Load方式加载DLL”,竟然成功了,特此补充。我还是用这个License工程为实验对象。“Qt非Load方式加载DLL”其实也不复杂,可以分为三步,事实上,静态库也可以按这个方法加载。
1,使用QCreator,打开宿主工程,在“项目”窗口,右键“项目目录树的根节点”,选择“添加库”。
2,在弹出来的对话框中,选择“库类型”为“外部库”,然后选择待添加的库的路径。
注:仔细观察上图,它是可以选择静态库的。
3,点击“下一步”,Qcreator将在*.pro文件添加以下代码
事实上,Qt非Load方式加载DLL仅需要添加这些代码。
注:做完以上工作,即可以加载DLL了。下面,我再以LicenseSystem为例,修改代码如下:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
//m_library("EncryptorDll.dll"),
m_pEncryptor(nullptr)
{
ui->setupUi(this);
QString currentDate = (QDate::currentDate()).toString("yyyy/MM/dd");
QString Deadline = (QDate::currentDate().addMonths(1)).toString("yyyy/MM/dd");
ui->lineEdit_6->setText(currentDate);
ui->lineEdit_7->setText(Deadline);
ui->lineEdit_8->setText(currentDate);
unsigned char key[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0A, 0x0B,0x0C,0x0D,0x0E,0x0F,0x10};
//AES::DEFAULT_KEYLENGTH
unsigned char iv[] = {0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08, 0x07,0x06, 0x05,0x04,0x03,0x02,0x01,0x10};
int keysize = 16;
// m_library.load();
// if (m_library.isLoaded())
// {
// pfnCreateEncryptor pCreate = (pfnCreateEncryptor)m_library.resolve("CreateEncryptor");
// if (pCreate)
// {
// m_pEncryptor = pCreate();
// m_pEncryptor->SetKey(key,iv,keysize);
// }
// }
m_pEncryptor = CreateEncryptor();
m_pEncryptor->SetKey(key,iv,keysize);
}
MainWindow::~MainWindow()
{
delete ui;
// if (m_library.isLoaded())
// {
// pfnReleaseEncryptor pRelease = (pfnReleaseEncryptor)m_library.resolve("ReleaseEncryptor");
// if (pRelease)
// {
// pRelease(m_pEncryptor);
// }
// m_library.unload();
// }
ReleaseEncryptor(m_pEncryptor);
}
注:以上注释了QLibrary和Load,直接调用DLL中的接口函数。
---------------------
作者:Sagittarius_Warrior
来源:优快云
原文:https://blog.youkuaiyun.com/Sagittarius_Warrior/article/details/53502359
版权声明:本文为博主原创文章,转载请附上博文链接!