3

I have this program working that encrypts a string of 9 bytes using AES128 from wincrypt.h but something strange happens when I change last character of the key:

from L"3igcZhRdWq96m3GUmTAiv2" to for example L"3igcZhRdWq96m3GUmTAiv1" or L"3igcZhRdWq96m3GUmTAiv9" the encrypted texts are still the same as each other.

#include <Windows.h>
#include <wincrypt.h>
#include <stdio.h>
#pragma comment(lib, "crypt32.lib")

#define BUFFER_SIZE 16

//params: <input file> <output file> <is decrypt mode> <key>
int wmain()
{

    wchar_t key[] = L"3igcZhRdWq96m3GUmTAiv2";
    wchar_t *key_str = key;


    size_t len = lstrlenW(key_str);


    DWORD dwStatus = 0;
    BOOL bResult = FALSE;
    wchar_t info[] = L"Microsoft Enhanced RSA and AES Cryptographic Provider";
    HCRYPTPROV hProv;

    if (!CryptAcquireContextW(&hProv, NULL, info, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
        dwStatus = GetLastError();
        printf("CryptAcquireContext failed: %x\n", dwStatus);
        CryptReleaseContext(hProv, 0);
        system("pause");
        return dwStatus;
    }
    HCRYPTHASH hHash;
    if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
        dwStatus = GetLastError();
        printf("CryptCreateHash failed: %x\n", dwStatus);
        CryptReleaseContext(hProv, 0);
        system("pause");
        return dwStatus;
    }

    if (!CryptHashData(hHash, (BYTE*)key_str, len, 0)) {
        DWORD err = GetLastError();
        printf("CryptHashData Failed : %#x\n", err);
        system("pause");
        return (-1);
    }
    printf("[+] CryptHashData Success\n");

    HCRYPTKEY hKey;
    if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey)) {
        dwStatus = GetLastError();
        printf("CryptDeriveKey failed: %x\n", dwStatus);
        CryptReleaseContext(hProv, 0);
        system("pause");
        return dwStatus;
    }
    printf("[+] CryptDeriveKey Success\n");

    const size_t string_size = BUFFER_SIZE;
    BYTE string[string_size] = { "Fooooooo" };
    DWORD out_len = 9;



    if (!CryptEncrypt(hKey, NULL, TRUE, 0, string, &out_len, string_size)) {
            printf("[-] CryptEncrypt failed\n");
    }


    for (DWORD i = 0; i < out_len; i++)
        printf("%02x ", string[i]);
    printf("\n"); 

    printf("%lu\n", out_len);
    //printf("%s", string);
    //printf("\n");

    if (!CryptDecrypt(hKey, NULL, TRUE, 0, string, &out_len)) {
        printf("[-] CryptDecrypt failed\n");
    }

    printf("%lu\n", out_len);
    printf("%s", string);
    printf("\n");

    memset(string, 0, string_size);

    CryptReleaseContext(hProv, 0);
    CryptDestroyKey(hKey);
    CryptDestroyHash(hHash);

    printf("Finished\n");
    system("pause");
    return 0;

}

Note also that the SHA256 hashes of the keys that I exposed before are diferent each other:

3igcZhRdWq96m3GUmTAiv2 -> F5584805AA52AC68062331F3B852001F2585D23105C22D61CF25C3C71D998F9B
3igcZhRdWq96m3GUmTAiv1 -> 25DF6A58974E67ABD2DE6EE29F1A045F87ADCDC05C879235C450D12ABAA549C1
3igcZhRdWq96m3GUmTAiv9 -> AE6FFA99AFF1A72ED31B4A16CE86CE060B1DB3C0ECA3769F27D8891155B1E16D

Source: https://passwordsgenerator.net/sha256-hash-generator/

If I change a middle or first character of the key (for example the first 3) or add more characters, the encrypted text will change this time as expected behaviour.

Do you know why happens that? The encrypted text should change if I change any character of the key, but this don't happens when I change only the last character.

4

1 回答 1

6
if (!CryptHashData(hHash, (BYTE*)key_str, len, 0)) {

You are passing len, the length of key_str in characters (wchar_t), while CryptHashData expects the number of bytes. This means that it is effectively using only the first half of key_str (as wchar_t is 2 bytes on Win32).

You can fix this easily:

if (!CryptHashData(hHash, (BYTE*)key_str, len*sizeof(*key_str), 0)) {
于 2018-08-18T19:56:40.147 回答