Почему CryptDecrypt возвращает NTE_BAD_DATA? - PullRequest
0 голосов
/ 14 января 2020

Хочу создать реализацию AES-CB C. Я создал этот код:

процесс шифрования:

#include "windows.h"
#include "stdio.h"
#include <string>

#pragma comment (lib, "crypt32.lib")

HCRYPTKEY hKey;
HCRYPTPROV hProv;

std::string message;

unsigned char* key;
DWORD keylen;
unsigned char* iv;
DWORD ivlen;

int Acquire() {
    if (!CryptAcquireContext(&hProv, "rsa1", NULL, PROV_RSA_AES, 0)) {
        ExitProcess(0);
    }
}

void GenKey()
{
    if (!CryptGenKey(hProv, CALG_AES_256, CRYPT_EXPORTABLE, &hKey))
    {
        printf("%d\n", GetLastError());
        ExitProcess(1);
    }

    if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, NULL, &keylen))
    {
        ExitProcess(2);
    }

    key = new unsigned char[keylen];

    if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, key, &keylen))
    {
        ExitProcess(3);
    }

    CryptDestroyKey(hKey);
}

void GenIV()
{
    HCRYPTKEY hKey;

    if (!CryptGenKey(hProv, CALG_AES_256, CRYPT_EXPORTABLE, &hKey))
    {
        ExitProcess(4);
    }

    if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, NULL, &ivlen))
    {
        ExitProcess(5);
    }

    iv = new unsigned char[ivlen];

    if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, iv, &ivlen))
    {
        ExitProcess(6);
    }

    CryptDestroyKey(hKey);
}

void WriteOutPut(std::wstring filePath, unsigned char* data, int len) {
    HANDLE hFile;
    DWORD dwBytesRead, dwBytesWritten, dwPos;

    if (hFile = CreateFileW(filePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL))
    {
        WriteFile(hFile, data, len, &dwBytesWritten, NULL);
        CloseHandle(hFile);
    }
}

unsigned char* ReadOutPut(std::wstring filePath) {
    HANDLE hFile;
    DWORD dwBytesRead, dwBytesWritten, dwPos;

    if (hFile = CreateFileW(filePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL))
    {
        LARGE_INTEGER size;
        GetFileSizeEx(hFile, &size);

        unsigned char* buffer = new unsigned char[size.QuadPart];

        ReadFile(hFile, buffer, size.QuadPart, &dwBytesRead, NULL);
        CloseHandle(hFile);

        return buffer;
    }
}

void EncryptBuffer() {
    HANDLE hFile;
    DWORD dwBytesRead, dwBytesWritten, dwPos;

    if (hFile = CreateFileW(L"1.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL))
    {
        LARGE_INTEGER size;
        GetFileSizeEx(hFile, &size);

        unsigned char* buffer = new unsigned char[size.QuadPart];
        DWORD len = size.QuadPart;
        DWORD lenpad = size.QuadPart + 16;

        ReadFile(hFile, buffer, size.QuadPart, &dwBytesRead, NULL);
        CloseHandle(hFile);

        if (!CryptImportKey(hProv, key, keylen, NULL, 0, &hKey))
        {
            ExitProcess(0);
        }

        DWORD padding = PKCS5_PADDING;
        DWORD mode = CRYPT_MODE_CBC;

        CryptSetKeyParam(hKey, KP_IV, iv, 0);
        CryptSetKeyParam(hKey, KP_PADDING, (BYTE*)&padding, 0);
        CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&mode, 0);

        if (!CryptEncrypt(hKey, NULL, TRUE, 0, buffer, &len, lenpad)) {
            printf("%d\n", GetLastError());
        }

        WriteOutPut(L"key.txt", key, keylen);
        WriteOutPut(L"iv.txt", iv, ivlen);
        WriteOutPut(L"data.txt", buffer, size.QuadPart);
    }
}

int main() 
{
    Acquire();
    GenKey();
    GenIV();
    EncryptBuffer();
}

и процесс расшифровки:

#include "windows.h"
#include "stdio.h"
#include <string>

#pragma comment (lib, "crypt32.lib")

HCRYPTKEY hKey;
HCRYPTPROV hProv;

unsigned char* key;
DWORD keylen;
unsigned char* iv;
DWORD ivlen;

void Acquire() {
    if (!CryptAcquireContext(&hProv, "rsa1", NULL, PROV_RSA_AES, 0)) {
        ExitProcess(0);
    }
}

void ReadKey() {
    HANDLE hFile;
    DWORD dwBytesRead, dwBytesWritten, dwPos;

    if (hFile = CreateFileW(L"key.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL))
    {
        LARGE_INTEGER size;
        GetFileSizeEx(hFile, &size);

        key = new unsigned char[size.QuadPart];
        keylen = size.QuadPart;

        ReadFile(hFile, key, size.QuadPart, &dwBytesRead, NULL);
        CloseHandle(hFile);
    }
}

void ReadIV() {
    HANDLE hFile;
    DWORD dwBytesRead, dwBytesWritten, dwPos;

    if (hFile = CreateFileW(L"iv.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL))
    {
        LARGE_INTEGER size;
        GetFileSizeEx(hFile, &size);

        iv = new unsigned char[size.QuadPart];
        ivlen = size.QuadPart;

        ReadFile(hFile, iv, size.QuadPart, &dwBytesRead, NULL);
        CloseHandle(hFile);
    }
}

void DecryptData() {
    HANDLE hFile;
    DWORD dwBytesRead, dwBytesWritten, dwPos;

    if (hFile = CreateFileW(L"buffer.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL))
    {
        LARGE_INTEGER size;
        GetFileSizeEx(hFile, &size);

        unsigned char* buffer = new unsigned char[16];
        DWORD len = 16;

        ReadFile(hFile, buffer, size.QuadPart, &dwBytesRead, NULL);
        CloseHandle(hFile);

        if (!CryptImportKey(hProv, key, keylen, NULL, 0, &hKey))
        {
            ExitProcess(0);
        }

        DWORD padding = PKCS5_PADDING;
        DWORD mode = CRYPT_MODE_CBC;

        CryptSetKeyParam(hKey, KP_IV, iv, 0);
        CryptSetKeyParam(hKey, KP_PADDING, (BYTE*)&padding, 0);
        CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&mode, 0);

        if (!CryptDecrypt(hKey, NULL, TRUE, 0, buffer, &len)) {
            printf("%d\n", GetLastError());
        }

        for (int i = 0; i < len; i++) {
            printf("%c", buffer[i]);
        }
    }
}

int main()
{
    Acquire();
    ReadKey();
    ReadIV();

    for (int i = 0; i < keylen; i++) {
        printf("%c", key[i]);
    }
    printf("\n");
    for (int i = 0; i < ivlen; i++) {
        printf("%c", iv[i]);
    }
    printf("\n");

    DecryptData();
}

Но когда я пытаюсь расшифровать данные, у меня возникает ошибка NTE_BAD_DATA во время CryptDecrypt() Я попробовал все, но мне ничего не помогло ... Если я расшифровываю при шифровании - это нормально, но в двух разных проектах это не работает Почему?

...