bool KxPdfMainWindow::DocPromptDecrypt(QString NameOfFile)
{
Crypt::KEY k;
k.Secret = 0x12;
k.Sig = (LPBYTE)"\x11\x22\x33\x44";
k.SizeOfSig = 4;
return Crypt::DecodeFile((LPCTSTR)NameOfFile.toLocal8Bit(), &k);
}
void KxPdfMainWindow::UniversalDeCrypt(QString filename)
{
QFileInfo backupFileInfo(filename);
QString backfilePath = backupFileInfo.path();
QString fileDecrypt(backfilePath + QDir::separator() + "temp.pdf");
QFile file(filename);
if(!file.open(QIODevice::ReadWrite))
return;
QFile defile(fileDecrypt);
QByteArray ba = QByteArray::fromBase64(file.readAll());
file.close();
while (file.remove()){}
if(defile.open(QIODevice::WriteOnly))
defile.write(ba);
defile.close();
defile.rename(fileDecrypt, filename);
}
//这是代码中调用解密的部分
//使用了增值功能的文档写到到了一个state.txt中,并且设置了文件的隐藏
QString stateFile(backupPath + QDir::separator() + "state.txt");
QFile fileRecordState(stateFile);
for(int i = 0 ; i < string_list.count(); i++)
{
if(DocPromptDecrypt(string_list.at(i)))
{
if(fileRecordState.open(QIODevice::WriteOnly|QIODevice::Append))
{
QFileInfo enFileInfo(string_list.at(i));
QString str = enFileInfo.completeBaseName() + ";";
QTextStream fileOut(&fileRecordState);
fileOut << str;
fileRecordState.flush();
fileRecordState.close();
}
SetFileAttributes((LPCSTR)stateFile.toLocal8Bit(),FILE_ATTRIBUTE_HIDDEN);
}
//调用加密部分
UniversalEnCrypt(m_filename);
//如果使用了增值功能需要特殊加密
if (m_backupFile->isFileNeedEncrypt())
DocPromptEncrypt(m_filename);
//加密接口部分:
void KPdfBackupTask::DocPromptEncrypt(QString NameOfFile)
{
Crypt::KEY k;
k.Secret = 0x12;
k.Sig = (LPBYTE)"\x11\x22\x33\x44";
k.SizeOfSig = 4;
Crypt::EncodeFile((LPCTSTR)NameOfFile.toLocal8Bit(), &k); //这个地方QString转LPCTSTR找了好久的,真是坑我不浅啊
}
void KPdfBackupTask::UniversalEnCrypt(QString filename)
{
QFile original(filename);
if(!original.open(QIODevice::ReadOnly))
return;
QByteArray ba = original.readAll().toBase64();
original.close();
original.open(QIODevice::ReadOnly);
QTextStream io(&original);
original.close();
original.open(QIODevice::Truncate);
original.close();
original.open(QIODevice::WriteOnly);
io<<"";
original.close();
if(!original.open(QIODevice::WriteOnly))
return;
original.write(ba);
original.close();
}
//加密实现部分单独写到了一个头文件中
#pragma once
#include "../../dialog/kxpdfmetrostyledialog.h"
#include <kso/framework/api/pdf.h>
#include <QEvent>
#include <QVector>
#include <QQueue>
#include <memory>
#include <tchar.h>
#include <WTypes.h>
#include <algorithm>
#include <functional>
#include <type_traits>
namespace Crypt
{
using std::min;
using std::bind;
using std::function;
using std::remove_cv;
using std::unique_ptr;
using std::remove_pointer;
using namespace std::placeholders;
typedef struct {
UCHAR Secret;
LPBYTE Sig;
DWORD SizeOfSig;
} KEY, *PKEY;
template< typename _Ty >
BOOL IsEmptyString(_Ty &&psz) /* _NOEXCEPT */ { return !psz || !*psz; }
template< typename _Ty >
struct Ptr : public unique_ptr < _Ty, function< VOID(typename remove_cv< _Ty>::type *) > >
{
template< typename _Pty > Ptr(_Pty &&_Ptr)
: unique_ptr < _Ty, function< VOID(typename remove_cv< _Ty>::type *) > >(
std::forward< _Pty&&>(_Ptr),
[](typename remove_cv< _Ty >::type *h) { if (h && h != INVALID_HANDLE_VALUE) CloseHandle(h); })
{
}
};
namespace Impl /* 内部实现,不要直接调用 */
{
static BOOL IsEncoded(_In_ HANDLE h, _In_ DWORD SizeOfFile, _In_ __readonly KEY *Key)
{
if (Key->SizeOfSig > SizeOfFile)
return FALSE;
if (SetFilePointer(h, SizeOfFile - Key->SizeOfSig, NULL, FILE_BEGIN) ==
INVALID_SET_FILE_POINTER)
return FALSE;
unique_ptr< BYTE, function< BOOL(PVOID)>>
p((LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Key->SizeOfSig),
bind(HeapFree, GetProcessHeap(), IGNORE, _1));
if (!p)
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
DWORD Readed = 0;
if (!ReadFile(h, p.get(), Key->SizeOfSig, &Readed, NULL) ||
Key->SizeOfSig != Readed)
return FALSE;
SetLastError(ERROR_SUCCESS);
return !memcmp(p.get(), Key->Sig, Key->SizeOfSig);
}
// 注:
// 此函数只承诺满足基本异常安全等级。若函数失败,文件的其中一部分可能已被修改。
template< typename _Fn >
BOOL Xor(_In_ HANDLE h, _In_ DWORD SizeOfFile, _In_ __readonly KEY *Key, _Fn &&_Func)
{
DWORD Readed = 0;
BYTE Buffer[BUFSIZ] = { 0 };
while (SizeOfFile)
{
if (!ReadFile(h, Buffer, min((DWORD)sizeof(Buffer), SizeOfFile), &Readed, NULL))
return FALSE;
SizeOfFile -= Readed;
for (DWORD i = 0; i < Readed; ++i)
Buffer[i] ^= Key->Secret;
if (SetFilePointer(h, 0 - Readed, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
return FALSE;
DWORD dw = 0;
while (Readed)
{
if (!WriteFile(h, Buffer, Readed, &dw, NULL))
return FALSE;
Readed -= dw;
}
}
return _Func(h, Key->Secret, Key->Sig, Key->SizeOfSig);
}
}
/*
IsEncoded
检查一个文件是否已被使用 KEY 对象编码过。
参数:
NameOfFile,被检查的文件。
Key,测试在文件上的 KEY 对象。
返回值:
已被编码返回非零值,否则返回零。
注:
若函数返回零且 GetLastError 不为 ERROR_SUCCESS 表示检查失败,而非文件未被编码。
*/
static BOOL IsEncoded(_In_z_ LPCTSTR NameOfFile, _In_ __readonly KEY *Key )
{
if (IsEmptyString( NameOfFile ) || !Key )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
Ptr< typename remove_pointer< HANDLE >::type > h(
CreateFile(NameOfFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
if (h.get() == INVALID_HANDLE_VALUE)
return GetLastError();
CONST DWORD SizeOfFile = GetFileSize(h.get(), NULL);
if (SizeOfFile == INVALID_FILE_SIZE)
return GetLastError();
return Impl::IsEncoded(h.get(), SizeOfFile, Key);
}
static BOOL EncodeFile(_In_z_ LPCTSTR NameOfFile, _In_ __readonly KEY *Key )
{
Ptr< typename remove_pointer< HANDLE >::type > h(
CreateFile(NameOfFile, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
if (h.get() == INVALID_HANDLE_VALUE)
return FALSE;
DWORD SizeOfFile = GetFileSize(h.get(), NULL);
if (SizeOfFile == INVALID_FILE_SIZE)
return FALSE;
if (Impl::IsEncoded(h.get(), SizeOfFile, Key) ||
GetLastError() != ERROR_SUCCESS)
return TRUE; // 文件已被编码,或没能检测到文件是否已被编码
if (SetFilePointer(h.get(), 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return FALSE;
DWORD Written = 0;
return Impl::Xor(h.get(), SizeOfFile, Key,
bind(WriteFile, _1, _3, _4, &Written, (LPOVERLAPPED)NULL));
}
static _Check_return_ BOOL DecodeFile(_In_z_ LPCTSTR NameOfFile, _In_ __readonly KEY *Key)
{
Ptr< typename remove_pointer< HANDLE >::type >
h(CreateFile(NameOfFile, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL) );
if (h.get() == INVALID_HANDLE_VALUE)
return FALSE;
DWORD SizeOfFile = GetFileSize(h.get(), NULL);
if (SizeOfFile == INVALID_FILE_SIZE)
return FALSE;
if (!Impl::IsEncoded(h.get(), SizeOfFile, Key))
return FALSE; // 文件没被编码
if (SetFilePointer(h.get(), 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return FALSE;
DWORD Written = 0;
return Impl::X