| | |
| | | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 |
| | | |
| | | SOURCES += \ |
| | | licensedata.cpp \ |
| | | main.cpp \ |
| | | mainwindow.cpp \ |
| | | qaesencryption.cpp |
| | | qaesencryption.cpp \ |
| | | shortcrypto.cpp \ |
| | | tinyaes.cpp |
| | | |
| | | HEADERS += \ |
| | | aesni-enc-cbc.h \ |
| | | aesni-enc-ecb.h \ |
| | | aesni-key-exp.h \ |
| | | aesni-key-init.h \ |
| | | licensedata.h \ |
| | | mainwindow.h \ |
| | | qaesencryption.h |
| | | qaesencryption.h \ |
| | | shortcrypto.h \ |
| | | tinyaes.h |
| | | |
| | | FORMS += \ |
| | | mainwindow.ui |
| | |
| | | |
| | | bool check_aesni_support() |
| | | { |
| | | unsigned int a,b,c,d; |
| | | cpuid(1, a,b,c,d); |
| | | return (c & 0x2000000); |
| | | // unsigned int a,b,c,d; |
| | | // cpuid(1, a,b,c,d); |
| | | // return (c & 0x2000000); |
| | | // 强制禁用 AES-NI,使用纯软件 AES 实现 |
| | | // 在 MSVC2017 + Qt 5.12.7 环境下,AES-NI 路径存在兼容性问题 |
| | | return false; |
| | | } |
| | | |
| | | __m128i AES_128_ASSIST (__m128i temp1, __m128i temp2) |
| New file |
| | |
| | | #include "licensedata.h" |
| | | #include <QDataStream> |
| | | #include <QtDebug> |
| | | |
| | | LicenseData::LicenseData() |
| | | : productId(0), verMajor(0), verMinor(0), activeState(0) |
| | | { |
| | | } |
| | | |
| | | QByteArray LicenseData::toBinary() const |
| | | { |
| | | QByteArray data; |
| | | data.reserve(64); |
| | | QDataStream stream(&data, QIODevice::WriteOnly); |
| | | stream.setByteOrder(QDataStream::BigEndian); |
| | | |
| | | // 1. 主板UUID:固定16字节 |
| | | QByteArray uuid = boardUuid.left(16); |
| | | uuid.append(QByteArray(16 - uuid.size(), '\0')); |
| | | stream.writeRawData(uuid.constData(), 16); |
| | | |
| | | // 2. CPU序列号:固定8字节 |
| | | QByteArray cpu = cpuSerial.left(8); |
| | | cpu.append(QByteArray(8 - cpu.size(), '\0')); |
| | | stream.writeRawData(cpu.constData(), 8); |
| | | |
| | | // 3. 用户名:长度前缀(1B) + UTF-8数据 |
| | | QByteArray userBytes = userName.toUtf8(); |
| | | if (userBytes.size() > 255) { |
| | | userBytes = userBytes.left(255); |
| | | } |
| | | stream << static_cast<quint8>(userBytes.size()); |
| | | stream.writeRawData(userBytes.constData(), userBytes.size()); |
| | | |
| | | // 4. 失效日期:2字节(距2000-01-01的天数) |
| | | stream << dateToDays(expireDate); |
| | | |
| | | // 5. 产品号:1字节 |
| | | stream << productId; |
| | | |
| | | // 6. 版本号:主版本 + 次版本,各1字节 |
| | | stream << verMajor << verMinor; |
| | | |
| | | // 7. 激活状态:1字节 |
| | | stream << activeState; |
| | | |
| | | return data; |
| | | } |
| | | |
| | | bool LicenseData::fromBinary(const QByteArray &data) |
| | | { |
| | | if (data.size() < 30) { |
| | | qWarning() << "LicenseData::fromBinary: data too short, need at least 30 bytes"; |
| | | return false; |
| | | } |
| | | |
| | | QDataStream stream(data); |
| | | stream.setByteOrder(QDataStream::BigEndian); |
| | | |
| | | // 1. UUID |
| | | boardUuid.resize(16); |
| | | stream.readRawData(boardUuid.data(), 16); |
| | | |
| | | // 2. CPU序列号 |
| | | cpuSerial.resize(8); |
| | | stream.readRawData(cpuSerial.data(), 8); |
| | | |
| | | // 3. 用户名 |
| | | quint8 nameLen = 0; |
| | | stream >> nameLen; |
| | | if (data.size() < 25 + nameLen + 5) { |
| | | qWarning() << "LicenseData::fromBinary: insufficient data for remaining fields"; |
| | | return false; |
| | | } |
| | | QByteArray userBytes(nameLen, '\0'); |
| | | stream.readRawData(userBytes.data(), nameLen); |
| | | userName = QString::fromUtf8(userBytes); |
| | | |
| | | // 4. 日期 |
| | | quint16 days = 0; |
| | | stream >> days; |
| | | expireDate = daysToDate(days); |
| | | |
| | | // 5. 产品号 |
| | | stream >> productId; |
| | | |
| | | // 6. 版本 |
| | | stream >> verMajor >> verMinor; |
| | | |
| | | // 7. 激活状态 |
| | | stream >> activeState; |
| | | |
| | | return true; |
| | | } |
| | | |
| | | QString LicenseData::toDebugString() const |
| | | { |
| | | return QString("{UUID:%1, CPU:%2, User:%3, Expire:%4, Prod:%5, Ver:%6.%7, State:%8}") |
| | | .arg(uuidBinaryToString(boardUuid)) |
| | | .arg(binaryToHexString(cpuSerial)) |
| | | .arg(userName) |
| | | .arg(expireDate.toString("yyyy-MM-dd")) |
| | | .arg(productId) |
| | | .arg(verMajor).arg(verMinor) |
| | | .arg(activeState); |
| | | } |
| | | |
| | | quint16 LicenseData::dateToDays(const QDate &date) const |
| | | { |
| | | QDate base(BASE_YEAR, BASE_MONTH, BASE_DAY); |
| | | if (!date.isValid() || date < base) { |
| | | return 0; |
| | | } |
| | | return static_cast<quint16>(base.daysTo(date)); |
| | | } |
| | | |
| | | QDate LicenseData::daysToDate(quint16 days) const |
| | | { |
| | | QDate base(BASE_YEAR, BASE_MONTH, BASE_DAY); |
| | | return base.addDays(days); |
| | | } |
| | | |
| | | QByteArray LicenseData::uuidStringToBinary(const QString &uuidStr) |
| | | { |
| | | QString clean = uuidStr; |
| | | clean.remove('-'); |
| | | clean.remove('{'); |
| | | clean.remove('}'); |
| | | clean = clean.toUpper(); |
| | | if (clean.size() != 32) { |
| | | return QByteArray(); |
| | | } |
| | | return hexStringToBinary(clean); |
| | | } |
| | | |
| | | QString LicenseData::uuidBinaryToString(const QByteArray &bin) |
| | | { |
| | | if (bin.size() != 16) { |
| | | return QString(); |
| | | } |
| | | QString hex = binaryToHexString(bin); |
| | | return QString("%1-%2-%3-%4-%5") |
| | | .arg(hex.mid(0, 8)) |
| | | .arg(hex.mid(8, 4)) |
| | | .arg(hex.mid(12, 4)) |
| | | .arg(hex.mid(16, 4)) |
| | | .arg(hex.mid(20, 12)); |
| | | } |
| | | |
| | | QByteArray LicenseData::hexStringToBinary(const QString &hexStr) |
| | | { |
| | | QString clean = hexStr; |
| | | clean.remove(' '); |
| | | QByteArray result; |
| | | result.reserve(clean.size() / 2); |
| | | for (int i = 0; i + 1 < clean.size(); i += 2) { |
| | | bool ok; |
| | | result.append(static_cast<char>(clean.mid(i, 2).toUInt(&ok, 16))); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | QString LicenseData::binaryToHexString(const QByteArray &bin) |
| | | { |
| | | return QString::fromLatin1(bin.toHex()).toUpper(); |
| | | } |
| New file |
| | |
| | | #ifndef LICENSEDATA_H |
| | | #define LICENSEDATA_H |
| | | |
| | | #include <QByteArray> |
| | | #include <QString> |
| | | #include <QDate> |
| | | |
| | | /** |
| | | * @brief 许可证数据结构 V2(极致紧凑版) |
| | | * |
| | | * 二进制格式(大端序): |
| | | * [0..15] 16B 主板UUID(原始二进制) |
| | | * [16..23] 8B CPU序列号(原始二进制) |
| | | * [24] 1B 用户名长度N |
| | | * [25..24+N] N B 用户名UTF-8数据 |
| | | * [25+N..26+N] 2B 失效日期(距2000-01-01的天数,uint16) |
| | | * [27+N] 1B 产品号(uint8) |
| | | * [28+N] 1B 主版本号(uint8) |
| | | * [29+N] 1B 次版本号(uint8) |
| | | * [30+N] 1B 激活状态(uint8) |
| | | * |
| | | * 总长度 = 31 + N 字节 |
| | | */ |
| | | struct LicenseData |
| | | { |
| | | QByteArray boardUuid; // 16字节二进制UUID |
| | | QByteArray cpuSerial; // 8字节二进制 |
| | | QString userName; // 用户名 |
| | | QDate expireDate; // 失效日期(仅日期,无时间) |
| | | quint8 productId; // 产品号 |
| | | quint8 verMajor; // 主版本号 |
| | | quint8 verMinor; // 次版本号 |
| | | quint8 activeState; // 激活状态 |
| | | |
| | | LicenseData(); |
| | | |
| | | QByteArray toBinary() const; |
| | | bool fromBinary(const QByteArray &data); |
| | | QString toDebugString() const; |
| | | |
| | | // 辅助转换 |
| | | static QByteArray uuidStringToBinary(const QString &uuidStr); |
| | | static QString uuidBinaryToString(const QByteArray &bin); |
| | | static QByteArray hexStringToBinary(const QString &hexStr); |
| | | static QString binaryToHexString(const QByteArray &bin); |
| | | |
| | | private: |
| | | // 日期基准:2000-01-01,用uint16存天数,范围 2000-01-01 ~ 2182-06-05 |
| | | static constexpr int BASE_YEAR = 2000; |
| | | static constexpr int BASE_MONTH = 1; |
| | | static constexpr int BASE_DAY = 1; |
| | | |
| | | quint16 dateToDays(const QDate &date) const; |
| | | QDate daysToDate(quint16 days) const; |
| | | }; |
| | | |
| | | #endif // LICENSEDATA_H |
| | |
| | | #include "mainwindow.h" |
| | | #include "ui_mainwindow.h" |
| | | #include "qaesencryption.h" |
| | | #include "licensedata.h" |
| | | #include "shortcrypto.h" |
| | | |
| | | #include <QClipboard> |
| | | #include <QDateTime> |
| | |
| | | ui->label_biosnum->setVisible(false); |
| | | ui->label_basenum_2->setVisible(false); |
| | | ui->label_biosnum_2->setVisible(false); |
| | | QTextOption opt = ui->textEdit_localid->document()->defaultTextOption(); |
| | | opt.setWrapMode(QTextOption::WrapAnywhere); |
| | | ui->textEdit_localid->document()->setDefaultTextOption(opt); |
| | | QTextOption opt_lic = ui->textEdit_licensekey->document()->defaultTextOption(); |
| | | opt_lic.setWrapMode(QTextOption::WrapAnywhere); |
| | | ui->textEdit_licensekey->document()->setDefaultTextOption(opt_lic); |
| | | //前七条是简化加密数据必用的,在这里设定好方便对应 |
| | | m_numToInfo.insert("1","Baseboard_Uuid"); |
| | | m_numToInfo.insert("2","CPU_Processorid"); |
| | |
| | | void MainWindow::on_pushButton_decrypt_clicked() |
| | | { |
| | | QString encryptlocalid = ui->textEdit_localid->toPlainText(); |
| | | QString localid = getDecrypt(encryptlocalid,key); |
| | | QByteArray localidbyte = localid.toLocal8Bit(); |
| | | QJsonParseError err_rpt; |
| | | QJsonDocument localidjsondoc(QJsonDocument::fromJson(localid.toUtf8(), &err_rpt));//字符串格式化为JSON |
| | | if(err_rpt.error != QJsonParseError::NoError) |
| | | { |
| | | localinfo = LicenseInfo(); |
| | | licenseinfo = LicenseInfo(); |
| | | workingjsondoc = QJsonDocument(); |
| | | ui->textEdit_licensekey->setPlainText(""); |
| | | changeUIstate(); |
| | | qDebug() << QStringLiteral("localid JSON格式错误"); |
| | | QMessageBox msgbox(QMessageBox::Information,QStringLiteral(""),QStringLiteral("解析失败,不是一个正确的设备ID序列"),QMessageBox::Ok); |
| | | msgbox.setButtonText(QMessageBox::Ok,QStringLiteral("确定")); |
| | | msgbox.exec(); |
| | | } |
| | | else //JSON格式正确 |
| | | { |
| | | QMessageBox msgbox(QMessageBox::Information,QStringLiteral(""),QStringLiteral("解析成功"),QMessageBox::Ok); |
| | | msgbox.setButtonText(QMessageBox::Ok,QStringLiteral("确定")); |
| | | msgbox.exec(); |
| | | ui->textEdit_licensekey->setPlainText(ui->textEdit_localid->toPlainText()); |
| | | workingjsondoc = QJsonDocument(QJsonDocument::fromJson(localidbyte)); |
| | | // 一键解密 |
| | | lic2.fromBinary(ShortCrypto::decrypt(encryptlocalid, key)); |
| | | qDebug()<<"on_pushButton_decrypt_clicked"<<lic2.toDebugString(); |
| | | //与之前的加密对应,且去掉冗余信息 |
| | | localinfo.Baseboard_Uuid = LicenseData::uuidBinaryToString(lic2.boardUuid); |
| | | localinfo.CPU_Processorid = LicenseData::binaryToHexString(lic2.cpuSerial); |
| | | localinfo.Username = lic2.userName; |
| | | localinfo.LicensedDuration_end = lic2.expireDate.toString("yyyy-MM-dd"); |
| | | // localinfo.LicensedDuration_start = localid_Obj.value(m_numToInfo.key("LicensedDuration_start")).toString(); |
| | | localinfo.Productid = QString::number(lic2.productId); |
| | | localinfo.Versionid = QString::number(lic2.verMajor)+"."+QString::number(lic2.verMinor); |
| | | localinfo.ActiveState = static_cast<int>(lic2.activeState); |
| | | licenseinfo = LicenseInfo(localinfo); |
| | | ui->textEdit_licensekey->setPlainText(ui->textEdit_localid->toPlainText()); |
| | | changeUIstate(); |
| | | |
| | | QJsonObject localid_Obj = localidjsondoc.object(); |
| | | // localinfo.Baseboard_Serialnumber = localid_Obj.value("Baseboard_Serialnumber").toString(); |
| | | // localinfo.Baseboard_Uuid = localid_Obj.value("Baseboard_Uuid").toString(); |
| | | // localinfo.Bios_Serialnumber = localid_Obj.value("Bios_Serialnumber").toString(); |
| | | // localinfo.CPU_Processorid = localid_Obj.value("CPU_Processorid").toString(); |
| | | // localinfo.Username = localid_Obj.value("Username").toString(); |
| | | // localinfo.IsEnabled_cell = localid_Obj.value("IsEnabled_cell").toInt(); |
| | | // localinfo.IsEnabled_aquifer = localid_Obj.value("IsEnabled_aquifer").toInt(); |
| | | // localinfo.IsEnabled_pipe = localid_Obj.value("IsEnabled_pipe").toInt(); |
| | | // localinfo.IsEnabled_network = localid_Obj.value("IsEnabled_network").toInt(); |
| | | // localinfo.LicensedDuration_end = localid_Obj.value("LicensedDuration_end").toString(); |
| | | // localinfo.LicensedDuration_start = localid_Obj.value("LicensedDuration_start").toString(); |
| | | // localinfo.Productid = localid_Obj.value("Productid").toString(); |
| | | // localinfo.Versionid = localid_Obj.value("Versionid").toString(); |
| | | // QString localid = getDecrypt(encryptlocalid,key); |
| | | // QByteArray localidbyte = localid.toLocal8Bit(); |
| | | // QJsonParseError err_rpt; |
| | | // QJsonDocument localidjsondoc(QJsonDocument::fromJson(localid.toUtf8(), &err_rpt));//字符串格式化为JSON |
| | | // if(err_rpt.error != QJsonParseError::NoError) |
| | | // { |
| | | // localinfo = LicenseInfo(); |
| | | // licenseinfo = LicenseInfo(); |
| | | // workingjsondoc = QJsonDocument(); |
| | | // ui->textEdit_licensekey->setPlainText(""); |
| | | // changeUIstate(); |
| | | // qDebug() << QStringLiteral("localid JSON格式错误"); |
| | | // QMessageBox msgbox(QMessageBox::Information,QStringLiteral(""),QStringLiteral("解析失败,不是一个正确的设备ID序列"),QMessageBox::Ok); |
| | | // msgbox.setButtonText(QMessageBox::Ok,QStringLiteral("确定")); |
| | | // msgbox.exec(); |
| | | // } |
| | | // else //JSON格式正确 |
| | | // { |
| | | // QMessageBox msgbox(QMessageBox::Information,QStringLiteral(""),QStringLiteral("解析成功"),QMessageBox::Ok); |
| | | // msgbox.setButtonText(QMessageBox::Ok,QStringLiteral("确定")); |
| | | // msgbox.exec(); |
| | | // ui->textEdit_licensekey->setPlainText(ui->textEdit_localid->toPlainText()); |
| | | // workingjsondoc = QJsonDocument(QJsonDocument::fromJson(localidbyte)); |
| | | |
| | | //与之前的加密对应,且去掉冗余信息 |
| | | localinfo.Baseboard_Uuid = localid_Obj.value(m_numToInfo.key("Baseboard_Uuid")).toString(); |
| | | localinfo.CPU_Processorid = localid_Obj.value(m_numToInfo.key("CPU_Processorid")).toString(); |
| | | localinfo.Username = localid_Obj.value(m_numToInfo.key("Username")).toString(); |
| | | localinfo.LicensedDuration_end = localid_Obj.value(m_numToInfo.key("LicensedDuration_end")).toString(); |
| | | localinfo.LicensedDuration_start = localid_Obj.value(m_numToInfo.key("LicensedDuration_start")).toString(); |
| | | localinfo.Productid = localid_Obj.value(m_numToInfo.key("Productid")).toString(); |
| | | localinfo.Versionid = localid_Obj.value(m_numToInfo.key("Versionid")).toString(); |
| | | localinfo.ActiveState = localid_Obj.value(m_numToInfo.key("ActiveState")).toInt(); |
| | | licenseinfo = LicenseInfo(localinfo); |
| | | changeUIstate(); |
| | | } |
| | | // QJsonObject localid_Obj = localidjsondoc.object(); |
| | | //// localinfo.Baseboard_Serialnumber = localid_Obj.value("Baseboard_Serialnumber").toString(); |
| | | //// localinfo.Baseboard_Uuid = localid_Obj.value("Baseboard_Uuid").toString(); |
| | | //// localinfo.Bios_Serialnumber = localid_Obj.value("Bios_Serialnumber").toString(); |
| | | //// localinfo.CPU_Processorid = localid_Obj.value("CPU_Processorid").toString(); |
| | | //// localinfo.Username = localid_Obj.value("Username").toString(); |
| | | //// localinfo.IsEnabled_cell = localid_Obj.value("IsEnabled_cell").toInt(); |
| | | //// localinfo.IsEnabled_aquifer = localid_Obj.value("IsEnabled_aquifer").toInt(); |
| | | //// localinfo.IsEnabled_pipe = localid_Obj.value("IsEnabled_pipe").toInt(); |
| | | //// localinfo.IsEnabled_network = localid_Obj.value("IsEnabled_network").toInt(); |
| | | //// localinfo.LicensedDuration_end = localid_Obj.value("LicensedDuration_end").toString(); |
| | | //// localinfo.LicensedDuration_start = localid_Obj.value("LicensedDuration_start").toString(); |
| | | //// localinfo.Productid = localid_Obj.value("Productid").toString(); |
| | | //// localinfo.Versionid = localid_Obj.value("Versionid").toString(); |
| | | |
| | | // //与之前的加密对应,且去掉冗余信息 |
| | | // localinfo.Baseboard_Uuid = localid_Obj.value(m_numToInfo.key("Baseboard_Uuid")).toString(); |
| | | // localinfo.CPU_Processorid = localid_Obj.value(m_numToInfo.key("CPU_Processorid")).toString(); |
| | | // localinfo.Username = localid_Obj.value(m_numToInfo.key("Username")).toString(); |
| | | // localinfo.LicensedDuration_end = localid_Obj.value(m_numToInfo.key("LicensedDuration_end")).toString(); |
| | | // localinfo.LicensedDuration_start = localid_Obj.value(m_numToInfo.key("LicensedDuration_start")).toString(); |
| | | // localinfo.Productid = localid_Obj.value(m_numToInfo.key("Productid")).toString(); |
| | | // localinfo.Versionid = localid_Obj.value(m_numToInfo.key("Versionid")).toString(); |
| | | // localinfo.ActiveState = localid_Obj.value(m_numToInfo.key("ActiveState")).toInt(); |
| | | // licenseinfo = LicenseInfo(localinfo); |
| | | // changeUIstate(); |
| | | // } |
| | | } |
| | | |
| | | void MainWindow::on_pushButton_accreditall_clicked() |
| | |
| | | |
| | | void MainWindow::giveLicense(int time) |
| | | { |
| | | QJsonObject licensekey_Obj = workingjsondoc.object(); |
| | | // licensekey_Obj[m_numToInfo.key("IsEnabled_cell")] = 1; |
| | | // licensekey_Obj[m_numToInfo.key("IsEnabled_aquifer")] = 1; |
| | | // licensekey_Obj[m_numToInfo.key("IsEnabled_pipe")] = 1; |
| | | // licensekey_Obj[m_numToInfo.key("IsEnabled_network")] = 1; |
| | | licensekey_Obj[m_numToInfo.key("ActiveState")] = 1; |
| | | // QDateTime licensedate = QDateTime::fromString(licensekey_Obj[m_numToInfo.key("LicensedDuration_end")].toString(),"yyyy-MM-dd hh:mm:ss"); |
| | | // if(licensedate.isNull()){ |
| | | // qDebug()<<"licenseTime is Null"; |
| | | // licensedate = QDateTime::currentDateTime(); |
| | | // } |
| | | //现在点击授权是从当前的时间加授权时间 |
| | | QDateTime licensedate = QDateTime::currentDateTime(); |
| | | QDateTime newlicensedate = licensedate.addMonths(time); |
| | | QString licensedatestr = newlicensedate.toString("yyyy-MM-dd hh:mm:ss"); |
| | | licensekey_Obj[m_numToInfo.key("LicensedDuration_start")] = licensedate.toString("yyyy-MM-dd hh:mm:ss"); |
| | | licensekey_Obj[m_numToInfo.key("LicensedDuration_end")] = licensedatestr; |
| | | workingjsondoc.setObject(licensekey_Obj); |
| | | //数据压缩,去空格换行等多余无用信息 |
| | | QByteArray compressedArray = QJsonDocument(licensekey_Obj).toJson(QJsonDocument::Compact); |
| | | QByteArray jsonbytearray = qCompress(compressedArray,9); |
| | | QString testid = jsonbytearray.toBase64(); |
| | | ui->textEdit_licensekey->setPlainText(""); |
| | | ui->textEdit_licensekey->setPlainText(getEncrypt(QString(testid),key)); |
| | | setLicenseinfo(licensekey_Obj); |
| | | QString licensedatestr = newlicensedate.toString("yyyy-MM-dd"); |
| | | lic2.expireDate = QDate::fromString(licensedatestr,"yyyy-MM-dd"); |
| | | // lic2.expireDate = lic2.expireDate.addMonths(time); |
| | | lic2.activeState = 1; |
| | | QString cipher = ShortCrypto::encrypt(lic2.toBinary(), key); |
| | | ui->textEdit_licensekey->clear(); |
| | | ui->textEdit_licensekey->setPlainText(cipher); |
| | | // 一键解密 |
| | | LicenseData lic3; |
| | | lic3.fromBinary(ShortCrypto::decrypt(cipher, key)); |
| | | qDebug()<<"change"<<cipher<<lic3.toDebugString()<<cipher.size(); |
| | | //更新licenseinfo,只需要更新LicensedDuration_end、LicensedDuration_start、ActiveState |
| | | licenseinfo.LicensedDuration_end = newlicensedate.toString("yyyy-MM-dd"); |
| | | licenseinfo.LicensedDuration_start = licensedate.toString("yyyy-MM-dd"); |
| | | licenseinfo.ActiveState = 1; |
| | | changeUIstate(); |
| | | //将授权信息记录到excel表中 |
| | | QString edition =""; |
| | | if(time == 3){ |
| | |
| | | }else if(time == 12){ |
| | | edition = QStringLiteral("专业版"); |
| | | } |
| | | ActiveRecord(licensekey_Obj,edition,ui->textEdit_licensekey->toPlainText()); |
| | | ActiveRecord(lic2,edition,ui->textEdit_licensekey->toPlainText()); |
| | | } |
| | | |
| | | void MainWindow::ActiveRecord(QJsonObject jsonObj,QString edition, QString licenseKey) |
| | | void MainWindow::ActiveRecord(LicenseData lic,QString edition, QString licenseKey) |
| | | { |
| | | QString Baseboard_Uuid = jsonObj[m_numToInfo.key("Baseboard_Uuid")].toString(); |
| | | QString Baseboard_Uuid = LicenseData::uuidBinaryToString(lic.boardUuid); |
| | | QString src = QApplication::applicationDirPath(); |
| | | QDir dir(src); |
| | | QString file_name(QStringLiteral("安全评价软件授权人数统计表.xlsx")); |
| | |
| | | int rowCount = xlsx.dimension().rowCount()+1; |
| | | int id = xlsx.read(rowCount-1,1).toInt(); |
| | | xlsx.write(rowCount, 1, id+1); |
| | | xlsx.write(rowCount, 2, jsonObj[m_numToInfo.key("Baseboard_Uuid")].toString()); |
| | | xlsx.write(rowCount, 2, LicenseData::uuidBinaryToString(lic.boardUuid)); |
| | | xlsx.write(rowCount, 3, edition); |
| | | xlsx.write(rowCount, 4, jsonObj[m_numToInfo.key("LicensedDuration_start")].toString()); |
| | | xlsx.write(rowCount, 5, jsonObj[m_numToInfo.key("LicensedDuration_end")].toString()); |
| | | xlsx.write(rowCount, 6, jsonObj[m_numToInfo.key("Productid")].toString()); |
| | | xlsx.write(rowCount, 7, jsonObj[m_numToInfo.key("Versionid")].toString()); |
| | | xlsx.write(rowCount, 4, QDate::currentDate().toString("yyyy-MM-dd")); |
| | | xlsx.write(rowCount, 5, lic.expireDate.toString("yyyy-MM-dd")); |
| | | xlsx.write(rowCount, 6, QString::number(lic2.productId)); |
| | | xlsx.write(rowCount, 7, QString::number(lic2.verMajor)+"."+QString::number(lic2.verMinor)); |
| | | xlsx.write(rowCount, 8, licenseKey); |
| | | }else{ |
| | | //如果存在这条记录就更新数据信息 |
| | | xlsx.write(uuidColumn, 2, jsonObj[m_numToInfo.key("Baseboard_Uuid")].toString()); |
| | | xlsx.write(uuidColumn, 2, LicenseData::uuidBinaryToString(lic.boardUuid)); |
| | | xlsx.write(uuidColumn, 3, edition); |
| | | xlsx.write(uuidColumn, 4, jsonObj[m_numToInfo.key("LicensedDuration_start")].toString()); |
| | | xlsx.write(uuidColumn, 5, jsonObj[m_numToInfo.key("LicensedDuration_end")].toString()); |
| | | xlsx.write(uuidColumn, 6, jsonObj[m_numToInfo.key("Productid")].toString()); |
| | | xlsx.write(uuidColumn, 7, jsonObj[m_numToInfo.key("Versionid")].toString()); |
| | | xlsx.write(uuidColumn, 4, QDate::currentDate().toString("yyyy-MM-dd")); |
| | | xlsx.write(uuidColumn, 5, lic.expireDate.toString("yyyy-MM-dd")); |
| | | xlsx.write(uuidColumn, 6, QString::number(lic2.productId)); |
| | | xlsx.write(uuidColumn, 7, QString::number(lic2.verMajor)+"."+QString::number(lic2.verMinor)); |
| | | xlsx.write(uuidColumn, 8, licenseKey); |
| | | } |
| | | xlsx.save(); |
| | | } |
| | | |
| | | QString MainWindow::getEncrypt_New() |
| | | { |
| | | QString localid = ""; |
| | | LicenseInfo localinfo; |
| | | //查询系统用户名 |
| | | localinfo.Username = qgetenv("USER"); // Linux系统 |
| | | if (localinfo.Username.isEmpty()) |
| | | localinfo.Username = qgetenv("USERNAME"); // Windows系统 |
| | | //查询CPU序列号 |
| | | localinfo.CPU_Processorid = getWindowsInfo("wmic cpu get processorid"); |
| | | //查询主板序列号 |
| | | localinfo.Baseboard_Serialnumber = getWindowsInfo("wmic baseboard get serialnumber"); |
| | | //查询BIOS序列号 |
| | | localinfo.Bios_Serialnumber = getWindowsInfo("wmic bios get serialnumber"); |
| | | //查询主板唯一标识 |
| | | localinfo.Baseboard_Uuid = getWindowsInfo("wmic csproduct get uuid"); |
| | | |
| | | //尝试新的加密方法 |
| | | LicenseData lic; |
| | | lic.boardUuid = LicenseData::hexStringToBinary(localinfo.Baseboard_Uuid); |
| | | lic.cpuSerial = LicenseData::hexStringToBinary(localinfo.CPU_Processorid); |
| | | lic.userName = localinfo.Username; |
| | | lic.expireDate = QDate::fromString(localinfo.LicensedDuration_end,"yyyy-MM-dd"); |
| | | lic.productId = localinfo.Productid.toUInt(); |
| | | QString version = localinfo.Versionid; |
| | | lic.verMajor = version.split(".").at(0).toUInt(); |
| | | lic.verMinor = version.split(".").at(1).toUInt(); |
| | | lic.activeState = localinfo.ActiveState; |
| | | // 一键加密 |
| | | QString cipher = ShortCrypto::encrypt(lic.toBinary(), key); |
| | | // ui->textEdit_localid->setText(cipher); |
| | | return cipher; |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | QString localid = getLocalID(); |
| | | QString encryptid = getEncrypt(localid,key); |
| | | |
| | | //新的加密方法 |
| | | encryptid = getEncrypt_New(); |
| | | ui->textEdit_localid->setText(encryptid); |
| | | |
| | | localinfo = LicenseInfo(); |
| | |
| | | |
| | | void MainWindow::on_pushButton_setproid_clicked() |
| | | { |
| | | QJsonObject licensekey_Obj = workingjsondoc.object(); |
| | | licensekey_Obj[m_numToInfo.key("Productid")] = ui->lineEdit_setproid->text(); |
| | | workingjsondoc.setObject(licensekey_Obj); |
| | | // QJsonObject licensekey_Obj = workingjsondoc.object(); |
| | | // licensekey_Obj[m_numToInfo.key("Productid")] = ui->lineEdit_setproid->text(); |
| | | // workingjsondoc.setObject(licensekey_Obj); |
| | | |
| | | QByteArray compressedArray = QJsonDocument(licensekey_Obj).toJson(QJsonDocument::Compact); |
| | | QByteArray jsonbytearray = qCompress(compressedArray,9); |
| | | QString testid = jsonbytearray.toBase64(); |
| | | ui->textEdit_licensekey->setPlainText(""); |
| | | ui->textEdit_licensekey->setPlainText(getEncrypt(QString(testid),key)); |
| | | |
| | | // QByteArray jsonbytearray = workingjsondoc.toJson(); |
| | | // QByteArray compressedArray = QJsonDocument(licensekey_Obj).toJson(QJsonDocument::Compact); |
| | | // QByteArray jsonbytearray = qCompress(compressedArray,9); |
| | | // QString testid = jsonbytearray.toBase64(); |
| | | // ui->textEdit_licensekey->setPlainText(""); |
| | | // ui->textEdit_licensekey->setPlainText(getEncrypt(QString(jsonbytearray),key)); |
| | | setLicenseinfo(licensekey_Obj); |
| | | // ui->textEdit_licensekey->setPlainText(getEncrypt(QString(testid),key)); |
| | | |
| | | lic2.productId = ui->lineEdit_setproid->text().toUInt(); |
| | | QString cipher = ShortCrypto::encrypt(lic2.toBinary(), key); |
| | | ui->textEdit_licensekey->setPlainText(cipher); |
| | | // setLicenseinfo(licensekey_Obj); |
| | | |
| | | //這裡也只需要更新productId |
| | | licenseinfo.Productid = ui->lineEdit_setproid->text(); |
| | | changeUIstate(); |
| | | |
| | | } |
| | | |
| | | void MainWindow::on_pushButton_setversion_clicked() |
| | | { |
| | | QJsonObject licensekey_Obj = workingjsondoc.object(); |
| | | licensekey_Obj[m_numToInfo.key("Versionid")] = ui->lineEdit_setversion->text(); |
| | | workingjsondoc.setObject(licensekey_Obj); |
| | | // QJsonObject licensekey_Obj = workingjsondoc.object(); |
| | | // licensekey_Obj[m_numToInfo.key("Versionid")] = ui->lineEdit_setversion->text(); |
| | | // workingjsondoc.setObject(licensekey_Obj); |
| | | |
| | | QByteArray compressedArray = QJsonDocument(licensekey_Obj).toJson(QJsonDocument::Compact); |
| | | QByteArray jsonbytearray = qCompress(compressedArray,9); |
| | | QString testid = jsonbytearray.toBase64(); |
| | | ui->textEdit_licensekey->setPlainText(""); |
| | | ui->textEdit_licensekey->setPlainText(getEncrypt(QString(testid),key)); |
| | | |
| | | // QByteArray jsonbytearray = workingjsondoc.toJson(); |
| | | // QByteArray compressedArray = QJsonDocument(licensekey_Obj).toJson(QJsonDocument::Compact); |
| | | // QByteArray jsonbytearray = qCompress(compressedArray,9); |
| | | // QString testid = jsonbytearray.toBase64(); |
| | | // ui->textEdit_licensekey->setPlainText(""); |
| | | // ui->textEdit_licensekey->setPlainText(getEncrypt(QString(jsonbytearray),key)); |
| | | setLicenseinfo(licensekey_Obj); |
| | | // ui->textEdit_licensekey->setPlainText(getEncrypt(QString(testid),key)); |
| | | |
| | | // setLicenseinfo(licensekey_Obj); |
| | | QString version = ui->lineEdit_setversion->text(); |
| | | lic2.verMajor = version.split(".").at(0).toUInt(); |
| | | lic2.verMinor = version.split(".").at(1).toUInt(); |
| | | QString cipher = ShortCrypto::encrypt(lic2.toBinary(), key); |
| | | ui->textEdit_licensekey->setPlainText(cipher); |
| | | //這裡也只需要更新Versionid |
| | | licenseinfo.Versionid = ui->lineEdit_setversion->text(); |
| | | changeUIstate(); |
| | | } |
| | | |
| | | void MainWindow::on_pushButton_normal_clicked() |
| | |
| | | #ifndef MAINWINDOW_H |
| | | #define MAINWINDOW_H |
| | | |
| | | #include "licensedata.h" |
| | | |
| | | #include <QMainWindow> |
| | | #include <QCryptographicHash> |
| | | #include <QJsonDocument> |
| | |
| | | int IsEnabled_aquifer = 0; |
| | | int IsEnabled_pipe = 0; |
| | | int IsEnabled_network = 0; |
| | | QString LicensedDuration_start = "2023-04-01 12:00:00"; |
| | | QString LicensedDuration_end = "2023-04-01 12:00:00"; |
| | | QString LicensedDuration_start = "2023-04-01"; |
| | | QString LicensedDuration_end = "2023-04-01"; |
| | | QString Productid = "1"; //产品号 (1,3)安全评价软件(2,3)数据库 |
| | | QString Versionid = "1.0.0.0"; //版本号 用于区分大版本,同一个大版本内可用 |
| | | QString Versionid = "2.0"; //版本号 用于区分大版本,同一个大版本内可用 |
| | | } LicenseInfo; |
| | | |
| | | class MainWindow : public QMainWindow |
| | |
| | | |
| | | //授权集中在一起,不同点在于时间 |
| | | void giveLicense(int time); |
| | | void ActiveRecord(QJsonObject jsonObj,QString edition, QString licenseKey); |
| | | void ActiveRecord(LicenseData lic,QString edition, QString licenseKey); |
| | | |
| | | //新的加密方法 |
| | | QString getEncrypt_New(); |
| | | private slots: |
| | | void on_pushButton_decrypt_clicked(); |
| | | |
| | |
| | | |
| | | QJsonDocument workingjsondoc; |
| | | |
| | | QString key = "9aFUEFjsqHsde4DOhirdskgdznSDHlfb0ae"; |
| | | LicenseData lic2; |
| | | QByteArray key = "MySecretKey12345"; |
| | | |
| | | // QString key = "9aFUEFjsqHsde4DOhirdskgdznSDHlfb0ae"; |
| | | // QByteArray key = "MySecretKey12345"; // 16字节密钥 |
| | | |
| | | QMap<QString,QString> m_numToInfo; |
| | | }; |
| | |
| | | <layout class="QGridLayout" name="gridLayout_3"> |
| | | <item row="0" column="0"> |
| | | <layout class="QGridLayout" name="gridLayout_2"> |
| | | <item row="0" column="1" rowspan="2" colspan="3"> |
| | | <widget class="QTextEdit" name="textEdit_licensekey"> |
| | | <property name="readOnly"> |
| | | <bool>true</bool> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="2" column="3"> |
| | | <widget class="QPushButton" name="pushButton_copykey"> |
| | | <property name="text"> |
| | | <string>复制密钥</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="1" column="0"> |
| | | <spacer name="verticalSpacer_2"> |
| | | <property name="orientation"> |
| | | <enum>Qt::Vertical</enum> |
| | | </property> |
| | | <property name="sizeHint" stdset="0"> |
| | | <size> |
| | | <width>20</width> |
| | | <height>40</height> |
| | | </size> |
| | | </property> |
| | | </spacer> |
| | | </item> |
| | | <item row="2" column="1"> |
| | | <spacer name="horizontalSpacer_2"> |
| | | <property name="orientation"> |
| | |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="0" column="1" rowspan="2" colspan="3"> |
| | | <widget class="QTextEdit" name="textEdit_licensekey"> |
| | | <property name="lineWrapMode"> |
| | | <enum>QTextEdit::WidgetWidth</enum> |
| | | </property> |
| | | <property name="readOnly"> |
| | | <bool>true</bool> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="2" column="2"> |
| | | <widget class="QPushButton" name="pushButton_export"> |
| | | <property name="text"> |
| | | <string>导出文本</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="1" column="0"> |
| | | <spacer name="verticalSpacer_2"> |
| | | <property name="orientation"> |
| | | <enum>Qt::Vertical</enum> |
| | | </property> |
| | | <property name="sizeHint" stdset="0"> |
| | | <size> |
| | | <width>20</width> |
| | | <height>40</height> |
| | | </size> |
| | | </property> |
| | | </spacer> |
| | | </item> |
| | | <item row="2" column="3"> |
| | | <widget class="QPushButton" name="pushButton_copykey"> |
| | | <property name="text"> |
| | | <string>复制密钥</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | |
| | | </item> |
| | | <item row="2" column="0"> |
| | | <layout class="QGridLayout" name="gridLayout_6"> |
| | | <item row="5" column="0"> |
| | | <widget class="QPushButton" name="pushButton_setproid"> |
| | | <item row="3" column="0"> |
| | | <widget class="QPushButton" name="pushButton_deaccreditall"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>设置产品号</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="3" column="1"> |
| | | <widget class="QPushButton" name="pushButton_accreditpipe"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>授权单裂隙</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="4" column="1"> |
| | | <widget class="QPushButton" name="pushButton_adddate"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>+1个月</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="1" column="0"> |
| | | <widget class="QPushButton" name="pushButton_normal"> |
| | | <property name="text"> |
| | | <string>授权普通版</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="2" column="0"> |
| | | <widget class="QPushButton" name="pushButton_accreditall"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>授权所有模块</string> |
| | | <string>解除所有授权</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="2" column="2"> |
| | | <widget class="QPushButton" name="pushButton_accreditaquifer"> |
| | | <item row="4" column="1"> |
| | | <widget class="QPushButton" name="pushButton_adddate"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>授权含水通道</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="3" column="0"> |
| | | <widget class="QPushButton" name="pushButton_deaccreditall"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>解除所有授权</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="6" column="1" colspan="2"> |
| | | <widget class="QLineEdit" name="lineEdit_setversion"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="5" column="1" colspan="2"> |
| | | <widget class="QLineEdit" name="lineEdit_setproid"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="1" column="1"> |
| | | <widget class="QPushButton" name="pushButton_education"> |
| | | <property name="text"> |
| | | <string>授权教育版</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="0" column="2"> |
| | | <widget class="QPushButton" name="pushButton"> |
| | | <property name="text"> |
| | | <string>详细信息>></string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="6" column="0"> |
| | | <widget class="QPushButton" name="pushButton_setversion"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>设置版本</string> |
| | | <string>+1个月</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="2" column="1"> |
| | | <widget class="QPushButton" name="pushButton_accreditcell"> |
| | | <item row="1" column="0"> |
| | | <widget class="QPushButton" name="pushButton_normal"> |
| | | <property name="text"> |
| | | <string>授权普通版</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="5" column="1" colspan="2"> |
| | | <widget class="QLineEdit" name="lineEdit_setproid"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="3" column="1"> |
| | | <widget class="QPushButton" name="pushButton_accreditpipe"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>授权孔隙单元</string> |
| | | <string>授权单裂隙</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="6" column="1" colspan="2"> |
| | | <widget class="QLineEdit" name="lineEdit_setversion"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="4" column="0"> |
| | | <widget class="QPushButton" name="pushButton_dateset"> |
| | | <item row="2" column="0"> |
| | | <widget class="QPushButton" name="pushButton_accreditall"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>时间同步</string> |
| | | <string>授权所有模块</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="5" column="0"> |
| | | <widget class="QPushButton" name="pushButton_setproid"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>设置产品号</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="6" column="0"> |
| | | <widget class="QPushButton" name="pushButton_setversion"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>设置版本</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="0" column="2"> |
| | | <widget class="QPushButton" name="pushButton"> |
| | | <property name="text"> |
| | | <string>详细信息>></string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | |
| | | <widget class="QPushButton" name="pushButton_viewUsers"> |
| | | <property name="text"> |
| | | <string>查看已激活用户</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="2" column="2"> |
| | | <widget class="QPushButton" name="pushButton_accreditaquifer"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>授权含水通道</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="2" column="1"> |
| | | <widget class="QPushButton" name="pushButton_accreditcell"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>授权孔隙单元</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="1" column="1"> |
| | | <widget class="QPushButton" name="pushButton_education"> |
| | | <property name="text"> |
| | | <string>授权教育版</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | | <item row="4" column="0"> |
| | | <widget class="QPushButton" name="pushButton_dateset"> |
| | | <property name="enabled"> |
| | | <bool>false</bool> |
| | | </property> |
| | | <property name="text"> |
| | | <string>时间同步</string> |
| | | </property> |
| | | </widget> |
| | | </item> |
| | |
| | | </item> |
| | | <item row="0" column="1" rowspan="2" colspan="6"> |
| | | <widget class="QTextEdit" name="textEdit_localid"> |
| | | <property name="lineWrapMode"> |
| | | <enum>QTextEdit::WidgetWidth</enum> |
| | | </property> |
| | | <property name="readOnly"> |
| | | <bool>false</bool> |
| | | </property> |
| New file |
| | |
| | | #include "shortcrypto.h" |
| | | #include "tinyaes.h" |
| | | #include <QtDebug> |
| | | |
| | | // Base85 字符集:85个可打印字符,避开容易在URL/JSON里出问题的字符 |
| | | const char *ShortCrypto::BASE85_CHARS = |
| | | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; |
| | | |
| | | namespace { |
| | | QByteArray pkcs7Pad(const QByteArray &data, int blockSize) { |
| | | int padLen = blockSize - (data.size() % blockSize); |
| | | if (padLen == 0) padLen = blockSize; |
| | | QByteArray result = data; |
| | | result.append(QByteArray(padLen, static_cast<char>(padLen))); |
| | | return result; |
| | | } |
| | | |
| | | bool isPkcs7Valid(const QByteArray &data, int blockSize = 16) { |
| | | if (data.isEmpty() || data.size() % blockSize != 0) return false; |
| | | unsigned char padLen = static_cast<unsigned char>(data.at(data.size() - 1)); |
| | | if (padLen == 0 || padLen > static_cast<unsigned char>(blockSize)) return false; |
| | | for (int i = 0; i < padLen; ++i) |
| | | if (static_cast<unsigned char>(data.at(data.size() - 1 - i)) != padLen) return false; |
| | | return true; |
| | | } |
| | | |
| | | QByteArray pkcs7Unpad(const QByteArray &data) { |
| | | if (data.isEmpty()) return QByteArray(); |
| | | unsigned char padLen = static_cast<unsigned char>(data.at(data.size() - 1)); |
| | | if (padLen == 0 || padLen > 16 || padLen > static_cast<unsigned char>(data.size())) return QByteArray(); |
| | | return data.left(data.size() - padLen); |
| | | } |
| | | } |
| | | |
| | | QString ShortCrypto::encrypt(const QByteArray &plaintext, const QByteArray &key, const QByteArray &iv) |
| | | { |
| | | if (key.size() != 16) { |
| | | qWarning() << "ShortCrypto::encrypt: key must be 16 bytes for AES-128"; |
| | | return QString(); |
| | | } |
| | | |
| | | QByteArray adjustedIv = iv; |
| | | if (adjustedIv.isEmpty()) { |
| | | adjustedIv = QByteArray(16, '\0'); // 默认全零IV(正式环境建议用随机IV并附带在密文前) |
| | | } else if (adjustedIv.size() != 16) { |
| | | adjustedIv = adjustedIv.left(16); |
| | | adjustedIv.append(QByteArray(16 - adjustedIv.size(), '\0')); |
| | | } |
| | | |
| | | // 1. PKCS7 填充 |
| | | QByteArray padded = pkcs7Pad(plaintext, 16); |
| | | |
| | | // 2. AES-128-CBC 加密(使用 Tiny-AES-C,纯软件实现,无 MSVC 兼容性问题) |
| | | QByteArray encrypted = padded; |
| | | struct AES_ctx ctx; |
| | | AES_init_ctx_iv(&ctx, reinterpret_cast<const uint8_t*>(key.constData()), |
| | | reinterpret_cast<const uint8_t*>(adjustedIv.constData())); |
| | | AES_CBC_encrypt_buffer(&ctx, reinterpret_cast<uint8_t*>(encrypted.data()), encrypted.size()); |
| | | |
| | | // 3. Base85 编码,缩短字符数 |
| | | QByteArray encoded = base85Encode(encrypted); |
| | | return QString::fromLatin1(encoded); |
| | | } |
| | | |
| | | QByteArray ShortCrypto::decrypt(const QString &ciphertext, const QByteArray &key, const QByteArray &iv) |
| | | { |
| | | if (key.size() != 16) { |
| | | qWarning() << "ShortCrypto::decrypt: key must be 16 bytes for AES-128"; |
| | | return QByteArray(); |
| | | } |
| | | |
| | | QByteArray adjustedIv = iv; |
| | | if (adjustedIv.isEmpty()) { |
| | | adjustedIv = QByteArray(16, '\0'); |
| | | } else if (adjustedIv.size() != 16) { |
| | | adjustedIv = adjustedIv.left(16); |
| | | adjustedIv.append(QByteArray(16 - adjustedIv.size(), '\0')); |
| | | } |
| | | |
| | | // 1. Base85 解码 |
| | | QByteArray encrypted = base85Decode(ciphertext); |
| | | if (encrypted.isEmpty()) { |
| | | qWarning() << "ShortCrypto::decrypt: base85 decode failed"; |
| | | return QByteArray(); |
| | | } |
| | | |
| | | if (encrypted.size() % 16 != 0) { |
| | | qWarning() << "ShortCrypto::decrypt: decoded data size not aligned to block size:" << encrypted.size(); |
| | | return QByteArray(); |
| | | } |
| | | |
| | | // 2. AES-128-CBC 解密 |
| | | QByteArray decrypted = encrypted; |
| | | struct AES_ctx ctx; |
| | | AES_init_ctx_iv(&ctx, reinterpret_cast<const uint8_t*>(key.constData()), |
| | | reinterpret_cast<const uint8_t*>(adjustedIv.constData())); |
| | | AES_CBC_decrypt_buffer(&ctx, reinterpret_cast<uint8_t*>(decrypted.data()), decrypted.size()); |
| | | |
| | | // 3. PKCS7 验证和移除填充 |
| | | if (!isPkcs7Valid(decrypted)) { |
| | | qWarning() << "ShortCrypto::decrypt: PKCS7 validation failed, wrong key or corrupted data"; |
| | | return QByteArray(); |
| | | } |
| | | |
| | | return pkcs7Unpad(decrypted); |
| | | } |
| | | |
| | | QByteArray ShortCrypto::base85Encode(const QByteArray &data) |
| | | { |
| | | QByteArray result; |
| | | result.reserve((data.size() + 3) / 4 * 5); |
| | | |
| | | const unsigned char *ptr = reinterpret_cast<const unsigned char *>(data.constData()); |
| | | int len = data.size(); |
| | | |
| | | while (len >= 4) { |
| | | quint32 val = (quint32(ptr[0]) << 24) | (quint32(ptr[1]) << 16) | |
| | | (quint32(ptr[2]) << 8) | quint32(ptr[3]); |
| | | char buf[5]; |
| | | for (int i = 4; i >= 0; --i) { |
| | | buf[i] = BASE85_CHARS[val % 85]; |
| | | val /= 85; |
| | | } |
| | | result.append(buf, 5); |
| | | ptr += 4; |
| | | len -= 4; |
| | | } |
| | | |
| | | // 处理剩余字节(1~3字节) |
| | | if (len > 0) { |
| | | quint32 val = 0; |
| | | for (int i = 0; i < len; ++i) { |
| | | val |= (quint32(ptr[i]) << (24 - i * 8)); |
| | | } |
| | | char buf[5]; |
| | | for (int i = 4; i >= 0; --i) { |
| | | buf[i] = BASE85_CHARS[val % 85]; |
| | | val /= 85; |
| | | } |
| | | result.append(buf, len + 1); // n字节需要n+1个字符表示 |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | QByteArray ShortCrypto::base85Decode(const QString &text) |
| | | { |
| | | QByteArray input = text.toLatin1(); |
| | | QByteArray result; |
| | | result.reserve(input.size() / 5 * 4); |
| | | |
| | | // 构建反向查找表 |
| | | int charToVal[256]; |
| | | memset(charToVal, -1, sizeof(charToVal)); |
| | | for (int i = 0; i < 85; ++i) { |
| | | charToVal[static_cast<unsigned char>(BASE85_CHARS[i])] = i; |
| | | } |
| | | |
| | | const unsigned char *ptr = reinterpret_cast<const unsigned char *>(input.constData()); |
| | | int len = input.size(); |
| | | int pos = 0; |
| | | |
| | | while (pos < len) { |
| | | // 读取一个5字符块(或末尾的短块) |
| | | int chunkLen = qMin(5, len - pos); |
| | | quint32 val = 0; |
| | | for (int i = 0; i < chunkLen; ++i) { |
| | | int v = charToVal[ptr[pos + i]]; |
| | | if (v < 0) { |
| | | qWarning() << "ShortCrypto::base85Decode: invalid character:" << QChar(ptr[pos + i]); |
| | | return QByteArray(); |
| | | } |
| | | val = val * 85 + v; |
| | | } |
| | | |
| | | if (chunkLen == 5) { |
| | | result.append(static_cast<char>((val >> 24) & 0xFF)); |
| | | result.append(static_cast<char>((val >> 16) & 0xFF)); |
| | | result.append(static_cast<char>((val >> 8) & 0xFF)); |
| | | result.append(static_cast<char>(val & 0xFF)); |
| | | } else { |
| | | // 末尾短块:用 'u'(84) 填充到 5 个字符,再解码 |
| | | for (int i = chunkLen; i < 5; ++i) |
| | | val = val * 85 + 84; |
| | | |
| | | char out[4]; |
| | | out[0] = static_cast<char>((val >> 24) & 0xFF); |
| | | out[1] = static_cast<char>((val >> 16) & 0xFF); |
| | | out[2] = static_cast<char>((val >> 8) & 0xFF); |
| | | out[3] = static_cast<char>(val & 0xFF); |
| | | |
| | | int outBytes = chunkLen - 1; |
| | | for (int i = 0; i < outBytes; ++i) |
| | | result.append(out[i]); |
| | | } |
| | | pos += chunkLen; |
| | | } |
| | | |
| | | return result; |
| | | } |
| New file |
| | |
| | | #ifndef SHORTCRYPTO_H |
| | | #define SHORTCRYPTO_H |
| | | |
| | | #include <QByteArray> |
| | | #include <QString> |
| | | |
| | | /** |
| | | * @brief 最短密文加密工具类 |
| | | * 流程:明文 → PKCS7填充 → AES-128-CBC加密 → Base85编码 |
| | | */ |
| | | class ShortCrypto |
| | | { |
| | | public: |
| | | /** |
| | | * @brief 加密 |
| | | * @param plaintext 原始明文 |
| | | * @param key 16字节密钥(AES-128) |
| | | * @param iv 16字节初始向量,可为空(内部自动补零) |
| | | * @return Base85编码的密文字符串 |
| | | */ |
| | | static QString encrypt(const QByteArray &plaintext, const QByteArray &key, const QByteArray &iv = QByteArray()); |
| | | |
| | | /** |
| | | * @brief 解密 |
| | | * @param ciphertext Base85编码的密文 |
| | | * @param key 16字节密钥(AES-128) |
| | | * @param iv 16字节初始向量,必须与加密时一致 |
| | | * @return 原始明文 |
| | | */ |
| | | static QByteArray decrypt(const QString &ciphertext, const QByteArray &key, const QByteArray &iv = QByteArray()); |
| | | |
| | | private: |
| | | // Base85 字符集(RFC 1924 变体,不含引号/逗号/句点/斜杠,避免JSON/XML转义问题) |
| | | static const char *BASE85_CHARS; |
| | | |
| | | static QByteArray base85Encode(const QByteArray &data); |
| | | static QByteArray base85Decode(const QString &text); |
| | | }; |
| | | |
| | | #endif // SHORTCRYPTO_H |
| New file |
| | |
| | | #include "tinyaes.h" |
| | | #include <string.h> |
| | | |
| | | #define Nb 4 |
| | | #define Nk 4 |
| | | #define Nr 10 |
| | | |
| | | typedef uint8_t state_t[4][4]; |
| | | |
| | | static const uint8_t sbox[256] = { |
| | | 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, |
| | | 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, |
| | | 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, |
| | | 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, |
| | | 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, |
| | | 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, |
| | | 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, |
| | | 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, |
| | | 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, |
| | | 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, |
| | | 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, |
| | | 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, |
| | | 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, |
| | | 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, |
| | | 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, |
| | | 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16 |
| | | }; |
| | | |
| | | static const uint8_t rsbox[256] = { |
| | | 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, |
| | | 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, |
| | | 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, |
| | | 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, |
| | | 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, |
| | | 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, |
| | | 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, |
| | | 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, |
| | | 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, |
| | | 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, |
| | | 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, |
| | | 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, |
| | | 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, |
| | | 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, |
| | | 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, |
| | | 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d |
| | | }; |
| | | |
| | | static const uint8_t Rcon[11] = { |
| | | 0x8d,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36 |
| | | }; |
| | | |
| | | #define getSBoxValue(num) (sbox[(num)]) |
| | | |
| | | static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) |
| | | { |
| | | unsigned i, j, k; |
| | | uint8_t tempa[4]; |
| | | for (i = 0; i < Nk; ++i) { |
| | | RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; |
| | | RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; |
| | | RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; |
| | | RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; |
| | | } |
| | | for (i = Nk; i < Nb * (Nr + 1); ++i) { |
| | | k = (i - 1) * 4; |
| | | tempa[0]=RoundKey[k + 0]; |
| | | tempa[1]=RoundKey[k + 1]; |
| | | tempa[2]=RoundKey[k + 2]; |
| | | tempa[3]=RoundKey[k + 3]; |
| | | if (i % Nk == 0) { |
| | | const uint8_t u8tmp = tempa[0]; |
| | | tempa[0] = tempa[1]; |
| | | tempa[1] = tempa[2]; |
| | | tempa[2] = tempa[3]; |
| | | tempa[3] = u8tmp; |
| | | tempa[0] = getSBoxValue(tempa[0]); |
| | | tempa[1] = getSBoxValue(tempa[1]); |
| | | tempa[2] = getSBoxValue(tempa[2]); |
| | | tempa[3] = getSBoxValue(tempa[3]); |
| | | tempa[0] = tempa[0] ^ Rcon[i/Nk]; |
| | | } |
| | | j = i * 4; k=(i - Nk) * 4; |
| | | RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; |
| | | RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; |
| | | RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; |
| | | RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; |
| | | } |
| | | } |
| | | |
| | | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) |
| | | { |
| | | KeyExpansion(ctx->RoundKey, key); |
| | | memcpy(ctx->Iv, iv, AES_BLOCKLEN); |
| | | } |
| | | |
| | | static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) |
| | | { |
| | | uint8_t i,j; |
| | | for (i = 0; i < 4; ++i) |
| | | for (j = 0; j < 4; ++j) |
| | | (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; |
| | | } |
| | | |
| | | static void SubBytes(state_t* state) |
| | | { |
| | | uint8_t i, j; |
| | | for (i = 0; i < 4; ++i) |
| | | for (j = 0; j < 4; ++j) |
| | | (*state)[j][i] = getSBoxValue((*state)[j][i]); |
| | | } |
| | | |
| | | static void ShiftRows(state_t* state) |
| | | { |
| | | uint8_t temp; |
| | | temp = (*state)[0][1]; |
| | | (*state)[0][1] = (*state)[1][1]; |
| | | (*state)[1][1] = (*state)[2][1]; |
| | | (*state)[2][1] = (*state)[3][1]; |
| | | (*state)[3][1] = temp; |
| | | temp = (*state)[0][2]; |
| | | (*state)[0][2] = (*state)[2][2]; |
| | | (*state)[2][2] = temp; |
| | | temp = (*state)[1][2]; |
| | | (*state)[1][2] = (*state)[3][2]; |
| | | (*state)[3][2] = temp; |
| | | temp = (*state)[0][3]; |
| | | (*state)[0][3] = (*state)[3][3]; |
| | | (*state)[3][3] = (*state)[2][3]; |
| | | (*state)[2][3] = (*state)[1][3]; |
| | | (*state)[1][3] = temp; |
| | | } |
| | | |
| | | static uint8_t xtime(uint8_t x) |
| | | { |
| | | return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); |
| | | } |
| | | |
| | | static void MixColumns(state_t* state) |
| | | { |
| | | uint8_t i; |
| | | uint8_t Tmp, Tm, t; |
| | | for (i = 0; i < 4; ++i) { |
| | | t = (*state)[i][0]; |
| | | Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3]; |
| | | Tm = (*state)[i][0] ^ (*state)[i][1]; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp; |
| | | Tm = (*state)[i][1] ^ (*state)[i][2]; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp; |
| | | Tm = (*state)[i][2] ^ (*state)[i][3]; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp; |
| | | Tm = (*state)[i][3] ^ t; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp; |
| | | } |
| | | } |
| | | |
| | | static uint8_t Multiply(uint8_t x, uint8_t y) |
| | | { |
| | | return (((y & 1) * x) ^ |
| | | ((y>>1 & 1) * xtime(x)) ^ |
| | | ((y>>2 & 1) * xtime(xtime(x))) ^ |
| | | ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ |
| | | ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); |
| | | } |
| | | |
| | | static void InvMixColumns(state_t* state) |
| | | { |
| | | int i; |
| | | uint8_t a, b, c, d; |
| | | for (i = 0; i < 4; ++i) { |
| | | a = (*state)[i][0]; |
| | | b = (*state)[i][1]; |
| | | c = (*state)[i][2]; |
| | | d = (*state)[i][3]; |
| | | (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); |
| | | (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); |
| | | (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); |
| | | (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); |
| | | } |
| | | } |
| | | |
| | | static void InvSubBytes(state_t* state) |
| | | { |
| | | uint8_t i, j; |
| | | for (i = 0; i < 4; ++i) |
| | | for (j = 0; j < 4; ++j) |
| | | (*state)[j][i] = rsbox[(*state)[j][i]]; |
| | | } |
| | | |
| | | static void InvShiftRows(state_t* state) |
| | | { |
| | | uint8_t temp; |
| | | temp = (*state)[3][1]; |
| | | (*state)[3][1] = (*state)[2][1]; |
| | | (*state)[2][1] = (*state)[1][1]; |
| | | (*state)[1][1] = (*state)[0][1]; |
| | | (*state)[0][1] = temp; |
| | | temp = (*state)[0][2]; |
| | | (*state)[0][2] = (*state)[2][2]; |
| | | (*state)[2][2] = temp; |
| | | temp = (*state)[1][2]; |
| | | (*state)[1][2] = (*state)[3][2]; |
| | | (*state)[3][2] = temp; |
| | | temp = (*state)[0][3]; |
| | | (*state)[0][3] = (*state)[1][3]; |
| | | (*state)[1][3] = (*state)[2][3]; |
| | | (*state)[2][3] = (*state)[3][3]; |
| | | (*state)[3][3] = temp; |
| | | } |
| | | |
| | | static void Cipher(state_t* state, const uint8_t* RoundKey) |
| | | { |
| | | uint8_t round = 0; |
| | | AddRoundKey(0, state, RoundKey); |
| | | for (round = 1; ; ++round) { |
| | | SubBytes(state); |
| | | ShiftRows(state); |
| | | if (round == Nr) break; |
| | | MixColumns(state); |
| | | AddRoundKey(round, state, RoundKey); |
| | | } |
| | | AddRoundKey(Nr, state, RoundKey); |
| | | } |
| | | |
| | | static void InvCipher(state_t* state, const uint8_t* RoundKey) |
| | | { |
| | | uint8_t round = 0; |
| | | AddRoundKey(Nr, state, RoundKey); |
| | | for (round = (Nr - 1); ; --round) { |
| | | InvShiftRows(state); |
| | | InvSubBytes(state); |
| | | AddRoundKey(round, state, RoundKey); |
| | | if (round == 0) break; |
| | | InvMixColumns(state); |
| | | } |
| | | } |
| | | |
| | | static void XorWithIv(uint8_t* buf, const uint8_t* Iv) |
| | | { |
| | | uint8_t i; |
| | | for (i = 0; i < AES_BLOCKLEN; ++i) |
| | | buf[i] ^= Iv[i]; |
| | | } |
| | | |
| | | void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) |
| | | { |
| | | size_t i; |
| | | uint8_t* Iv = ctx->Iv; |
| | | for (i = 0; i < length; i += AES_BLOCKLEN) { |
| | | XorWithIv(buf, Iv); |
| | | Cipher((state_t*)buf, ctx->RoundKey); |
| | | Iv = buf; |
| | | buf += AES_BLOCKLEN; |
| | | } |
| | | memcpy(ctx->Iv, Iv, AES_BLOCKLEN); |
| | | } |
| | | |
| | | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) |
| | | { |
| | | size_t i; |
| | | uint8_t storeNextIv[AES_BLOCKLEN]; |
| | | for (i = 0; i < length; i += AES_BLOCKLEN) { |
| | | memcpy(storeNextIv, buf, AES_BLOCKLEN); |
| | | InvCipher((state_t*)buf, ctx->RoundKey); |
| | | XorWithIv(buf, ctx->Iv); |
| | | memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); |
| | | buf += AES_BLOCKLEN; |
| | | } |
| | | } |
| New file |
| | |
| | | #ifndef TINYAES_H |
| | | #define TINYAES_H |
| | | |
| | | #include <stdint.h> |
| | | #include <stddef.h> |
| | | |
| | | #define AES_BLOCKLEN 16 |
| | | #define AES_KEYLEN 16 |
| | | #define AES_keyExpSize 176 |
| | | |
| | | struct AES_ctx |
| | | { |
| | | uint8_t RoundKey[AES_keyExpSize]; |
| | | uint8_t Iv[AES_BLOCKLEN]; |
| | | }; |
| | | |
| | | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); |
| | | void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); |
| | | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); |
| | | |
| | | #endif // TINYAES_H |