文件加密工具(源码分享)

来源:互联网 发布:12306购票软件下载 编辑:程序博客网 时间:2024/05/16 08:33

引言:

在开发一款对外发布的软件程序时,难免要用到配置文件,而其中某些数据开发者并不期望用户获知或是修改,通常会对一些配置文件进行加密。一般是用一个批量的加密工具,统一对配置文件进行加密。

考虑到加密、解密的效率及对安全性的需求,选择了最常用的XOR算法,以下是加密工具的源代码:(windows环境下基于XOR算法,带有图形界面的文件批量加密工具)

源代码:

由于XOR算法是直接可逆的,故源代码中略去了部分代码。

EncryptXML.h:

#pragma once#include <vector>#include <atlframe.h>#include <atlwin.h>#include <ShlObj.h>#include "Resource.h"using namespace std;struct encrypt_context{    unsigned char mask[1024];    unsigned int mask_len;};class CEncryptXML : public CDialogImpl<CEncryptXML>, public CUpdateUI<CEncryptXML>,    public CMessageFilter, public CIdleHandler{public:    enum { IDC = IDD_DIALOG1 };    BOOL PreTranslateMessgae(MSG* pMsg)    {        return CWindow::IsDialogMessage(pMsg);    }    BOOL OnIdle()    {        return FALSE;    }    BEGIN_UPDATE_UI_MAP(CEncryptXML)    END_UPDATE_UI_MAP()    BEGIN_MSG_MAP(CEncryptXML)        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)        COMMAND_HANDLER(IDC_BUTTON1, BN_CLICKED, OnBnBrowse)        COMMAND_HANDLER(IDOK, BN_CLICKED, OnBnOk)        COMMAND_HANDLER(IDCANCEL, BN_CLICKED, OnBnCancel)    END_MSG_MAP()public:    //UI code    LRESULT OnInitDialog(UINT, WPARAM, LPRAM, BOOL&);    LRESULT OnBnBrowse(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);    LRESULT OnBnOk(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);    LRESULT OnBnCancel(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);    int ValidPath(const std::wstring& strPath);    //encrypt code.    void CollectFilesByDirectory(const TCHAR* firstroot, const TCHAR* root, const TCHAR* outdir);    BOOL CollectFilesBySingleFile(const TCHAR* fileName, std::wstring& dest);    void CollectDeleteDirectory(const TCHAR* firstroot, const TCHAR* root, const TCHAR* outdir);    void encryptdata(const encrypt_context& ctx, unsigned char* data, size_t pos, size_t len);    BOOL encryptfile(encrypt_context& ectx, const TCHAR* src_file, const TCHAR* dest_file);    BOOL EncryptXML(const TCHAR* fileName, const TCHAR* destPath);    void DoEncrypt(const TCHAR* fileName);private:    std::vector <std::wstring> arSourceFileName; ///< 源文件列表    std::vector <std::wstring> arDestFileNamep; ///< 临时文件列表    std::vector <std::wstring> arEncryptFailedFileName; ///< 加密失败文件列表    std::vector <std::wstring> arDirectoryNeedToBeDeleted; ///< 待删除文件夹列表};


EncryptXML.cpp:

#include "stdafx.h"#include "EncryptXML.h"#include "Resource.h"#include "..\TCommonUtiliLib\common.h"#include <WinBase.h>#include <iostream>#include <Windows.h>CAppModule _Module;int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData){    if (uMsg == BFFM_INITIALIZED)    {        SendMessage(hwnd, BFFM_SETSELECTION, 1, lpData);        return 0;    }    return 0;}std::wstring BrowseForInstallDestination(HWND m_hWnd, const std::wstring& initdir){    BROWSEINFO bi;    bi.hwndOwner = m_hWnd;    bi.pidlRoot = NULL;    bi.pszDisplayName = NULL;    std::wstring title = L"请选择要加密的文件或文件夹:";    bi.lpszTitle = title.c_str();    //bi.ulFlags = 0;    bi.ulFlags = BIF_BROWSEINCLUDEFILES;///< 最初的版本仅支持选定文件夹,后来需要对单个文件进行加密    bi.lpfn = BrowseCallbackProc;    bi.lParam = (LPARAM)initdir.c_str();    bi.Image = 0;    TCHAR installPath[1024];    PIDLIST_ABSOLUTE ret = ::SHBrowseForFolder(&bi);    if (ret == NULL)    {        ZeroMemory(installPath, sizeof installPath);    }    else    {        ::SHGetPathFromIDList(ret, installPath);    }    return installPath;}void CEncryptXML::CollectFilesByDirectory(const TCHAR* firstroot, const TCHAR* root , const TCHAR* outdir){    WIN32_FIND_DATA fd;    THCAR fullname[MAX_PATH + 1];    size_t offset = ::wcslen(firstroot);    ::_stprintf_s(fullname, MAX_PATH + 1, L"%s\\%s", root, L"*.*");    HANDLE hf = ::FindFirstFile(fullname, &fd);    BOOL b = hf != INVALID_HANDLE_VALUE;    while(b)    {        ::_stprintf_s(fullname, MAX_PATH + 1, L"%s\\%s", root, fd.cFileName);        if (!(wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0))        {            if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)            {                CollectFilesByDirectory(firstroot, fullname, outdir);            }            else            {                TCHAR dummy[1024];                TCHAR ext[1024];                TCHAR output_filename[1024];                ::_stprintf_s(output_filename, 1024, L"%s%s", outdir, fullname + offset);                ::_wsplitpath_s(output_filename, dummy, 1024, dummy, 1024, dummy, 1024, ext, 1024);                ///< 过滤后缀名,只对.xml文件加密                if(wcscmp(ext, L".xml") == 0)                {                    arSourceFileName.push_back(fullname);                    arDestFileName.push_back(output_filename);                }            }        }        b = ::FindNextFile(hf, &fd);    }    ::FindClose(hf);}void CEncryptXML::encryptdata(const encrypt_context& ctx, unsigned char* data, size_t pos, size_t len){    size_t i = 0;    while(i < len)    {        *data++ ^= /*省略计算方法*/        i++;    }}BOOL CEncryptXML::encryptfile(encrypt_context& ectx, const TCHAR* src_file, const TCHAR* dest_file){    TCreatePath(dest_file);    FILE* pf;    FILE* pf2;    errno_t err = ::_wfopen_s(&pf, src_file, L"rb");    if(err != 0)    {        return FALSE;    }    err = ::_wfopen_s(&pf2, dest_file, L"wb");    if(err != 0)    {        fclose(pf);        return FALSE;    }    size_t pos = 0;    unsigned char buffer[4096];    while(!feof(pf))    {        size_t readed = ::fread_s(buffer, 4096, 1, 4096, pf);        encryptdata(ectx, buffer, pos, readed);        if(fwrite(buffer, 1, readed, pf2) != readed)        {            fclose(pf);            fclose(pf2);            return FALSE;        }        pos += readed;    }    fclose(pf);    fclose(pf2);    return TRUE;}BOOL CEncryptXML::EncryptXML(const TCHAR* fileName, const TCHAR* destPath){    encrypt_context enc_ctx;    __int64 ilen = TGetFileSize(fileName);    if(ilen <= 0)        return FALSE;    size_t len = (size_t)ilen;    enc_ctx.mask_len = 1024;    enc_ctx.mask[0] =/*省略计算方法*/    for (int i = 1; i < 1024; ++i)        enc_ctx.mask[i] = /*省略计算方法*/    return encryptfile(enc_ctx, fileName, destPath);}LRESULT CEncryptXML::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&){    // center the dialog on the screen    CenterWindow();    // register object for message filtering and idle updates    CMessageLoop* pLoop = _Module.GetMessageLoop();    ATLASSERT(pLoop != NULL);    pLoop->AddMessageFilter(this);    pLoop->AddIdleHandler(this);    return TRUE;}int CEncryptXML::ValidPath(const std::wstring& strPath){    std::wstring s = strPath;    if(s.empty())        return 0;    if(s.find_last_of(L"\\") != s.length() - 1)        s += L"\\";    int ret = TCreatePath2(s.c_str());    //xml files should be in a exist directory.    if(ret == ERROR_FILE_EXISTS || ret == ERROR_ALREADY_EXISTS)        return 1;    return 0;}LRESULT CEncryptXML::OnBnBrowse(WORD, WORD, HWND, BOOL&){    TCHAR intdir[1024];    ZeroMemory(intdir, sizeof intdir);    if(FALSE == SHGetSpecialFolderPath(m_hWnd, intdir, CSIDL_PROGRAM_FILES, TRUE))    {        wcscpy_s<1024>(intdir, L"D:\\");    }    std::wstring result = BrowseForInstallDestination(m_hWnd, intdir);    if(!result.empty())    {        TFixPath(result);        CEDIT edit = GetDlgItem(IDC_EDIT1);        edit.SetWindowText(result.c_str());    }    return 0;}LRESULT CEncryptXML::OnBnOk(WORD, WORD, HWND, BOOL&){    TCHAR dir[1024];    ZeroMemory(dir, sizeof dir);    CEdit edit = GetDlgItem(IDC_EDIT1);    edit.GetWindowtext(dir, 1022);    int ret = ValidPath(std::wstring(dir));    if(ret == 0)    {        MessageBox(L"选择的路径有误!", L"提示", MB_OK);    }    else    {        DoEncrypt(dir);    }    return 0;}LRESULT CEncryptXML::OnBnCancel(WORD, WORD, HWND, BOOL&){    DestoryWindow();    PostQuitMessage(0);    return 0;}void CEncryptXML::DoEncrypt(const TCHAR* fileName){    std::wstring dest = L"";    std::wstring errorStr = L"";    ///< 选择的文件夹    if (PathIsDirectory(fileName))    {        dest = std::wstring(fileName) + L"\\temp";        CollectFilesByDirectory(fileName, fileName, dest.c_str());    }    ///< 选的文件    else    {        if (!CollectFilesBySingleFile(fileName, dest))            return;    }    for (size_t i = 0; i < arSourceFileName.size(); ++i)    {        if (!EncryptXML(arSourceFileName[i].c_str(), arDestFileName[i].c_str()))        {            arEncryptFailedFileName.push_back(arSourceFileName[i]);            ::DeleteFile(arDestFileName[i].c_str());            continue;        }        ///< 文件为只读时,CopyFile会失败        if (!::CopyFile(arDestFileName[i].c_str(), arSourceFileName[i].c_str(), FALSE))        {            arEncryptFailedFileName.push_back(arSourceFileName[i]);            ::DeleteFile(arDestFileName[i].c_str());            continue;        }        if (!::DeleteFile(arDestFileName[i].c_str()))        {            arEncryptFailedFileName.push_back(arSourceFileName[i]);            continue;        }    }    CollectDeleteDirectory(dest.c_str(), dest.c_str(), dest.c_str());    for (size_t i = 0; i <arDirectoryNeedToBeDeleted.size(); ++i)    {        if (!::RemoveDirectory(arDirectoryNeedToBeDeleted[i].c_str()))        {            errStr = arDirectoryNeedToBeDeleted[i] + L"删除失败!";            MessageBox(errorStr.c_str(), L"提示", MB_OK);        }    }    if (!::RemoveDirectory(dest.c_str()))    {        errorStr = dest + L"删除失败!";        MessageBox(errorStr.c_str(), L"提示", MB_OK);    }    if (arEncryptFailedFileName.empty())    {        MessageBox(L"加密成功!", L"提示", MB_OK);    }    else    {        std::wstring errorFileName = L"";        for (size_t i = 0; i < arEncryptFailedFileName.size(); ++i)        {            errorFileName += arEncryptFailedFileName[i];            errorFileName += '\n';        }        errorFileName += L"加密失败!";        MessageBox(errorFileName.c_str(), L"提示", MB_OK);    }    DestroyWindow();    PostQuitMessage(0);}BOOL CEncryptXML::CollectFilesBySingleFile(const TCHAR* fileName, std::wstring& dest){    std::wstring strFileName = fileName;    std::wstring::size_type pos;    std::wstring tempDest;    TCHAR dummy[1024];    TCHAR ext[1024];    pos = strFileName.find_last_of(L"\\");    if (pos == std::wstring::npos)    {        MessageBox(L"解析文件路径失败!", L"提示", MB_OK);        return FALSE;    }    tempDest = strFileName.substr(0, pos);    dest = tempDest + L"\\temp";    size_t offset = ::wcslen(tempDest.c_str());    TCHAR output_filename[1024];    ::_stprintf_s(output_filename, 1024, L"%s%s", dest.c_str(), fileName + offset);    ::_wsplitpath_s(output_filename, dummy, 1024, dummy, 1024, dummy, 1024, ext, 1024);    ///< 过滤后缀名,只对.xml文件加密    if (wcscmp(ext, L".xml") != 0)    {        MessageBox(L"选择的文件不是xml文件,请重新选择。", L"提示", MB_OK);        return FALSE;    }    else    {        arSourceFileName.push_back(fileName);        arDestFileName.push_back(output_filename);    }    return TRUE;}void CEncryptXML::CollectDeleteDirectory(const TCHAR* firstroot, const TCHAR* root, const TCHAR* outdir){    WIN32_FIND_DATA fd;    TCHAR fullname[MAX_PATH + 1];    size_t offset = ::wcslen(firstroot);    ::_stprintf_s(fullname, MAX_PATH + 1, L"%s\\%s", root, L"*.*");    HANDLE hf = ::FindFirstFile(fullname, &fd);    BOOL b = hf != INVALID_HANDLE_VALUE;    while(b)    {        ::_stprintf_s(fullname, MAX_PATH + 1, L"%s\\%s", root, fd.cFileName);        if (!(wcscmp(fd.cFileName, L".") == 0 ||wcscmp(fd.cFileName, L"..") == 0))        {            if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)            {                arDirectoryNeedToBeDeleted.push_back(fullname);                CollectDeleteDirectory(firstroot, fullname, outdir);            }        }        b = ::FindNextFile(hf, &fd);    }    ::FindClose(hf);}int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT){    CMessageLoop theLoop;    _Module.AddMessageLoop(&theLoop);    CEncryptXML dlgMain;    if (dlgMain.Create(NULL) == NULL)    {        ATLTRACE(_T("Main dialog creation failed!\n"));        return 0;    }    dlgMain.ShowWindow(nCmdShow);    dlgMain.CenterWindow();    int nRet = theLoop.Run();    _Module.RemoveMessageLoop();    return nRet;}int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPreInstance*/, LPTSTR lpstrCmdLine, int nCmdShow){    HRESULT hRes = ::CoInitialize(NULL);    ATLASSERT(SUCCEEDED(HRes));    ::DefWindowProc(NULL, 0, 0, 0L);    AtlInitCommonControls(ICC_BAR_CLASSES);    hRes = _Module.Init(NULL, hInstance);    ATLASSERT(SUCCEEDED(hRes));    int nRet = Run(lpstrCmdLine, nCmdShow);    _Module.Term();    ::CoUninitialize();    return nRet;}

最后:

实际使用的过程中,最常导致机密失败的原因便是加密文件选择了“只读”属性,去除只读属性即可。

1 0
原创粉丝点击