You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 lines
10 KiB
C++

1 year ago
#include "Auth.h"
#include <QDateTime>
#include "Utils.h"
#include <QDebug>
#include <fstream>
#include <QMessageBox>
Auth *Auth::m_pInstance = nullptr;
std::mutex Auth::m_mutex;
Auth::Auth()
{
m_isEncrypt = true;
m_bTimesFlag = false;
m_companyName = "";
m_date = "19700101";
m_times = 0;
m_cfgFileName = "tmskey.cfg";
m_desKey = "tmskey2021_zwzxfyxcytq!";
m_hexDesKey = Utils::strToHexStr(m_desKey);
}
Auth::~Auth()
{
}
std::string Auth::getOriginString()
{
std::string str = "";
// 公司名
str.append(m_companyName);
// 产品类型UCHAR转为HEX格式
str.append(",");
//str.append(Utils::strToHexStr(Utils::ucharToStr(m_productType)));
str.append(Utils::ucharToHexStr(m_productType));
// 使用期限
str.append(",");
str.append(m_publishDate); // 发布日期
str.append(",");
str.append(m_date); // 使用期限
// 使用次数
str.append(",");
str.append(m_bTimesFlag ? "1" : "0");
str.append(",");
str.append(std::to_string(m_times));
// 高级设置密码 - 后续考虑密码额外加密
str.append(",");
str.append(Utils::strToHexStr(m_advancePwd));
//QMessageBox::warning(this, "Warning!", tr("Origin String : %1").arg(str), QMessageBox::Ok, QMessageBox::Ok);
return str;
}
std::string Auth::toMessage()
{
std::string str = "";
// 公司名
str.append("公司名 : ");
str.append(m_companyName);
str.append("\n");
// 产品类型
str.append("产品类型 : \n");
str.append("\t电动扳手").append((((m_productType >> 0) & 0x01) == 1) ? "(true)" : "(false)").append("\n");
str.append("\t充电扳手").append((((m_productType >> 1) & 0x01) == 1) ? "(true)" : "(false)").append("\n");
str.append("\t液压扳手").append((((m_productType >> 2) & 0x01) == 1) ? "(true)" : "(false)").append("\n");
str.append("\t气动扳手").append((((m_productType >> 3) & 0x01) == 1) ? "(true)" : "(false)").append("\n");
// 使用期限
str.append("发布日期 : ");
str.append(m_publishDate);
str.append("\n");
str.append("使用期限 : ");
str.append(m_date);
str.append("\n");
// 使用次数
str.append("使用次数标记 : ");
str.append(m_bTimesFlag ? "" : "");
str.append("\n");
str.append("使用次数 : ");
str.append(std::to_string(m_times));
str.append("\n");
// 高级设置密码
str.append("高级设置密码 : ");
str.append(m_advancePwd);
str.append("\n");
qDebug() << QObject::tr("Origin String : %1").arg(QString::fromStdString(str));
return str;
}
bool Auth::writeFile()
{
// 加密标记字节:
// 位0 | 位1 | 位2 | 位3 | 位4 | 位5 | 位6 | 位7
// 保留 | 加密标记 | 保留 | 1 | 保留 | 1 | 0 | 保留
// 取当前时间的秒,与上 1010 1001即0xA9去除非保留字节然后加上0001 0100
// 获取当前时间的毫秒值与255的余数
unsigned char mSecond = QDateTime::currentDateTime().time().msec() % 255;
// 计算加密标记
// unsigned char a = mSecond & 0xA9;
// unsigned char b = m_isEncrypt ? 0x40 : 0x00;
// unsigned char c = a + b;
// unsigned char d = c + 0x14;
m_encryptFlag = (mSecond & 0xA9) // 去除指定位 1[0]1[0] 1[0][0]1方括号内标记
+ (m_isEncrypt ? 0x40 : 0x00) // 加入加密标记 0[1]00 0000方括号内标记目前仅支持加密
+ (0x14); // 加入其他标记 000[1] 0[1][0]0方括号内的标记
// 加密标记转hex
std::string hexEncryptFlag = Utils::charToHexStr(m_encryptFlag); //Utils::strToHexStr(Utils::charToStr(m_encryptFlag));
qDebug() << QObject::tr("加密标记: %1 , %2 ").arg(QString::fromStdString(hexEncryptFlag)).arg(m_encryptFlag);
// 参数加密 - des
// 获取参数字符串
std::string originStr = getOriginString();
qDebug() << QObject::tr("Origin String : %1").arg(QString::fromStdString(originStr));
// des加密
char strOut[2048];
bool bRet = m_des.Encrypt((char *)originStr.c_str(), (unsigned int)originStr.length(), m_hexDesKey.c_str(), (unsigned char)m_hexDesKey.length(), strOut);
if(!bRet)
{
//QMessageBox::warning(this, "Warning!", tr("加密失败!"), QMessageBox::Ok, QMessageBox::Ok);
return false;
}
// 加密结果转hex
std::string hexOut = Utils::strToHexStr(strOut);
qDebug() << QObject::tr("hex Origin String : %1").arg(QString::fromStdString(hexOut));
// 生成文件内容:加密标记+加密结果
std::string fileContent = "";
fileContent.append(hexEncryptFlag);
fileContent.append(hexOut);
// 写入文件
Utils::writeFile(m_cfgFileName, fileContent);
//QMessageBox::warning(this, "Warning!", tr("write file : %1").arg(QString::fromStdString(fileContent)), QMessageBox::Ok, QMessageBox::Ok);
qDebug() << QObject::tr("writeFile : %1").arg(QString::fromStdString(fileContent));
return true;
}
bool Auth::readFile()
{
// 读取文件
std::ifstream f(m_cfgFileName);
if(!f.good())
{
return false;
}
std::string fileContent = Utils::readFile(m_cfgFileName);
// 获取前两个hex字符为加密标记的hex格式
std::string hexEncryptFlag = fileContent.substr(0, 2);
// 加密标记hex格式转字符
m_encryptFlag = Utils::strToChar(Utils::hexStrToStr(hexEncryptFlag));
qDebug() << QObject::tr("加密标记: %1 , %2 ").arg(QString::fromStdString(hexEncryptFlag)).arg(m_encryptFlag);
if(!checkEncryptFlag())
{
return false;
}
// 获取文件剩余内容参数加密后的hex格式
std::string hexOut = fileContent.substr(2);
qDebug() << QObject::tr("hex Origin String : %1").arg(QString::fromStdString(hexOut));
// hex格式的加密参数转字符串
std::string strOut = Utils::hexStrToStr(hexOut);
// des解密
char strOrigin[2048] = {0};
bool bRet = m_des.Decrypt((char *)strOut.c_str(), (unsigned int)strOut.length(), m_hexDesKey.c_str(), (unsigned char)m_hexDesKey.length(), strOrigin);
if(!bRet)
{
//QMessageBox::warning(this, "Warning!", tr("解密失败"), QMessageBox::Ok, QMessageBox::Ok);
return false;
}
qDebug() << QObject::tr("Origin String : %1").arg(strOrigin);
QStringList strList =QString(strOrigin).split(",");
if(strList.size() < 7)
{
//QMessageBox::warning(this, "Warning!", tr("秘钥文件损坏!"), QMessageBox::Ok, QMessageBox::Ok);
return false;
}
int idx = 0;
setComanyName(strList[idx].toStdString());
idx++;
setProductType(Utils::hexStrToUchar(strList[idx].toStdString()));
idx++;
setPublishDate(strList[idx].toStdString());
idx++;
setDate(strList[idx].toStdString());
idx++;
setTimesFlag(((!strList[idx].isEmpty()) && (strList[idx].toInt() != 0)) ? true : false);
idx++;
setTimes(strList[idx].isEmpty() ? 0 : strList[idx].toInt());
idx++;
setAdvancePwd(Utils::hexStrToStr(strList[idx].toStdString()));
//QMessageBox::warning(this, "Warning!", strMsg, QMessageBox::Ok, QMessageBox::Ok);
qDebug() << QString::fromStdString(toMessage());
return true;
}
bool Auth::checkEncryptFlag()
{
// 0x0[1]0[1] 0[1][0]0方括号内为需要检查的位
unsigned char b1 = m_encryptFlag >> 6 & 0x01;
if(b1 == 0)
{
return false;
}
unsigned char b3 = m_encryptFlag >> 4 & 0x01;
if(b3 == 0)
{
return false;
}
unsigned char b5 = m_encryptFlag >> 2 & 0x01;
if(b5 == 0)
{
return false;
}
unsigned char b6 = m_encryptFlag >> 1 & 0x01;
if(b6 == 1)
{
return false;
}
return true;
}
bool Auth::checkProductType()
{
// m_productType[1,2,4,8]取值范围1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
if(m_productType < 1 || m_productType > 15)
{
return false;
}
return true;
}
bool Auth::checkDate()
{
// 如果设置日期小于发布日期
if(m_publishDate.compare(m_date) > 0)
{
return false;
}
std::string currDate = QDate::currentDate().toString("yyyyMMdd").toStdString();
// 发布日期大于当前日期
if(m_publishDate.compare(currDate) > 0)
{
return false;
}
// 使用期限小于当前日期
if(m_date.compare(currDate) < 0)
{
return false;
}
}
bool Auth::checkTimes()
{
if(m_bTimesFlag)
{
}
return true;
}
// 密码必须有大小写数字和特殊字符长度必须大于等于8
bool Auth::checkAdvancePwd()
{
if(m_advancePwd.empty())
{
return false;
}
if(m_advancePwd.length() < 8)
{
return false;
}
std::string upperCharStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::string lowerCharStr = "abcdefghijklmnopqrstuvwxyz";
std::string digitStr = "0123456789";
std::string specialStr = "!@#$%^&*()_+=-`~[]{}|':;/?<,>.\\\"";
bool bHasUpperChar = false;
bool bHasLowerChar = false;
bool bHasDigit = false;
bool bHasSpecial = false;
// 字符不能超出以上范围
for(int i=0; i<m_advancePwd.length(); i++)
{
bool bUpperChar = (upperCharStr.find(m_advancePwd.at(i)) != std::string::npos);
bool bLowerChar = (lowerCharStr.find(m_advancePwd.at(i)) != std::string::npos);
bool bDigit = (digitStr.find(m_advancePwd.at(i)) != std::string::npos);
bool bSpecial = (specialStr.find(m_advancePwd.at(i)) != std::string::npos);
if(!bUpperChar && !bLowerChar && !bDigit && !bSpecial)
{
return false;
}
if(!bHasUpperChar && bUpperChar) bHasUpperChar = true;
if(!bHasLowerChar && bLowerChar) bHasLowerChar = true;
if(!bHasDigit && bDigit) bHasDigit = true;
if(!bHasSpecial && bSpecial) bHasSpecial = true;
}
if(!bHasUpperChar || !bHasLowerChar || !bHasDigit || !bHasSpecial)
{
return false;
}
return true;
}
bool Auth::bIsValidate()
{
if(!checkEncryptFlag())
{
return false;
}
if(!checkProductType())
{
return false;
}
if(!checkDate())
{
return false;
}
if(!checkTimes())
{
return false;
}
if(!checkAdvancePwd())
{
return false;
}
return true;
}