202 lines
6.7 KiB
C++
202 lines
6.7 KiB
C++
|
|
#include <QCoreApplication>
|
|||
|
|
#include <QCommandLineParser>
|
|||
|
|
#include <QFile>
|
|||
|
|
#include <QFileInfo>
|
|||
|
|
#include <QDir>
|
|||
|
|
#include <QTextStream>
|
|||
|
|
#include <iostream>
|
|||
|
|
#include "ConfigEncryption.h"
|
|||
|
|
|
|||
|
|
// 打印到控制台(支持中文)
|
|||
|
|
void printConsole(const QString& message)
|
|||
|
|
{
|
|||
|
|
#ifdef _WIN32
|
|||
|
|
// Windows 控制台输出
|
|||
|
|
std::wcout << message.toStdWString() << std::endl;
|
|||
|
|
#else
|
|||
|
|
std::cout << message.toStdString() << std::endl;
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int main(int argc, char *argv[])
|
|||
|
|
{
|
|||
|
|
QCoreApplication app(argc, argv);
|
|||
|
|
app.setApplicationName("ConfigDecryptor");
|
|||
|
|
app.setApplicationVersion("1.0.0");
|
|||
|
|
|
|||
|
|
// 设置控制台输出编码(Windows)
|
|||
|
|
#ifdef _WIN32
|
|||
|
|
system("chcp 65001 > nul");
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
// 命令行参数解析
|
|||
|
|
QCommandLineParser parser;
|
|||
|
|
parser.setApplicationDescription("配置文件解密工具 - 用于解密 config.encrypt 文件");
|
|||
|
|
parser.addHelpOption();
|
|||
|
|
parser.addVersionOption();
|
|||
|
|
|
|||
|
|
// 添加位置参数:加密文件路径
|
|||
|
|
parser.addPositionalArgument("file", "要解密的 config.encrypt 文件路径");
|
|||
|
|
|
|||
|
|
// 添加密钥选项
|
|||
|
|
QCommandLineOption keyOption(QStringList() << "k" << "key",
|
|||
|
|
"解密密钥(格式:AppName + VisionRobot)",
|
|||
|
|
"key");
|
|||
|
|
parser.addOption(keyOption);
|
|||
|
|
|
|||
|
|
// 添加输出路径选项(可选)
|
|||
|
|
QCommandLineOption outputOption(QStringList() << "o" << "output",
|
|||
|
|
"输出文件路径(默认:与加密文件同级目录下的 config.xml)",
|
|||
|
|
"output");
|
|||
|
|
parser.addOption(outputOption);
|
|||
|
|
|
|||
|
|
// 添加静默模式选项
|
|||
|
|
QCommandLineOption silentOption(QStringList() << "s" << "silent",
|
|||
|
|
"静默模式(不显示详细信息)");
|
|||
|
|
parser.addOption(silentOption);
|
|||
|
|
|
|||
|
|
// 解析命令行参数
|
|||
|
|
parser.process(app);
|
|||
|
|
|
|||
|
|
bool silent = parser.isSet(silentOption);
|
|||
|
|
|
|||
|
|
// 显示欢迎信息
|
|||
|
|
if (!silent) {
|
|||
|
|
printConsole("========================================");
|
|||
|
|
printConsole(" 配置文件解密工具 v1.0.0");
|
|||
|
|
printConsole(" Config Decryptor for VisionRobot");
|
|||
|
|
printConsole("========================================");
|
|||
|
|
printConsole("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取位置参数
|
|||
|
|
QStringList args = parser.positionalArguments();
|
|||
|
|
if (args.isEmpty()) {
|
|||
|
|
printConsole("错误:未指定要解密的文件路径");
|
|||
|
|
printConsole("");
|
|||
|
|
parser.showHelp(1);
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QString encryptedFilePath = args.at(0);
|
|||
|
|
|
|||
|
|
// 检查文件是否存在
|
|||
|
|
QFileInfo fileInfo(encryptedFilePath);
|
|||
|
|
if (!fileInfo.exists()) {
|
|||
|
|
printConsole(QString("错误:文件不存在: %1").arg(encryptedFilePath));
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!fileInfo.isFile()) {
|
|||
|
|
printConsole(QString("错误:指定的路径不是文件: %1").arg(encryptedFilePath));
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取密钥
|
|||
|
|
QString key = parser.value(keyOption);
|
|||
|
|
if (key.isEmpty()) {
|
|||
|
|
printConsole("错误:未指定解密密钥");
|
|||
|
|
printConsole("请使用 -k 或 --key 选项指定密钥");
|
|||
|
|
printConsole("密钥格式:应用程序名称 + \"VisionRobot\"");
|
|||
|
|
printConsole("");
|
|||
|
|
printConsole("示例:");
|
|||
|
|
printConsole(" GrabBagApp 的密钥为: GrabBagAppVisionRobot");
|
|||
|
|
printConsole(" LapWeldApp 的密钥为: LapWeldAppVisionRobot");
|
|||
|
|
printConsole("");
|
|||
|
|
parser.showHelp(1);
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 确定输出路径
|
|||
|
|
QString outputFilePath;
|
|||
|
|
if (parser.isSet(outputOption)) {
|
|||
|
|
outputFilePath = parser.value(outputOption);
|
|||
|
|
} else {
|
|||
|
|
// 默认输出到同级目录下的 config.xml
|
|||
|
|
QDir fileDir = fileInfo.absoluteDir();
|
|||
|
|
outputFilePath = fileDir.absoluteFilePath("config.xml");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!silent) {
|
|||
|
|
printConsole(QString("加密文件: %1").arg(fileInfo.absoluteFilePath()));
|
|||
|
|
printConsole(QString("输出文件: %1").arg(outputFilePath));
|
|||
|
|
printConsole(QString("解密密钥: %1").arg(key));
|
|||
|
|
printConsole("");
|
|||
|
|
printConsole("开始解密...");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 读取加密文件
|
|||
|
|
QFile encryptedFile(encryptedFilePath);
|
|||
|
|
if (!encryptedFile.open(QIODevice::ReadOnly)) {
|
|||
|
|
printConsole(QString("错误:无法打开加密文件: %1").arg(encryptedFilePath));
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QByteArray encryptedData = encryptedFile.readAll();
|
|||
|
|
encryptedFile.close();
|
|||
|
|
|
|||
|
|
if (encryptedData.isEmpty()) {
|
|||
|
|
printConsole("错误:加密文件为空");
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证文件格式
|
|||
|
|
if (!encryptedData.startsWith("VRENC1.0")) {
|
|||
|
|
printConsole("警告:文件格式不匹配,可能不是有效的加密配置文件");
|
|||
|
|
printConsole("是否继续尝试解密?(Y/N)");
|
|||
|
|
|
|||
|
|
char response;
|
|||
|
|
std::cin >> response;
|
|||
|
|
if (response != 'Y' && response != 'y') {
|
|||
|
|
printConsole("操作已取消");
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解密数据
|
|||
|
|
QByteArray decryptedData = ConfigEncryption::DecryptConfig(encryptedData, key);
|
|||
|
|
|
|||
|
|
if (decryptedData.isEmpty()) {
|
|||
|
|
printConsole("错误:解密失败!");
|
|||
|
|
printConsole("可能的原因:");
|
|||
|
|
printConsole(" 1. 密钥错误");
|
|||
|
|
printConsole(" 2. 文件已损坏");
|
|||
|
|
printConsole(" 3. 文件格式不正确");
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 写入解密后的文件
|
|||
|
|
QFile outputFile(outputFilePath);
|
|||
|
|
if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
|||
|
|
printConsole(QString("错误:无法创建输出文件: %1").arg(outputFilePath));
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
qint64 written = outputFile.write(decryptedData);
|
|||
|
|
outputFile.close();
|
|||
|
|
|
|||
|
|
if (written != decryptedData.size()) {
|
|||
|
|
printConsole("错误:写入输出文件失败");
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 成功
|
|||
|
|
if (!silent) {
|
|||
|
|
printConsole("");
|
|||
|
|
printConsole("========================================");
|
|||
|
|
printConsole(" 解密成功!");
|
|||
|
|
printConsole("========================================");
|
|||
|
|
printConsole(QString("解密后的文件已保存到: %1").arg(outputFilePath));
|
|||
|
|
printConsole(QString("文件大小: %1 字节").arg(decryptedData.size()));
|
|||
|
|
printConsole("");
|
|||
|
|
printConsole("提示:");
|
|||
|
|
printConsole(" 修改配置后,重新启动应用程序将自动重新加密配置文件。");
|
|||
|
|
printConsole(" 原始加密文件将被更新,config.xml 将被删除。");
|
|||
|
|
printConsole("");
|
|||
|
|
} else {
|
|||
|
|
printConsole("解密成功");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|