Как создать защищенный паролем ZIP-файл в Windows, используя C? - PullRequest
0 голосов
/ 10 марта 2020

Я пытаюсь создать защищенный ZIP в Windows файле в C.

Я создал следующий подход на основе этих ответов:

  1. Создание ZIP-файла в Windows (XP / 2003) в C / C ++ # 1
  2. Создание ZIP-файла в Windows (XP / 2003) в C / C ++ # 2

Вот код:

#include <windows.h>
#include <shldisp.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <shellapi.h>
#include <stdlib.h>
#include <objbase.h>

int main(int argc, TCHAR* argv[])
{
    DWORD strlen = 0;
    char szFrom[] = "C:\\Users\\dist",
        szTo[] = "C:\\Users\\harrison4\\Desktop\\example.zip";
    HRESULT hResult;
    IShellDispatch *pISD;
    Folder* pToFolder = NULL;
    VARIANT vDir, vFile, vOpt;
    BSTR strptr1, strptr2;

    FILE* f;
    fopen_s(&f, szTo, "wb");
    if (!f)
        return 0;

    fwrite("\x50\x4B\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 22, 1, f);
    fclose(f);

    CoInitialize(NULL);

    hResult = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, &IID_IShellDispatch, (void**)&pISD);

    if (SUCCEEDED(hResult) && pISD != NULL)
    {
        strlen = MultiByteToWideChar(CP_ACP, 0, szTo, -1, 0, 0);
        strptr1 = SysAllocStringLen(0, strlen);
        MultiByteToWideChar(CP_ACP, 0, szTo, -1, strptr1, strlen);

        VariantInit(&vDir);
        vDir.vt = VT_BSTR;
        vDir.bstrVal = strptr1;
        hResult = pISD->NameSpace(vDir, &pToFolder);

        if (SUCCEEDED(hResult))
        {
            strlen = MultiByteToWideChar(CP_ACP, 0, szFrom, -1, 0, 0);
            strptr2 = SysAllocStringLen(0, strlen);
            MultiByteToWideChar(CP_ACP, 0, szFrom, -1, strptr2, strlen);

            VariantInit(&vFile);
            vFile.vt = VT_BSTR;
            vFile.bstrVal = strptr2;

            VariantInit(&vOpt);
            vOpt.vt = VT_I4;
            vOpt.lVal = 4;          // Do not display a progress dialog box

            printf("Copying %s to %s ...\n", szFrom, szTo);
            hResult = pToFolder->CopyHere(vFile, vOpt); //NOTE: this appears to always return S_OK even on error
            /*
             * 1) Enumerate current threads in the process using Thread32First/Thread32Next
             * 2) Start the operation
             * 3) Enumerate the threads again
             * 4) Wait for any new threads using WaitForMultipleObjects
             *
             * Of course, if the operation creates any new threads that don't exit, then you have a problem.
             */
            if (hResult == S_OK) {
                //NOTE: hard-coded for testing - be sure not to overflow the array if > 5 threads exist
                HANDLE hThrd[5];
                HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);  //TH32CS_SNAPMODULE, 0);
                DWORD NUM_THREADS = 0;
                if (h != INVALID_HANDLE_VALUE) {
                    THREADENTRY32 te;
                    te.dwSize = sizeof(te);
                    if (Thread32First(h, &te)) {
                        do {
                            if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))) {
                                //only enumerate threads that are called by this process and not the main thread
                                if ((te.th32OwnerProcessID == GetCurrentProcessId()) && (te.th32ThreadID != GetCurrentThreadId())) {
                                    //printf("Process 0x%04x Thread 0x%04x\n", te.th32OwnerProcessID, te.th32ThreadID);
                                    hThrd[NUM_THREADS] = OpenThread(SYNCHRONIZE, FALSE, te.th32ThreadID);
                                    NUM_THREADS++;
                                }
                            }
                            te.dwSize = sizeof(te);
                        } while (Thread32Next(h, &te));
                    }
                    CloseHandle(h);

                    printf("waiting for all threads to exit...\n");
                    //Wait for all threads to exit
                    WaitForMultipleObjects(NUM_THREADS, hThrd, TRUE, INFINITE);

                    //Close All handles
                    for (DWORD i = 0; i < NUM_THREADS; i++) {
                        CloseHandle(hThrd[i]);
                    }
                } //if invalid handle
            } //if CopyHere() hResult is S_OK

            SysFreeString(strptr2);
            pToFolder->Release();
        }

        SysFreeString(strptr1);
        pISD->Release();
    }

    CoUninitialize();

    printf("Press ENTER to exit\n");
    getchar();
    return 0;

}

Это работает. Тем не менее, я не могу найти никакой документации, чтобы установить пароль для файла.

Я также нашел zip C библиотека , которая облегчает создание ZIP, но к сожалению, он не включает защиту паролем.

Ответы [ 2 ]

4 голосов
/ 16 марта 2020

Вы можете использовать minizip library на Windows. Его можно скомпилировать с помощью CMake.

Вот как вы можете использовать его для создания защищенного паролем zip-файла:

#include "mz.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_buf.h"
#include "mz_strm_split.h"
#include "mz_zip.h"
#include "mz_zip_rw.h"
#include <stdio.h>

int main() {
    void *writer = NULL;
    int32_t err = MZ_OK;

    mz_zip_writer_create(&writer);
    mz_zip_writer_set_password(writer, "mypassword");
    mz_zip_writer_set_compress_method(writer, MZ_COMPRESS_METHOD_DEFLATE);
    mz_zip_writer_set_compress_level(writer, MZ_COMPRESS_LEVEL_DEFAULT);
    err = mz_zip_writer_open_file(writer, "output.zip", 0, 0);
    if (err != MZ_OK) {
        printf("Could not open zip file for writing.");
        return 1;
    }
    err = mz_zip_writer_add_path(writer, "text1.txt", NULL, 0, 0);
    if (err != MZ_OK) {
        printf("Failed to add file to the archive.");
    }
    mz_zip_writer_close(writer);
    mz_zip_writer_delete(&writer);
    return 0;
}

Этот код создаст файл output.zip с паролем -защищенный файл text1.txt.

Для получения дополнительной информации и использования см. пример файла . c.

Надеюсь, это поможет.

0 голосов
/ 18 марта 2020

Если вам строго не нужен формат .zip и вы можете использовать внешние инструменты, вот простой способ: -

Вы можете использовать внешние программы, такие как https://www.aescrypt.com/. Загрузите его, поместите исполняемый файл в ту же папку, что и ваша c программа, а затем, когда вы захотите зашифровать файл, выполните системный вызов, используя

system("aescrypt -e -p apples picture.jpg") 

(код из официальной документации): https://www.aescrypt.com/documentation/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...